]> git.saurik.com Git - apple/dyld.git/blob - testing/test-cases/thread-local-atexit-macOS.dtest/main.cpp
598911551b8b35279f50b0f67c3242eb31e3904b
[apple/dyld.git] / testing / test-cases / thread-local-atexit-macOS.dtest / main.cpp
1 // BUILD_ONLY: MacOSX
2
3 // BUILD: $CXX main.cpp -std=c++11 -o $BUILD_DIR/thread-local-atexit-macOS.exe
4
5 // RUN: ./thread-local-atexit-macOS.exe
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <pthread.h>
10
11 // We create an A and a B.
12 // While destroying B we create a C
13 // Given that tlv_finalize has "destroy in reverse order of construction", we
14 // must then immediately destroy C before we destroy A to maintain that invariant
15
16 enum State {
17 None,
18 ConstructedA,
19 ConstructedB,
20 ConstructedC,
21 DestroyingB,
22 DestroyedA,
23 DestroyedB,
24 DestroyedC,
25 };
26
27 struct A {
28 A();
29 ~A();
30 };
31
32 struct B {
33 B();
34 ~B();
35 };
36
37 struct C {
38 C();
39 ~C();
40 };
41
42 State state;
43
44 A::A() {
45 if ( state != None ) {
46 printf("[FAIL] thread-local-atexit-macOS: should be in the 'None' state\n");
47 }
48 state = ConstructedA;
49 }
50
51 B::B() {
52 if ( state != ConstructedA ) {
53 printf("[FAIL] thread-local-atexit-macOS: should be in the 'ConstructedA' state\n");
54 _Exit(0);
55 }
56 state = ConstructedB;
57 }
58
59 C::C() {
60 // We construct C during B's destructor
61 if ( state != DestroyingB ) {
62 printf("[FAIL] thread-local-atexit-macOS: should be in the 'DestroyingB' state\n");
63 _Exit(0);
64 }
65 state = ConstructedC;
66 }
67
68 // We destroy B first
69 B::~B() {
70 if ( state != ConstructedB ) {
71 printf("[FAIL] thread-local-atexit-macOS: should be in the 'ConstructedB' state\n");
72 _Exit(0);
73 }
74 state = DestroyingB;
75 static thread_local C c;
76 if ( state != ConstructedC ) {
77 printf("[FAIL] thread-local-atexit-macOS: should be in the 'ConstructedC' state\n");
78 _Exit(0);
79 }
80 state = DestroyedB;
81 }
82
83 // Then we destroy C
84 C::~C() {
85 if ( state != DestroyedB ) {
86 printf("[FAIL] thread-local-atexit-macOS: should be in the 'DestroyedB' state\n");
87 _Exit(0);
88 }
89 state = DestroyedC;
90 }
91
92 // And finally destroy A
93 A::~A() {
94 if ( state != DestroyedC ) {
95 printf("[FAIL] thread-local-atexit-macOS: should be in the 'DestroyedC' state\n");
96 _Exit(0);
97 }
98 state = DestroyedA;
99 printf("[PASS] thread-local-atexit-macOS\n");
100 }
101
102 static void work()
103 {
104 thread_local A a = {};
105 thread_local B b = {};
106 }
107
108 int main() {
109 printf("[BEGIN] thread-local-atexit-macOS\n");
110
111 work();
112
113 return 0;
114 }
115