78 lines · plain
1// RUN: %clangxx_tsan %s -o %t -framework Foundation2// RUN: %run %t 2>&1 | FileCheck %s3 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 = 100000075// CHECK: destructor_counter = 100076// CHECK: Done.77// CHECK-NOT: WARNING: ThreadSanitizer78