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
32 static int seq;
33
34 class OrderChecker {
35 public:
OrderChecker(int n)36 explicit OrderChecker(int n) : n_{n} { }
37
~OrderChecker()38 ~OrderChecker() {
39 if (seq != n_) {
40 printf("Unexpected sequence point: %d\n", 3);
41 _Exit(1);
42 }
43 ++seq;
44 }
45
46 private:
47 int n_;
48 };
49
50 template <int ID>
51 class CreatesThreadLocalInDestructor {
52 public:
~CreatesThreadLocalInDestructor()53 ~CreatesThreadLocalInDestructor() {
54 thread_local OrderChecker checker{ID};
55 }
56 };
57
58 OrderChecker global{7};
59
thread_fn()60 void 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
main()67 int 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