mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-08-02 14:14:27 +02:00
Split sp_counted_base into no threads (nt), win32 lock-free (w32) and pthreads (pt)
[SVN r27729]
This commit is contained in:
@@ -10,8 +10,7 @@
|
|||||||
//
|
//
|
||||||
// detail/sp_counted_base.hpp
|
// detail/sp_counted_base.hpp
|
||||||
//
|
//
|
||||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
// Copyright 2005 Peter Dimov
|
||||||
// Copyright 2004-2005 Peter Dimov
|
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
// Distributed under the Boost Software License, Version 1.0. (See
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
// accompanying file LICENSE_1_0.txt or copy at
|
||||||
@@ -19,125 +18,28 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/detail/lightweight_mutex.hpp>
|
|
||||||
|
|
||||||
#include <typeinfo>
|
#if defined( BOOST_SP_DISABLE_THREADS )
|
||||||
|
|
||||||
namespace boost
|
# include <boost/detail/sp_counted_base_nt.hpp>
|
||||||
{
|
|
||||||
|
|
||||||
namespace detail
|
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
|
||||||
{
|
|
||||||
|
|
||||||
class sp_counted_base
|
# include <boost/detail/sp_counted_base_w32.hpp>
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
typedef detail::lightweight_mutex mutex_type;
|
#elif !defined( BOOST_HAS_THREADS )
|
||||||
|
|
||||||
sp_counted_base( sp_counted_base const & );
|
# include <boost/detail/sp_counted_base_nt.hpp>
|
||||||
sp_counted_base & operator= ( sp_counted_base const & );
|
|
||||||
|
|
||||||
long use_count_; // #shared
|
#elif defined( BOOST_HAS_PTHREADS )
|
||||||
long weak_count_; // #weak + (#shared != 0)
|
|
||||||
|
# include <boost/detail/sp_counted_base_pt.hpp>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Use #define BOOST_DISABLE_THREADS to avoid the error
|
||||||
|
# error Unrecognized threading platform
|
||||||
|
|
||||||
#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
|
|
||||||
mutable mutex_type mtx_;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~sp_counted_base() // nothrow
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispose() is called when use_count_ drops to zero, to release
|
|
||||||
// the resources managed by *this.
|
|
||||||
|
|
||||||
virtual void dispose() = 0; // nothrow
|
|
||||||
|
|
||||||
// destroy() is called when weak_count_ drops to zero.
|
|
||||||
|
|
||||||
virtual void destroy() // nothrow
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void * get_deleter( std::type_info const & ti ) = 0;
|
|
||||||
|
|
||||||
void add_ref_copy()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_HAS_THREADS)
|
|
||||||
mutex_type::scoped_lock lock(mtx_);
|
|
||||||
#endif
|
|
||||||
++use_count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool add_ref_lock() // true on success
|
|
||||||
{
|
|
||||||
#if defined(BOOST_HAS_THREADS)
|
|
||||||
mutex_type::scoped_lock lock(mtx_);
|
|
||||||
#endif
|
|
||||||
if( use_count_ == 0 ) return false;
|
|
||||||
++use_count_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void release() // nothrow
|
|
||||||
{
|
|
||||||
{
|
|
||||||
#if defined(BOOST_HAS_THREADS)
|
|
||||||
mutex_type::scoped_lock lock(mtx_);
|
|
||||||
#endif
|
|
||||||
long new_use_count = --use_count_;
|
|
||||||
|
|
||||||
if( new_use_count != 0 ) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispose();
|
|
||||||
weak_release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void weak_add_ref() // nothrow
|
|
||||||
{
|
|
||||||
#if defined(BOOST_HAS_THREADS)
|
|
||||||
mutex_type::scoped_lock lock(mtx_);
|
|
||||||
#endif
|
|
||||||
++weak_count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void weak_release() // nothrow
|
|
||||||
{
|
|
||||||
long new_weak_count;
|
|
||||||
|
|
||||||
{
|
|
||||||
#if defined(BOOST_HAS_THREADS)
|
|
||||||
mutex_type::scoped_lock lock(mtx_);
|
|
||||||
#endif
|
|
||||||
new_weak_count = --weak_count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( new_weak_count == 0 )
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long use_count() const // nothrow
|
|
||||||
{
|
|
||||||
#if defined(BOOST_HAS_THREADS)
|
|
||||||
mutex_type::scoped_lock lock(mtx_);
|
|
||||||
#endif
|
|
||||||
return use_count_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
|
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
|
||||||
|
107
include/boost/detail/sp_counted_base_nt.hpp
Normal file
107
include/boost/detail/sp_counted_base_nt.hpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// detail/sp_counted_base_nt.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||||
|
// Copyright 2004-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 <typeinfo>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class sp_counted_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
sp_counted_base( sp_counted_base const & );
|
||||||
|
sp_counted_base & operator= ( sp_counted_base const & );
|
||||||
|
|
||||||
|
long use_count_; // #shared
|
||||||
|
long weak_count_; // #weak + (#shared != 0)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~sp_counted_base() // nothrow
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispose() is called when use_count_ drops to zero, to release
|
||||||
|
// the resources managed by *this.
|
||||||
|
|
||||||
|
virtual void dispose() = 0; // nothrow
|
||||||
|
|
||||||
|
// destroy() is called when weak_count_ drops to zero.
|
||||||
|
|
||||||
|
virtual void destroy() // nothrow
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void * get_deleter( std::type_info const & ti ) = 0;
|
||||||
|
|
||||||
|
void add_ref_copy()
|
||||||
|
{
|
||||||
|
++use_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_ref_lock() // true on success
|
||||||
|
{
|
||||||
|
if( use_count_ == 0 ) return false;
|
||||||
|
++use_count_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() // nothrow
|
||||||
|
{
|
||||||
|
if( --use_count_ == 0 )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
weak_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_add_ref() // nothrow
|
||||||
|
{
|
||||||
|
++weak_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_release() // nothrow
|
||||||
|
{
|
||||||
|
if( --weak_count_ == 0 )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // nothrow
|
||||||
|
{
|
||||||
|
return use_count_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
|
135
include/boost/detail/sp_counted_base_pt.hpp
Normal file
135
include/boost/detail/sp_counted_base_pt.hpp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// detail/sp_counted_base_pt.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||||
|
// Copyright 2004-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 <typeinfo>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class sp_counted_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
sp_counted_base( sp_counted_base const & );
|
||||||
|
sp_counted_base & operator= ( sp_counted_base const & );
|
||||||
|
|
||||||
|
long use_count_; // #shared
|
||||||
|
long weak_count_; // #weak + (#shared != 0)
|
||||||
|
|
||||||
|
pthread_mutex_t m_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||||
|
{
|
||||||
|
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
|
||||||
|
|
||||||
|
#if defined(__hpux) && defined(_DECTHREADS_)
|
||||||
|
pthread_mutex_init( &m_, pthread_mutexattr_default );
|
||||||
|
#else
|
||||||
|
pthread_mutex_init( &m_, 0 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~sp_counted_base() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy( &m_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispose() is called when use_count_ drops to zero, to release
|
||||||
|
// the resources managed by *this.
|
||||||
|
|
||||||
|
virtual void dispose() = 0; // nothrow
|
||||||
|
|
||||||
|
// destroy() is called when weak_count_ drops to zero.
|
||||||
|
|
||||||
|
virtual void destroy() // nothrow
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void * get_deleter( std::type_info const & ti ) = 0;
|
||||||
|
|
||||||
|
void add_ref_copy()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
++use_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_ref_lock() // true on success
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
bool r = use_count_ == 0? false: ( ++use_count_, true );
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
long new_use_count = --use_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
|
||||||
|
if( new_use_count == 0 )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
weak_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_add_ref() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
++weak_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_release() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
long new_weak_count = --weak_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
|
||||||
|
if( new_weak_count == 0 )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
long r = use_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
|
114
include/boost/detail/sp_counted_base_w32.hpp
Normal file
114
include/boost/detail/sp_counted_base_w32.hpp
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// detail/sp_counted_base_w32.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||||
|
// Copyright 2004-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)
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Lock-free algorithm by Alexander Terekhov
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/detail/interlocked.hpp>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class sp_counted_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
sp_counted_base( sp_counted_base const & );
|
||||||
|
sp_counted_base & operator= ( sp_counted_base const & );
|
||||||
|
|
||||||
|
long use_count_; // #shared
|
||||||
|
long weak_count_; // #weak + (#shared != 0)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~sp_counted_base() // nothrow
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispose() is called when use_count_ drops to zero, to release
|
||||||
|
// the resources managed by *this.
|
||||||
|
|
||||||
|
virtual void dispose() = 0; // nothrow
|
||||||
|
|
||||||
|
// destroy() is called when weak_count_ drops to zero.
|
||||||
|
|
||||||
|
virtual void destroy() // nothrow
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void * get_deleter( std::type_info const & ti ) = 0;
|
||||||
|
|
||||||
|
void add_ref_copy()
|
||||||
|
{
|
||||||
|
BOOST_INTERLOCKED_INCREMENT( &use_count_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_ref_lock() // true on success
|
||||||
|
{
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
long tmp = static_cast< long const volatile& >( use_count_ );
|
||||||
|
if( tmp == 0 ) return false;
|
||||||
|
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() // nothrow
|
||||||
|
{
|
||||||
|
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
weak_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_add_ref() // nothrow
|
||||||
|
{
|
||||||
|
BOOST_INTERLOCKED_INCREMENT( &weak_count_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_release() // nothrow
|
||||||
|
{
|
||||||
|
if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // nothrow
|
||||||
|
{
|
||||||
|
return static_cast<long const volatile &>( use_count_ );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
|
@@ -143,19 +143,11 @@ void test(boost::shared_ptr<int> const & pi)
|
|||||||
|
|
||||||
int const m = 16; // threads
|
int const m = 16; // threads
|
||||||
|
|
||||||
#if defined(BOOST_LWM_USE_CRITICAL_SECTION)
|
|
||||||
char const * implementation = "critical section";
|
|
||||||
#elif defined(BOOST_LWM_USE_PTHREADS)
|
|
||||||
char const * implementation = "pthread_mutex";
|
|
||||||
#else
|
|
||||||
char const * implementation = "spinlock";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
using namespace std; // printf, clock_t, clock
|
using namespace std; // printf, clock_t, clock
|
||||||
|
|
||||||
printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n);
|
printf("%s: %d threads, %d iterations: ", title, m, n);
|
||||||
|
|
||||||
boost::shared_ptr<int> pi(new int(42));
|
boost::shared_ptr<int> pi(new int(42));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user