• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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