1/*
2 * Copyright (c) 2016 Tavian Barnes. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
14 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
15 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23 * POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__RCSID("$NetBSD: h_thread_local_dtor.cpp,v 1.1 2017/07/11 15:21:36 joerg Exp $");
28
29#include <cstdlib>
30#include <thread>
31
32static int seq;
33
34class OrderChecker {
35public:
36  explicit OrderChecker(int n) : n_{n} { }
37
38  ~OrderChecker() {
39    if (seq != n_) {
40      printf("Unexpected sequence point: %d\n", 3);
41      _Exit(1);
42    }
43    ++seq;
44  }
45
46private:
47  int n_;
48};
49
50template <int ID>
51class CreatesThreadLocalInDestructor {
52public:
53  ~CreatesThreadLocalInDestructor() {
54    thread_local OrderChecker checker{ID};
55  }
56};
57
58OrderChecker global{7};
59
60void thread_fn() {
61  static OrderChecker fn_static{5};
62  thread_local CreatesThreadLocalInDestructor<2> creates_tl2;
63  thread_local OrderChecker fn_thread_local{1};
64  thread_local CreatesThreadLocalInDestructor<0> creates_tl0;
65}
66
67int main() {
68  static OrderChecker fn_static{6};
69
70  std::thread{thread_fn}.join();
71  if (seq != 3) {
72    printf("Unexpected sequence point: %d\n", 3);
73    _Exit(1);
74  }
75
76  thread_local OrderChecker fn_thread_local{4};
77  thread_local CreatesThreadLocalInDestructor<3> creates_tl;
78
79  return 0;
80}
81