1 // RUN: %clangxx_tsan %s -o %t -framework Foundation
2 // RUN: %run %t 2>&1 | FileCheck %s
4 #import <Foundation/Foundation.h>
11 std::atomic<long> shared_call_counter(0);
12 std::atomic<long> weak_call_counter(0);
13 std::atomic<long> destructor_counter(0);
14 std::atomic<long> weak_destroyed_counter(0);
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);
23 virtual void weak_call() {
24 std::atomic_fetch_add_explicit(&weak_call_counter, 1, std::memory_order_relaxed);
27 long n = self_counter;
29 std::atomic_fetch_add_explicit(&destructor_counter, 1, std::memory_order_relaxed);
33 int main(int argc, const char *argv[]) {
34 std::fprintf(stderr, "Hello world.\n");
36 dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
38 dispatch_group_t g = dispatch_group_create();
40 for (int i = 0; i < 1000; i++) {
41 std::shared_ptr<MyStruct> shared(new MyStruct());
42 std::weak_ptr<MyStruct> weak(shared);
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();
50 dispatch_group_async(g, q, ^{
51 for (int j = 0; j < 1000; j++) {
52 std::shared_ptr<MyStruct> weak_copy = weak.lock();
54 weak_copy->weak_call();
56 std::atomic_fetch_add_explicit(&weak_destroyed_counter, 1, std::memory_order_relaxed);
63 dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
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());
70 std::fprintf(stderr, "Done.\n");
73 // CHECK: Hello world.
74 // CHECK: shared_call_counter = 1000000
75 // CHECK: destructor_counter = 1000
77 // CHECK-NOT: WARNING: ThreadSanitizer