From 774a8d330cc4ccf0000c30e28216a9318a82f6e0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 10:41:24 +0000 Subject: [PATCH] Merged 44595, 44638, 44707, 44711, 44728 from trunk to release [SVN r47341] --- include/boost/detail/shared_count.hpp | 27 +++-- include/boost/detail/yield_k.hpp | 6 +- include/boost/shared_ptr.hpp | 8 +- test/shared_ptr_mt_test.cpp | 143 +++++--------------------- test/weak_ptr_mt_test.cpp | 132 ++++-------------------- 5 files changed, 76 insertions(+), 240 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 1eae671..2745649 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -28,8 +28,11 @@ #include #include #include - -#include // std::auto_ptr +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr #include // std::less #include // std::bad_alloc @@ -321,9 +324,13 @@ public: weak_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } return *this; } @@ -331,9 +338,13 @@ public: weak_count & operator= (weak_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } return *this; } diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index d856d57..0d964a7 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -111,7 +111,11 @@ inline void yield( unsigned k ) } else { - struct timespec rqtp = { 0 }; + // g++ -Wextra warns on {} or {0} + struct timespec rqtp = { 0, 0 }; + + // POSIX says that timespec has tv_sec and tv_nsec + // But it doesn't guarantee order or placement rqtp.tv_sec = 0; rqtp.tv_nsec = 1000; diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6f4d49a..b6af46d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -20,7 +20,11 @@ #include #else -#include // for std::auto_ptr +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr #include #include @@ -573,7 +577,7 @@ template inline T * get_pointer(shared_ptr const & p) #if !defined(BOOST_NO_IOSTREAM) -#if defined(__GNUC__) && (__GNUC__ < 3) +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) { diff --git a/test/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp index fa31894..50a9f51 100644 --- a/test/shared_ptr_mt_test.cpp +++ b/test/shared_ptr_mt_test.cpp @@ -7,167 +7,76 @@ #pragma warning(disable: 4514) // unreferenced inline removed #endif -// // shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 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) -// +// 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 -// '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."); -} +#include // int const n = 1024 * 1024; -void test(boost::shared_ptr const & pi) +void test( boost::shared_ptr const & pi ) { std::vector< boost::shared_ptr > v; - for(int i = 0; i < n; ++i) + for( int i = 0; i < n; ++i ) { - v.push_back(pi); + v.push_back( pi ); } } int const m = 16; // threads +#if defined( BOOST_HAS_PTHREADS ) + +char const * thmodel = "POSIX"; + +#else + +char const * thmodel = "Windows"; + +#endif + int main() { using namespace std; // printf, clock_t, clock - printf("%s: %d threads, %d iterations: ", title, m, n); + printf( "Using %s threads: %d threads, %d iterations: ", thmodel, m, n ); - boost::shared_ptr pi(new int(42)); + boost::shared_ptr pi( new int(42) ); clock_t t = clock(); - pthread_t a[m]; + pthread_t a[ m ]; - for(int i = 0; i < m; ++i) + for( int i = 0; i < m; ++i ) { - a[i] = createThread( boost::bind(test, pi) ); + boost::detail::lw_thread_create( a[ i ], boost::bind( test, pi ) ); } - for(int j = 0; j < m; ++j) + for( int j = 0; j < m; ++j ) { - pthread_join(a[j], 0); + pthread_join( a[j], 0 ); } t = clock() - t; - printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + printf( "\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC ); return 0; } diff --git a/test/weak_ptr_mt_test.cpp b/test/weak_ptr_mt_test.cpp index 442c591..04439e6 100644 --- a/test/weak_ptr_mt_test.cpp +++ b/test/weak_ptr_mt_test.cpp @@ -7,128 +7,26 @@ #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) +// Copyright 2005, 2008 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."); -} +#include // @@ -177,11 +75,21 @@ void test( std::vector< boost::shared_ptr > & v ) printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r ); } +#if defined( BOOST_HAS_PTHREADS ) + +char const * thmodel = "POSIX"; + +#else + +char const * thmodel = "Windows"; + +#endif + int main() { using namespace std; // printf, clock_t, clock - printf("%s: %d threads, %d * %d iterations: ", title, m, n, k ); + printf("Using %s threads: %d threads, %d * %d iterations: ", thmodel, m, n, k ); std::vector< boost::shared_ptr > v( k ); @@ -192,16 +100,16 @@ int main() clock_t t = clock(); - pthread_t a[m]; + pthread_t a[ m ]; - for(int i = 0; i < m; ++i) + for( int i = 0; i < m; ++i ) { - a[i] = createThread( boost::bind( test, v ) ); + boost::detail::lw_thread_create( a[ i ], boost::bind( test, v ) ); } v.resize( 0 ); // kill original copies - for(int j = 0; j < m; ++j) + for( int j = 0; j < m; ++j ) { pthread_join( a[j], 0 ); }