forked from boostorg/smart_ptr
Merged 44595, 44638, 44707, 44711, 44728 from trunk to release
[SVN r47341]
This commit is contained in:
@@ -28,8 +28,11 @@
|
|||||||
#include <boost/detail/bad_weak_ptr.hpp>
|
#include <boost/detail/bad_weak_ptr.hpp>
|
||||||
#include <boost/detail/sp_counted_base.hpp>
|
#include <boost/detail/sp_counted_base.hpp>
|
||||||
#include <boost/detail/sp_counted_impl.hpp>
|
#include <boost/detail/sp_counted_impl.hpp>
|
||||||
|
// In order to avoid circular dependencies with Boost.TR1
|
||||||
#include <memory> // std::auto_ptr
|
// we make sure that our include of <memory> doesn't try to
|
||||||
|
// pull in the TR1 headers: that's why we use this header
|
||||||
|
// rather than including <memory> directly:
|
||||||
|
#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
|
||||||
#include <functional> // std::less
|
#include <functional> // std::less
|
||||||
#include <new> // std::bad_alloc
|
#include <new> // std::bad_alloc
|
||||||
|
|
||||||
@@ -321,9 +324,13 @@ public:
|
|||||||
weak_count & operator= (shared_count const & r) // nothrow
|
weak_count & operator= (shared_count const & r) // nothrow
|
||||||
{
|
{
|
||||||
sp_counted_base * tmp = r.pi_;
|
sp_counted_base * tmp = r.pi_;
|
||||||
|
|
||||||
|
if( tmp != pi_ )
|
||||||
|
{
|
||||||
if(tmp != 0) tmp->weak_add_ref();
|
if(tmp != 0) tmp->weak_add_ref();
|
||||||
if(pi_ != 0) pi_->weak_release();
|
if(pi_ != 0) pi_->weak_release();
|
||||||
pi_ = tmp;
|
pi_ = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -331,9 +338,13 @@ public:
|
|||||||
weak_count & operator= (weak_count const & r) // nothrow
|
weak_count & operator= (weak_count const & r) // nothrow
|
||||||
{
|
{
|
||||||
sp_counted_base * tmp = r.pi_;
|
sp_counted_base * tmp = r.pi_;
|
||||||
|
|
||||||
|
if( tmp != pi_ )
|
||||||
|
{
|
||||||
if(tmp != 0) tmp->weak_add_ref();
|
if(tmp != 0) tmp->weak_add_ref();
|
||||||
if(pi_ != 0) pi_->weak_release();
|
if(pi_ != 0) pi_->weak_release();
|
||||||
pi_ = tmp;
|
pi_ = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@@ -111,7 +111,11 @@ inline void yield( unsigned k )
|
|||||||
}
|
}
|
||||||
else
|
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_sec = 0;
|
||||||
rqtp.tv_nsec = 1000;
|
rqtp.tv_nsec = 1000;
|
||||||
|
@@ -20,7 +20,11 @@
|
|||||||
#include <boost/detail/shared_ptr_nmt.hpp>
|
#include <boost/detail/shared_ptr_nmt.hpp>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <memory> // for std::auto_ptr
|
// In order to avoid circular dependencies with Boost.TR1
|
||||||
|
// we make sure that our include of <memory> doesn't try to
|
||||||
|
// pull in the TR1 headers: that's why we use this header
|
||||||
|
// rather than including <memory> directly:
|
||||||
|
#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/checked_delete.hpp>
|
#include <boost/checked_delete.hpp>
|
||||||
@@ -573,7 +577,7 @@ template<class T> inline T * get_pointer(shared_ptr<T> const & p)
|
|||||||
|
|
||||||
#if !defined(BOOST_NO_IOSTREAM)
|
#if !defined(BOOST_NO_IOSTREAM)
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ < 3)
|
#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
|
||||||
|
|
||||||
template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
|
template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
|
||||||
{
|
{
|
||||||
|
@@ -7,125 +7,24 @@
|
|||||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
|
||||||
// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
|
// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
|
||||||
//
|
//
|
||||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||||
|
// Copyright (c) 2008 Peter Dimov
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
// See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt
|
||||||
//
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
// 'portable' thread framework
|
#include <boost/detail/lightweight_thread.hpp>
|
||||||
|
|
||||||
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 <windows.h>
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
typedef HANDLE pthread_t;
|
|
||||||
|
|
||||||
unsigned __stdcall common_thread_routine(void * pv)
|
|
||||||
{
|
|
||||||
abstract_thread * pt = static_cast<abstract_thread *>(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 <pthread.h>
|
|
||||||
|
|
||||||
extern "C" void * common_thread_routine(void * pv)
|
|
||||||
{
|
|
||||||
abstract_thread * pt = static_cast<abstract_thread *>(pv);
|
|
||||||
pt->run();
|
|
||||||
delete pt;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
template<class F> class thread: public abstract_thread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit thread(F f): f_(f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
f_();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
F f_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class F> pthread_t createThread(F f)
|
|
||||||
{
|
|
||||||
std::auto_ptr<abstract_thread> p(new thread<F>(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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -143,11 +42,21 @@ void test(boost::shared_ptr<int> const & pi)
|
|||||||
|
|
||||||
int const m = 16; // threads
|
int const m = 16; // threads
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_PTHREADS )
|
||||||
|
|
||||||
|
char const * thmodel = "POSIX";
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
char const * thmodel = "Windows";
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
using namespace std; // printf, clock_t, clock
|
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<int> pi( new int(42) );
|
boost::shared_ptr<int> pi( new int(42) );
|
||||||
|
|
||||||
@@ -157,7 +66,7 @@ int main()
|
|||||||
|
|
||||||
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 )
|
||||||
|
@@ -7,128 +7,26 @@
|
|||||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
|
||||||
// weak_ptr_mt_test.cpp
|
// weak_ptr_mt_test.cpp
|
||||||
//
|
//
|
||||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||||
// Copyright 2005 Peter Dimov
|
// 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)
|
|
||||||
//
|
//
|
||||||
|
// 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 <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/weak_ptr.hpp>
|
#include <boost/weak_ptr.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
// 'portable' thread framework
|
#include <boost/detail/lightweight_thread.hpp>
|
||||||
|
|
||||||
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 <windows.h>
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
typedef HANDLE pthread_t;
|
|
||||||
|
|
||||||
unsigned __stdcall common_thread_routine(void * pv)
|
|
||||||
{
|
|
||||||
abstract_thread * pt = static_cast<abstract_thread *>(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 <pthread.h>
|
|
||||||
|
|
||||||
extern "C" void * common_thread_routine(void * pv)
|
|
||||||
{
|
|
||||||
abstract_thread * pt = static_cast<abstract_thread *>(pv);
|
|
||||||
pt->run();
|
|
||||||
delete pt;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
template<class F> class thread: public abstract_thread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit thread(F f): f_(f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
f_();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
F f_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class F> pthread_t createThread(F f)
|
|
||||||
{
|
|
||||||
std::auto_ptr<abstract_thread> p(new thread<F>(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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -177,11 +75,21 @@ void test( std::vector< boost::shared_ptr<int> > & v )
|
|||||||
printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r );
|
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()
|
int main()
|
||||||
{
|
{
|
||||||
using namespace std; // printf, clock_t, clock
|
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<int> > v( k );
|
std::vector< boost::shared_ptr<int> > v( k );
|
||||||
|
|
||||||
@@ -196,7 +104,7 @@ int main()
|
|||||||
|
|
||||||
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
|
v.resize( 0 ); // kill original copies
|
||||||
|
Reference in New Issue
Block a user