1 | // RUN: %clangxx_tsan %s %link_libcxx_tsan -o %t |
2 | // RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer' |
3 | |
4 | #include <dispatch/dispatch.h> |
5 | |
6 | #include <atomic> |
7 | #include <cstdio> |
8 | #include <memory> |
9 | |
10 | std::atomic<long> destructor_counter(0); |
11 | |
12 | struct MyStruct { |
13 | virtual ~MyStruct() { |
14 | usleep(10000); |
15 | std::atomic_fetch_add_explicit(&destructor_counter, 1, std::memory_order_relaxed); |
16 | } |
17 | }; |
18 | |
19 | int main(int argc, const char *argv[]) { |
20 | std::fprintf(stderr, "Hello world.\n" ); |
21 | |
22 | dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); |
23 | dispatch_group_t g = dispatch_group_create(); |
24 | |
25 | for (int i = 0; i < 100; i++) { |
26 | std::shared_ptr<MyStruct> shared(new MyStruct()); |
27 | |
28 | dispatch_group_async(g, q, ^{ |
29 | shared.get(); // just to make sure the object is captured by the block |
30 | }); |
31 | } |
32 | |
33 | dispatch_group_wait(g, DISPATCH_TIME_FOREVER); |
34 | |
35 | if (destructor_counter != 100) { |
36 | std::abort(); |
37 | } |
38 | |
39 | std::fprintf(stderr, "Done.\n" ); |
40 | } |
41 | |
42 | // CHECK: Hello world. |
43 | // CHECK: Done. |
44 | |