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