From 1942b647518522fa3ae3295f6a8e92a13137f31b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 19:35:58 +0000 Subject: [PATCH] weak_ptr_mt_test.cpp added. [SVN r27938] --- test/weak_ptr_mt_test.cpp | 214 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 test/weak_ptr_mt_test.cpp diff --git a/test/weak_ptr_mt_test.cpp b/test/weak_ptr_mt_test.cpp new file mode 100644 index 0000000..442c591 --- /dev/null +++ b/test/weak_ptr_mt_test.cpp @@ -0,0 +1,214 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// weak_ptr_mt_test.cpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +// 'portable' thread framework + +class abstract_thread +{ +public: + + virtual ~abstract_thread() {} + virtual void run() = 0; +}; + +#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) + +char const * title = "Using Windows threads"; + +#include +#include + +typedef HANDLE pthread_t; + +unsigned __stdcall common_thread_routine(void * pv) +{ + abstract_thread * pt = static_cast(pv); + pt->run(); + delete pt; + return 0; +} + +int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg) +{ + HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0); + + if(h != 0) + { + *thread = h; + return 0; + } + else + { + return 1; // return errno; + } +} + +int pthread_join(pthread_t thread, void ** /*value_ptr*/) +{ + ::WaitForSingleObject(thread, INFINITE); + ::CloseHandle(thread); + return 0; +} + +#else + +char const * title = "Using POSIX threads"; + +#include + +extern "C" void * common_thread_routine(void * pv) +{ + abstract_thread * pt = static_cast(pv); + pt->run(); + delete pt; + return 0; +} + +#endif + +// + +template class thread: public abstract_thread +{ +public: + + explicit thread(F f): f_(f) + { + } + + void run() + { + f_(); + } + +private: + + F f_; +}; + +template pthread_t createThread(F f) +{ + std::auto_ptr p(new thread(f)); + + pthread_t r; + + if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0) + { + p.release(); + return r; + } + + throw std::runtime_error("createThread failed."); +} + +// + +int const n = 16384; +int const k = 512; // vector size +int const m = 16; // threads + +void test( std::vector< boost::shared_ptr > & v ) +{ + using namespace std; // printf, rand + + std::vector< boost::weak_ptr > w( v.begin(), v.end() ); + + int s = 0, f = 0, r = 0; + + for( int i = 0; i < n; ++i ) + { + // randomly kill a pointer + + v[ rand() % k ].reset(); + ++s; + + for( int j = 0; j < k; ++j ) + { + if( boost::shared_ptr px = w[ j ].lock() ) + { + ++s; + + if( rand() & 4 ) + { + continue; + } + + // rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention + ++f; + } + else + { + ++r; + } + + w[ j ] = v[ rand() % k ]; + } + } + + printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r ); +} + +int main() +{ + using namespace std; // printf, clock_t, clock + + printf("%s: %d threads, %d * %d iterations: ", title, m, n, k ); + + std::vector< boost::shared_ptr > v( k ); + + for( int i = 0; i < k; ++i ) + { + v[ i ].reset( new int( 0 ) ); + } + + clock_t t = clock(); + + pthread_t a[m]; + + for(int i = 0; i < m; ++i) + { + a[i] = createThread( boost::bind( test, v ) ); + } + + v.resize( 0 ); // kill original copies + + for(int j = 0; j < m; ++j) + { + pthread_join( a[j], 0 ); + } + + t = clock() - t; + + printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + + return 0; +}