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