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