1e32f8626804ace131a11b074784f335af71e2299bart/*
2e32f8626804ace131a11b074784f335af71e2299bart * Test program that illustrates how to annotate a smart pointer
3e32f8626804ace131a11b074784f335af71e2299bart * implementation.  In a multithreaded program the following is relevant when
4e32f8626804ace131a11b074784f335af71e2299bart * working with smart pointers:
5e32f8626804ace131a11b074784f335af71e2299bart * - whether or not the objects pointed at are shared over threads.
6e32f8626804ace131a11b074784f335af71e2299bart * - whether or not the methods of the objects pointed at are thread-safe.
7e32f8626804ace131a11b074784f335af71e2299bart * - whether or not the smart pointer objects are shared over threads.
8e32f8626804ace131a11b074784f335af71e2299bart * - whether or not the smart pointer object itself is thread-safe.
9e32f8626804ace131a11b074784f335af71e2299bart *
10e32f8626804ace131a11b074784f335af71e2299bart * Most smart pointer implemenations are not thread-safe
11e32f8626804ace131a11b074784f335af71e2299bart * (e.g. boost::shared_ptr<>, tr1::shared_ptr<> and the smart_ptr<>
12e32f8626804ace131a11b074784f335af71e2299bart * implementation below). This means that it is not safe to modify a shared
13e32f8626804ace131a11b074784f335af71e2299bart * pointer object that is shared over threads without proper synchronization.
14e32f8626804ace131a11b074784f335af71e2299bart *
15e32f8626804ace131a11b074784f335af71e2299bart * Even for non-thread-safe smart pointers it is possible to have different
16e32f8626804ace131a11b074784f335af71e2299bart * threads access the same object via smart pointers without triggering data
17e32f8626804ace131a11b074784f335af71e2299bart * races on the smart pointer objects.
18e32f8626804ace131a11b074784f335af71e2299bart *
19e32f8626804ace131a11b074784f335af71e2299bart * A smart pointer implementation guarantees that the destructor of the object
20e32f8626804ace131a11b074784f335af71e2299bart * pointed at is invoked after the last smart pointer that points to that
21e32f8626804ace131a11b074784f335af71e2299bart * object has been destroyed or reset. Data race detection tools cannot detect
22e32f8626804ace131a11b074784f335af71e2299bart * this ordering without explicit annotation for smart pointers that track
23e32f8626804ace131a11b074784f335af71e2299bart * references without invoking synchronization operations recognized by data
24e32f8626804ace131a11b074784f335af71e2299bart * race detection tools.
25e32f8626804ace131a11b074784f335af71e2299bart */
26e32f8626804ace131a11b074784f335af71e2299bart
27e32f8626804ace131a11b074784f335af71e2299bart
28e32f8626804ace131a11b074784f335af71e2299bart#include <cassert>     // assert()
29e32f8626804ace131a11b074784f335af71e2299bart#include <climits>     // PTHREAD_STACK_MIN
305530f5f35830ab84a42a69e01f7762666813b75dbart#include <iostream>    // std::cerr
31e32f8626804ace131a11b074784f335af71e2299bart#include <stdlib.h>    // atoi()
326b9b1b034ede58bbc7eff24f67c8ba3704a7224abart#include <vector>
33c710de6053e28508b4d49065f50bf10e4861b508bart#ifdef _WIN32
34e32f8626804ace131a11b074784f335af71e2299bart#include <process.h>   // _beginthreadex()
35e32f8626804ace131a11b074784f335af71e2299bart#include <windows.h>   // CRITICAL_SECTION
36c710de6053e28508b4d49065f50bf10e4861b508bart#else
37e32f8626804ace131a11b074784f335af71e2299bart#include <pthread.h>   // pthread_mutex_t
38c710de6053e28508b4d49065f50bf10e4861b508bart#endif
395530f5f35830ab84a42a69e01f7762666813b75dbart#include "unified_annotations.h"
405530f5f35830ab84a42a69e01f7762666813b75dbart
415530f5f35830ab84a42a69e01f7762666813b75dbart
4219aa39213866b6a26674d1f002a58531db53c5cabartstatic bool s_enable_annotations;
43e32f8626804ace131a11b074784f335af71e2299bart
44c710de6053e28508b4d49065f50bf10e4861b508bart
45c710de6053e28508b4d49065f50bf10e4861b508bart#ifdef _WIN32
46e32f8626804ace131a11b074784f335af71e2299bart
47c710de6053e28508b4d49065f50bf10e4861b508bartclass AtomicInt32
48c710de6053e28508b4d49065f50bf10e4861b508bart{
49c710de6053e28508b4d49065f50bf10e4861b508bartpublic:
50c710de6053e28508b4d49065f50bf10e4861b508bart  AtomicInt32(const int value = 0) : m_value(value) { }
51c710de6053e28508b4d49065f50bf10e4861b508bart  ~AtomicInt32() { }
52c710de6053e28508b4d49065f50bf10e4861b508bart  LONG operator++() { return InterlockedIncrement(&m_value); }
53c710de6053e28508b4d49065f50bf10e4861b508bart  LONG operator--() { return InterlockedDecrement(&m_value); }
54c710de6053e28508b4d49065f50bf10e4861b508bart
55c710de6053e28508b4d49065f50bf10e4861b508bartprivate:
56c710de6053e28508b4d49065f50bf10e4861b508bart  volatile LONG m_value;
57c710de6053e28508b4d49065f50bf10e4861b508bart};
58c710de6053e28508b4d49065f50bf10e4861b508bart
59c710de6053e28508b4d49065f50bf10e4861b508bartclass Mutex
60c710de6053e28508b4d49065f50bf10e4861b508bart{
61c710de6053e28508b4d49065f50bf10e4861b508bartpublic:
62c710de6053e28508b4d49065f50bf10e4861b508bart  Mutex() : m_mutex()
63c710de6053e28508b4d49065f50bf10e4861b508bart  { InitializeCriticalSection(&m_mutex); }
64c710de6053e28508b4d49065f50bf10e4861b508bart  ~Mutex()
65c710de6053e28508b4d49065f50bf10e4861b508bart  { DeleteCriticalSection(&m_mutex); }
66c710de6053e28508b4d49065f50bf10e4861b508bart  void Lock()
67c710de6053e28508b4d49065f50bf10e4861b508bart  { EnterCriticalSection(&m_mutex); }
68c710de6053e28508b4d49065f50bf10e4861b508bart  void Unlock()
69c710de6053e28508b4d49065f50bf10e4861b508bart  { LeaveCriticalSection(&m_mutex); }
70c710de6053e28508b4d49065f50bf10e4861b508bart
71c710de6053e28508b4d49065f50bf10e4861b508bartprivate:
72c710de6053e28508b4d49065f50bf10e4861b508bart  CRITICAL_SECTION m_mutex;
73c710de6053e28508b4d49065f50bf10e4861b508bart};
74c710de6053e28508b4d49065f50bf10e4861b508bart
75c710de6053e28508b4d49065f50bf10e4861b508bartclass Thread
76c710de6053e28508b4d49065f50bf10e4861b508bart{
77c710de6053e28508b4d49065f50bf10e4861b508bartpublic:
78c710de6053e28508b4d49065f50bf10e4861b508bart  Thread() : m_thread(INVALID_HANDLE_VALUE) { }
79c710de6053e28508b4d49065f50bf10e4861b508bart  ~Thread() { }
80c710de6053e28508b4d49065f50bf10e4861b508bart  void Create(void* (*pf)(void*), void* arg)
81c710de6053e28508b4d49065f50bf10e4861b508bart  {
82e32f8626804ace131a11b074784f335af71e2299bart    WrapperArgs* wrapper_arg_p = new WrapperArgs(pf, arg);
83e32f8626804ace131a11b074784f335af71e2299bart    m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, wrapper,
84e32f8626804ace131a11b074784f335af71e2299bart						       wrapper_arg_p, 0, NULL));
85c710de6053e28508b4d49065f50bf10e4861b508bart  }
86c710de6053e28508b4d49065f50bf10e4861b508bart  void Join()
87c710de6053e28508b4d49065f50bf10e4861b508bart  { WaitForSingleObject(m_thread, INFINITE); }
88c710de6053e28508b4d49065f50bf10e4861b508bart
89c710de6053e28508b4d49065f50bf10e4861b508bartprivate:
90e32f8626804ace131a11b074784f335af71e2299bart  struct WrapperArgs
91c710de6053e28508b4d49065f50bf10e4861b508bart  {
92e32f8626804ace131a11b074784f335af71e2299bart    WrapperArgs(void* (*pf)(void*), void* arg) : m_pf(pf), m_arg(arg) { }
93c710de6053e28508b4d49065f50bf10e4861b508bart
94c710de6053e28508b4d49065f50bf10e4861b508bart    void* (*m_pf)(void*);
95c710de6053e28508b4d49065f50bf10e4861b508bart    void* m_arg;
96c710de6053e28508b4d49065f50bf10e4861b508bart  };
97c710de6053e28508b4d49065f50bf10e4861b508bart  static unsigned int __stdcall wrapper(void* arg)
98c710de6053e28508b4d49065f50bf10e4861b508bart  {
99e32f8626804ace131a11b074784f335af71e2299bart    WrapperArgs* wrapper_arg_p = reinterpret_cast<WrapperArgs*>(arg);
100e32f8626804ace131a11b074784f335af71e2299bart    WrapperArgs wa = *wrapper_arg_p;
101c710de6053e28508b4d49065f50bf10e4861b508bart    delete wrapper_arg_p;
102c710de6053e28508b4d49065f50bf10e4861b508bart    return reinterpret_cast<unsigned>((wa.m_pf)(wa.m_arg));
103c710de6053e28508b4d49065f50bf10e4861b508bart  }
104c710de6053e28508b4d49065f50bf10e4861b508bart  HANDLE m_thread;
105c710de6053e28508b4d49065f50bf10e4861b508bart};
106e32f8626804ace131a11b074784f335af71e2299bart
107c710de6053e28508b4d49065f50bf10e4861b508bart#else // _WIN32
108e32f8626804ace131a11b074784f335af71e2299bart
109c710de6053e28508b4d49065f50bf10e4861b508bartclass AtomicInt32
110c710de6053e28508b4d49065f50bf10e4861b508bart{
111c710de6053e28508b4d49065f50bf10e4861b508bartpublic:
112c710de6053e28508b4d49065f50bf10e4861b508bart  AtomicInt32(const int value = 0) : m_value(value) { }
113c710de6053e28508b4d49065f50bf10e4861b508bart  ~AtomicInt32() { }
114c710de6053e28508b4d49065f50bf10e4861b508bart  int operator++() { return __sync_add_and_fetch(&m_value, 1); }
115c710de6053e28508b4d49065f50bf10e4861b508bart  int operator--() { return __sync_sub_and_fetch(&m_value, 1); }
116c710de6053e28508b4d49065f50bf10e4861b508bartprivate:
117c710de6053e28508b4d49065f50bf10e4861b508bart  volatile int m_value;
118c710de6053e28508b4d49065f50bf10e4861b508bart};
119c710de6053e28508b4d49065f50bf10e4861b508bart
120c710de6053e28508b4d49065f50bf10e4861b508bartclass Mutex
121c710de6053e28508b4d49065f50bf10e4861b508bart{
122c710de6053e28508b4d49065f50bf10e4861b508bartpublic:
123c710de6053e28508b4d49065f50bf10e4861b508bart  Mutex() : m_mutex()
124c710de6053e28508b4d49065f50bf10e4861b508bart  { pthread_mutex_init(&m_mutex, NULL); }
125c710de6053e28508b4d49065f50bf10e4861b508bart  ~Mutex()
126c710de6053e28508b4d49065f50bf10e4861b508bart  { pthread_mutex_destroy(&m_mutex); }
127c710de6053e28508b4d49065f50bf10e4861b508bart  void Lock()
128c710de6053e28508b4d49065f50bf10e4861b508bart  { pthread_mutex_lock(&m_mutex); }
129c710de6053e28508b4d49065f50bf10e4861b508bart  void Unlock()
130c710de6053e28508b4d49065f50bf10e4861b508bart  { pthread_mutex_unlock(&m_mutex); }
131c710de6053e28508b4d49065f50bf10e4861b508bart
132c710de6053e28508b4d49065f50bf10e4861b508bartprivate:
133c710de6053e28508b4d49065f50bf10e4861b508bart  pthread_mutex_t m_mutex;
134c710de6053e28508b4d49065f50bf10e4861b508bart};
135c710de6053e28508b4d49065f50bf10e4861b508bart
136c710de6053e28508b4d49065f50bf10e4861b508bartclass Thread
137c710de6053e28508b4d49065f50bf10e4861b508bart{
138c710de6053e28508b4d49065f50bf10e4861b508bartpublic:
139c710de6053e28508b4d49065f50bf10e4861b508bart  Thread() : m_tid() { }
140c710de6053e28508b4d49065f50bf10e4861b508bart  ~Thread() { }
141c710de6053e28508b4d49065f50bf10e4861b508bart  void Create(void* (*pf)(void*), void* arg)
142e32f8626804ace131a11b074784f335af71e2299bart  {
143e32f8626804ace131a11b074784f335af71e2299bart    pthread_attr_t attr;
144e32f8626804ace131a11b074784f335af71e2299bart    pthread_attr_init(&attr);
145e32f8626804ace131a11b074784f335af71e2299bart    pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 4096);
146e32f8626804ace131a11b074784f335af71e2299bart    pthread_create(&m_tid, &attr, pf, arg);
147e32f8626804ace131a11b074784f335af71e2299bart    pthread_attr_destroy(&attr);
148e32f8626804ace131a11b074784f335af71e2299bart  }
149c710de6053e28508b4d49065f50bf10e4861b508bart  void Join()
150c710de6053e28508b4d49065f50bf10e4861b508bart  { pthread_join(m_tid, NULL); }
151c710de6053e28508b4d49065f50bf10e4861b508bartprivate:
152c710de6053e28508b4d49065f50bf10e4861b508bart  pthread_t m_tid;
153c710de6053e28508b4d49065f50bf10e4861b508bart};
154e32f8626804ace131a11b074784f335af71e2299bart
155e32f8626804ace131a11b074784f335af71e2299bart#endif // !defined(_WIN32)
156c710de6053e28508b4d49065f50bf10e4861b508bart
15721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
15821e49d778a698f3e28ba2ad6b3b0430a26f9255ebarttemplate<class T>
15921e49d778a698f3e28ba2ad6b3b0430a26f9255ebartclass smart_ptr
16021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart{
16121e49d778a698f3e28ba2ad6b3b0430a26f9255ebartpublic:
162c710de6053e28508b4d49065f50bf10e4861b508bart  typedef AtomicInt32 counter_t;
16321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
16421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  template <typename Q> friend class smart_ptr;
16521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
16621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  explicit smart_ptr()
16721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    : m_ptr(NULL), m_count_ptr(NULL)
16821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  { }
16921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
17021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  explicit smart_ptr(T* const pT)
17121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    : m_ptr(NULL), m_count_ptr(NULL)
17221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
17321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(pT, pT ? new counter_t(0) : NULL);
17421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
17521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
17621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  template <typename Q>
17721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  explicit smart_ptr(Q* const q)
17821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    : m_ptr(NULL), m_count_ptr(NULL)
17921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
18021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(q, q ? new counter_t(0) : NULL);
18121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
18221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
18321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  ~smart_ptr()
18421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
18521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(NULL, NULL);
18621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
18721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
18821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  smart_ptr(const smart_ptr<T>& sp)
18921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    : m_ptr(NULL), m_count_ptr(NULL)
19021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
19121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(sp.m_ptr, sp.m_count_ptr);
19221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
19321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
19421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  template <typename Q>
19521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  smart_ptr(const smart_ptr<Q>& sp)
19621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    : m_ptr(NULL), m_count_ptr(NULL)
19721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
19821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(sp.m_ptr, sp.m_count_ptr);
19921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
20021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
20121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  smart_ptr& operator=(const smart_ptr<T>& sp)
20221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
20321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(sp.m_ptr, sp.m_count_ptr);
20421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    return *this;
20521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
20621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
20721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  smart_ptr& operator=(T* const p)
20821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
20921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(p, p ? new counter_t(0) : NULL);
21021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    return *this;
21121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
21221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
21321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  template <typename Q>
21421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  smart_ptr& operator=(Q* const q)
21521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
21621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    set(q, q ? new counter_t(0) : NULL);
21721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    return *this;
21821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
21921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
22021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  T* operator->() const
22121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
22221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    assert(m_ptr);
22321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    return m_ptr;
22421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
22521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
22621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  T& operator*() const
22721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
22821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    assert(m_ptr);
22921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    return *m_ptr;
23021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
23121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
23221e49d778a698f3e28ba2ad6b3b0430a26f9255ebartprivate:
233c710de6053e28508b4d49065f50bf10e4861b508bart  void set(T* const pT, counter_t* const count_ptr)
23421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
23521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    if (m_ptr != pT)
23621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    {
237e32f8626804ace131a11b074784f335af71e2299bart      if (m_count_ptr)
23821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart      {
2395530f5f35830ab84a42a69e01f7762666813b75dbart	if (s_enable_annotations)
24062049c4c03731f028bb5a29c7cb77bfe68cea193bart	  U_ANNOTATE_HAPPENS_BEFORE(m_count_ptr);
241e32f8626804ace131a11b074784f335af71e2299bart	if (--(*m_count_ptr) == 0)
242e32f8626804ace131a11b074784f335af71e2299bart	{
2435530f5f35830ab84a42a69e01f7762666813b75dbart	  if (s_enable_annotations)
24462049c4c03731f028bb5a29c7cb77bfe68cea193bart	    U_ANNOTATE_HAPPENS_AFTER(m_count_ptr);
245e32f8626804ace131a11b074784f335af71e2299bart	  delete m_ptr;
246e32f8626804ace131a11b074784f335af71e2299bart	  m_ptr = NULL;
247e32f8626804ace131a11b074784f335af71e2299bart	  delete m_count_ptr;
248e32f8626804ace131a11b074784f335af71e2299bart	  m_count_ptr = NULL;
249e32f8626804ace131a11b074784f335af71e2299bart	}
25021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart      }
25121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart      m_ptr = pT;
25221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart      m_count_ptr = count_ptr;
25321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart      if (count_ptr)
254c710de6053e28508b4d49065f50bf10e4861b508bart	++(*m_count_ptr);
25521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    }
25621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
25721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
258c710de6053e28508b4d49065f50bf10e4861b508bart  T*         m_ptr;
259c710de6053e28508b4d49065f50bf10e4861b508bart  counter_t* m_count_ptr;
26021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart};
26121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
26221e49d778a698f3e28ba2ad6b3b0430a26f9255ebartclass counter
26321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart{
26421e49d778a698f3e28ba2ad6b3b0430a26f9255ebartpublic:
26521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  counter()
26621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    : m_mutex(), m_count()
267e32f8626804ace131a11b074784f335af71e2299bart  { }
268e32f8626804ace131a11b074784f335af71e2299bart  ~counter()
26921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
270e32f8626804ace131a11b074784f335af71e2299bart    // Data race detection tools that do not recognize the
271e32f8626804ace131a11b074784f335af71e2299bart    // ANNOTATE_HAPPENS_BEFORE() / ANNOTATE_HAPPENS_AFTER() annotations in the
272e32f8626804ace131a11b074784f335af71e2299bart    // smart_ptr<> implementation will report that the assignment below
273e32f8626804ace131a11b074784f335af71e2299bart    // triggers a data race.
274e32f8626804ace131a11b074784f335af71e2299bart    m_count = -1;
27521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
27621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  int get() const
27721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
27821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    int result;
279c710de6053e28508b4d49065f50bf10e4861b508bart    m_mutex.Lock();
28021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    result = m_count;
281c710de6053e28508b4d49065f50bf10e4861b508bart    m_mutex.Unlock();
28221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    return result;
28321e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
28421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  int post_increment()
28521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  {
28621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    int result;
287c710de6053e28508b4d49065f50bf10e4861b508bart    m_mutex.Lock();
28821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    result = m_count++;
289c710de6053e28508b4d49065f50bf10e4861b508bart    m_mutex.Unlock();
29021e49d778a698f3e28ba2ad6b3b0430a26f9255ebart    return result;
29121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  }
29221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
29321e49d778a698f3e28ba2ad6b3b0430a26f9255ebartprivate:
294c710de6053e28508b4d49065f50bf10e4861b508bart  mutable Mutex m_mutex;
295c710de6053e28508b4d49065f50bf10e4861b508bart  int           m_count;
29621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart};
29721e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
29821e49d778a698f3e28ba2ad6b3b0430a26f9255ebartstatic void* thread_func(void* arg)
29921e49d778a698f3e28ba2ad6b3b0430a26f9255ebart{
300e32f8626804ace131a11b074784f335af71e2299bart  smart_ptr<counter>* pp = reinterpret_cast<smart_ptr<counter>*>(arg);
301e32f8626804ace131a11b074784f335af71e2299bart  (*pp)->post_increment();
302e32f8626804ace131a11b074784f335af71e2299bart  *pp = NULL;
303e32f8626804ace131a11b074784f335af71e2299bart  delete pp;
30421e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  return NULL;
30521e49d778a698f3e28ba2ad6b3b0430a26f9255ebart}
30621e49d778a698f3e28ba2ad6b3b0430a26f9255ebart
30721e49d778a698f3e28ba2ad6b3b0430a26f9255ebartint main(int argc, char** argv)
30821e49d778a698f3e28ba2ad6b3b0430a26f9255ebart{
309e32f8626804ace131a11b074784f335af71e2299bart  const int nthreads = std::max(argc > 1 ? atoi(argv[1]) : 1, 1);
3105530f5f35830ab84a42a69e01f7762666813b75dbart  const int iterations = std::max(argc > 2 ? atoi(argv[2]) : 1, 1);
3115530f5f35830ab84a42a69e01f7762666813b75dbart  s_enable_annotations = argc > 3 ? !!atoi(argv[3]) : true;
3125530f5f35830ab84a42a69e01f7762666813b75dbart
3135530f5f35830ab84a42a69e01f7762666813b75dbart  for (int j = 0; j < iterations; ++j)
3145530f5f35830ab84a42a69e01f7762666813b75dbart  {
3156b9b1b034ede58bbc7eff24f67c8ba3704a7224abart    std::vector<Thread> T(nthreads);
3165530f5f35830ab84a42a69e01f7762666813b75dbart    smart_ptr<counter> p(new counter);
3175530f5f35830ab84a42a69e01f7762666813b75dbart    p->post_increment();
3186b9b1b034ede58bbc7eff24f67c8ba3704a7224abart    for (std::vector<Thread>::iterator q = T.begin(); q != T.end(); q++)
3196b9b1b034ede58bbc7eff24f67c8ba3704a7224abart      q->Create(thread_func, new smart_ptr<counter>(p));
320863f1ebabe3b97854383c27cc708ddeb0c8c7425bart    {
321863f1ebabe3b97854383c27cc708ddeb0c8c7425bart      // Avoid that counter.m_mutex introduces a false ordering on the
322863f1ebabe3b97854383c27cc708ddeb0c8c7425bart      // counter.m_count accesses.
323863f1ebabe3b97854383c27cc708ddeb0c8c7425bart      const timespec delay = { 0, 100 * 1000 * 1000 };
324863f1ebabe3b97854383c27cc708ddeb0c8c7425bart      nanosleep(&delay, 0);
325863f1ebabe3b97854383c27cc708ddeb0c8c7425bart    }
3265530f5f35830ab84a42a69e01f7762666813b75dbart    p = NULL;
3276b9b1b034ede58bbc7eff24f67c8ba3704a7224abart    for (std::vector<Thread>::iterator q = T.begin(); q != T.end(); q++)
3286b9b1b034ede58bbc7eff24f67c8ba3704a7224abart      q->Join();
3295530f5f35830ab84a42a69e01f7762666813b75dbart  }
3305530f5f35830ab84a42a69e01f7762666813b75dbart  std::cerr << "Done.\n";
33121e49d778a698f3e28ba2ad6b3b0430a26f9255ebart  return 0;
33221e49d778a698f3e28ba2ad6b3b0430a26f9255ebart}
333