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