1// RUN: %clangxx_tsan %s -o %t -framework Foundation
2// RUN: %run %t 2>&1 | FileCheck %s
3
4#import <Foundation/Foundation.h>
5
6#import <atomic>
7#import <cassert>
8#import <cstdio>
9#import <memory>
10
11std::atomic<long> shared_call_counter(0);
12std::atomic<long> weak_call_counter(0);
13std::atomic<long> destructor_counter(0);
14std::atomic<long> weak_destroyed_counter(0);
15
16struct MyStruct {
17 std::atomic<long> self_counter;
18 MyStruct() : self_counter(0) { }
19 virtual void shared_call() {
20 std::atomic_fetch_add_explicit(&self_counter, 1, std::memory_order_relaxed);
21 std::atomic_fetch_add_explicit(&shared_call_counter, 1, std::memory_order_relaxed);
22 }
23 virtual void weak_call() {
24 std::atomic_fetch_add_explicit(&weak_call_counter, 1, std::memory_order_relaxed);
25 }
26 virtual ~MyStruct() {
27 long n = self_counter;
28 assert(n == 1000);
29 std::atomic_fetch_add_explicit(&destructor_counter, 1, std::memory_order_relaxed);
30 }
31};
32
33int main(int argc, const char *argv[]) {
34 std::fprintf(stderr, "Hello world.\n");
35
36 dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
37
38 dispatch_group_t g = dispatch_group_create();
39
40 for (int i = 0; i < 1000; i++) {
41 std::shared_ptr<MyStruct> shared(new MyStruct());
42 std::weak_ptr<MyStruct> weak(shared);
43
44 dispatch_group_async(g, q, ^{
45 for (int j = 0; j < 1000; j++) {
46 std::shared_ptr<MyStruct> shared_copy(shared);
47 shared_copy->shared_call();
48 }
49 });
50 dispatch_group_async(g, q, ^{
51 for (int j = 0; j < 1000; j++) {
52 std::shared_ptr<MyStruct> weak_copy = weak.lock();
53 if (weak_copy) {
54 weak_copy->weak_call();
55 } else {
56 std::atomic_fetch_add_explicit(&weak_destroyed_counter, 1, std::memory_order_relaxed);
57 break;
58 }
59 }
60 });
61 }
62
63 dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
64
65 std::fprintf(stderr, "shared_call_counter = %ld\n", shared_call_counter.load());
66 std::fprintf(stderr, "weak_call_counter = %ld\n", weak_call_counter.load());
67 std::fprintf(stderr, "destructor_counter = %ld\n", destructor_counter.load());
68 std::fprintf(stderr, "weak_destroyed_counter = %ld\n", weak_destroyed_counter.load());
69
70 std::fprintf(stderr, "Done.\n");
71}
72
73// CHECK: Hello world.
74// CHECK: shared_call_counter = 1000000
75// CHECK: destructor_counter = 1000
76// CHECK: Done.
77// CHECK-NOT: WARNING: ThreadSanitizer
78

source code of compiler-rt/test/tsan/Darwin/libcxx-shared-ptr-stress.mm