forked from boostorg/smart_ptr
boost::detail::spinlock added.
[SVN r43950]
This commit is contained in:
43
include/boost/detail/spinlock.hpp
Normal file
43
include/boost/detail/spinlock.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// boost/detail/spinlock.hpp
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
// struct spinlock
|
||||||
|
// {
|
||||||
|
// void lock();
|
||||||
|
// bool try_lock();
|
||||||
|
// void unlock();
|
||||||
|
//
|
||||||
|
// class scoped_lock;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// #define BOOST_DETAIL_SPINLOCK_INIT <unspecified>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
|
||||||
|
# include <boost/detail/spinlock_sync.hpp>
|
||||||
|
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||||
|
# include <boost/detail/spinlock_w32.hpp>
|
||||||
|
#elif defined(BOOST_HAS_PTHREADS)
|
||||||
|
# include <boost/detail/spinlock_pt.hpp>
|
||||||
|
#else
|
||||||
|
# error Unrecognized threading platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED
|
79
include/boost/detail/spinlock_pt.hpp
Normal file
79
include/boost/detail/spinlock_pt.hpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
pthread_mutex_t v_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
return pthread_mutex_trylock( &v_ ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &v_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock( &v_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER }
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED
|
83
include/boost/detail/spinlock_sync.hpp
Normal file
83
include/boost/detail/spinlock_sync.hpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/detail/yield_k.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
int v_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
int r = __sync_lock_test_and_set( &v_, 1 );
|
||||||
|
return r == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
for( unsigned k = 0; !try_lock(); ++k )
|
||||||
|
{
|
||||||
|
boost::detail::yield( k );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
__sync_lock_release( &v_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT {0}
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
|
98
include/boost/detail/spinlock_w32.hpp
Normal file
98
include/boost/detail/spinlock_w32.hpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/detail/interlocked.hpp>
|
||||||
|
#include <boost/detail/yield_k.hpp>
|
||||||
|
|
||||||
|
#if defined( _MSC_VER ) && _MSC_VER >= 1310
|
||||||
|
extern "C" void _ReadWriteBarrier();
|
||||||
|
# pragma intrinsic( _ReadWriteBarrier )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
long v_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 );
|
||||||
|
|
||||||
|
#if defined( _MSC_VER ) && _MSC_VER >= 1310
|
||||||
|
_ReadWriteBarrier();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return r == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
for( unsigned k = 0; !try_lock(); ++k )
|
||||||
|
{
|
||||||
|
boost::detail::yield( k );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
#if defined( _MSC_VER ) && _MSC_VER >= 1310
|
||||||
|
_ReadWriteBarrier();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*const_cast< long volatile* >( &v_ ) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT {0}
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED
|
@ -38,5 +38,6 @@ import testing ;
|
|||||||
[ run esft_regtest.cpp ]
|
[ run esft_regtest.cpp ]
|
||||||
[ run esft_constructor_test.cpp ]
|
[ run esft_constructor_test.cpp ]
|
||||||
[ run yield_k_test.cpp ]
|
[ run yield_k_test.cpp ]
|
||||||
|
[ run spinlock_test.cpp ]
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
46
test/spinlock_test.cpp
Normal file
46
test/spinlock_test.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// spinlock_test.cpp
|
||||||
|
//
|
||||||
|
// Copyright 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 <boost/detail/spinlock.hpp>
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
|
||||||
|
// Sanity check only
|
||||||
|
|
||||||
|
static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT;
|
||||||
|
static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
BOOST_TEST( sp.try_lock() );
|
||||||
|
BOOST_TEST( !sp.try_lock() );
|
||||||
|
BOOST_TEST( sp2.try_lock() );
|
||||||
|
BOOST_TEST( !sp.try_lock() );
|
||||||
|
BOOST_TEST( !sp2.try_lock() );
|
||||||
|
sp.unlock();
|
||||||
|
sp2.unlock();
|
||||||
|
|
||||||
|
sp.lock();
|
||||||
|
BOOST_TEST( !sp.try_lock() );
|
||||||
|
sp2.lock();
|
||||||
|
BOOST_TEST( !sp.try_lock() );
|
||||||
|
BOOST_TEST( !sp2.try_lock() );
|
||||||
|
sp.unlock();
|
||||||
|
sp2.unlock();
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::detail::spinlock::scoped_lock lock( sp );
|
||||||
|
BOOST_TEST( !sp.try_lock() );
|
||||||
|
boost::detail::spinlock::scoped_lock lock2( sp2 );
|
||||||
|
BOOST_TEST( !sp.try_lock() );
|
||||||
|
BOOST_TEST( !sp2.try_lock() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
Reference in New Issue
Block a user