From: Bart Van Assche Date: Tue, 2 Mar 2010 08:57:50 +0000 (+0000) Subject: Added the source code of one more unit test. X-Git-Tag: svn/VALGRIND_3_6_0~365 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c7741d5db1bb26551394798332d3dc43505d6025;p=thirdparty%2Fvalgrind.git Added the source code of one more unit test. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11059 --- diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am index a252ec0460..c11a6704a0 100644 --- a/drd/tests/Makefile.am +++ b/drd/tests/Makefile.am @@ -281,8 +281,12 @@ check_PROGRAMS += boost_thread endif if HAVE_BUILTIN_ATOMIC -check_PROGRAMS += annotate_rwlock atomic_var circular_buffer -check_PROGRAMS += tsan_unittest +check_PROGRAMS += \ + annotate_rwlock \ + annotate_smart_pointer \ + atomic_var \ + circular_buffer \ + tsan_unittest endif if HAVE_OPENMP @@ -339,6 +343,10 @@ boost_thread_CXXFLAGS = $(AM_CXXFLAGS) $(BOOST_CFLAGS) boost_thread_LDADD = $(BOOST_LIBS) endif +if HAVE_BUILTIN_ATOMIC +annotate_smart_pointer_SOURCES = annotate_smart_pointer.cpp +endif + if HAVE_OPENMP omp_matinv_CFLAGS = $(AM_CFLAGS) -fopenmp omp_matinv_LDFLAGS = -fopenmp diff --git a/drd/tests/annotate_smart_pointer.cpp b/drd/tests/annotate_smart_pointer.cpp new file mode 100755 index 0000000000..90dd023bbd --- /dev/null +++ b/drd/tests/annotate_smart_pointer.cpp @@ -0,0 +1,162 @@ +#include +#include +#include +#include + +template +class smart_ptr +{ +public: + typedef unsigned counter_t; + + template friend class smart_ptr; + + explicit smart_ptr() + : m_ptr(NULL), m_count_ptr(NULL) + { } + + explicit smart_ptr(T* const pT) + : m_ptr(NULL), m_count_ptr(NULL) + { + set(pT, pT ? new counter_t(0) : NULL); + } + + template + explicit smart_ptr(Q* const q) + : m_ptr(NULL), m_count_ptr(NULL) + { + set(q, q ? new counter_t(0) : NULL); + } + + ~smart_ptr() + { + set(NULL, NULL); + } + + smart_ptr(const smart_ptr& sp) + : m_ptr(NULL), m_count_ptr(NULL) + { + set(sp.m_ptr, sp.m_count_ptr); + } + + template + smart_ptr(const smart_ptr& sp) + : m_ptr(NULL), m_count_ptr(NULL) + { + set(sp.m_ptr, sp.m_count_ptr); + } + + smart_ptr& operator=(const smart_ptr& sp) + { + set(sp.m_ptr, sp.m_count_ptr); + return *this; + } + + smart_ptr& operator=(T* const p) + { + set(p, p ? new counter_t(0) : NULL); + return *this; + } + + template + smart_ptr& operator=(Q* const q) + { + set(q, q ? new counter_t(0) : NULL); + return *this; + } + + T* operator->() const + { + assert(m_ptr); + return m_ptr; + } + + T& operator*() const + { + assert(m_ptr); + return *m_ptr; + } + +private: + void set(T* const pT, volatile counter_t* const count_ptr) + { + if (m_ptr != pT) + { + if (m_count_ptr && __sync_sub_and_fetch(m_count_ptr, 1) == 0) + { + delete m_ptr; + delete m_count_ptr; + } + m_ptr = pT; + m_count_ptr = count_ptr; + if (count_ptr) + __sync_add_and_fetch(count_ptr, 1); + } + } + + T* m_ptr; + volatile counter_t* m_count_ptr; +}; + +class counter +{ +public: + counter() + : m_mutex(), m_count() + { + pthread_mutex_init(&m_mutex, NULL); + } + ~counter() + { + m_count = -1; + pthread_mutex_destroy(&m_mutex); + } + int get() const + { + int result; + pthread_mutex_lock(&m_mutex); + result = m_count; + pthread_mutex_unlock(&m_mutex); + return result; + } + int post_increment() + { + int result; + pthread_mutex_lock(&m_mutex); + result = m_count++; + pthread_mutex_unlock(&m_mutex); + return result; + } + +private: + mutable pthread_mutex_t m_mutex; + int m_count; +}; + +static sem_t s_sem; + +static void* thread_func(void* arg) +{ + smart_ptr p(*reinterpret_cast*>(arg)); + sem_post(&s_sem); + p->post_increment(); + p = NULL; + return NULL; +} + +int main(int argc, char** argv) +{ + smart_ptr p(new counter); + pthread_t tid; + + sem_init(&s_sem, 0, 0); + p->post_increment(); + pthread_create(&tid, NULL, thread_func, &p); + // Wait until the created thread has copied the shared pointer. + sem_wait(&s_sem); + p = NULL; + pthread_join(tid, NULL); + sem_destroy(&s_sem); + std::cout << "Done.\n"; + return 0; +}