mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
8 Commits
boost-1.43
...
boost-1.45
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
935d5249d3 | ||
|
|
4dc1cb1ba1 | ||
|
|
506019dd62 | ||
|
|
e30be60bc4 | ||
|
|
7bfafec128 | ||
|
|
e12d2bc486 | ||
|
|
a37d2a1364 | ||
|
|
cc662c102c |
@@ -43,6 +43,7 @@ project boost/thread
|
||||
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
|
||||
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
|
||||
<tag>@$(__name__).tag
|
||||
<toolset>gcc:<cxxflags>-Wno-long-long
|
||||
: default-build <threading>multi
|
||||
;
|
||||
|
||||
|
||||
@@ -26,11 +26,6 @@ boostbook standalone
|
||||
<xsl:param>generate.section.toc.level=10
|
||||
# Path for links to Boost:
|
||||
<xsl:param>boost.root=../../../..
|
||||
# Path for libraries index:
|
||||
<xsl:param>boost.libraries=../../../../libs/libraries.htm
|
||||
# Use the main Boost stylesheet:
|
||||
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ __thread_id__ yield a total order for every non-equal thread ID.
|
||||
};
|
||||
|
||||
void swap(thread& lhs,thread& rhs);
|
||||
detail::thread_move_t<thread> move(detail::thread_move_t<thread> t);
|
||||
|
||||
[section:default_constructor Default Constructor]
|
||||
|
||||
@@ -234,6 +235,40 @@ __thread_id__ yield a total order for every non-equal thread ID.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_constructor Move Constructor]
|
||||
|
||||
thread(detail::thread_move_t<thread> other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Transfers ownership of the thread managed by `other` (if any) to the newly constructed __thread__ instance.]]
|
||||
|
||||
[[Postconditions:] [`other->get_id()==thread::id()`]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_assignment Move assignment operator]
|
||||
|
||||
thread& operator=(detail::thread_move_t<thread> other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Transfers ownership of the thread managed by `other` (if
|
||||
any) to `*this`. If there was a thread previously associated with
|
||||
`*this` then that thread is detached.]]
|
||||
|
||||
[[Postconditions:] [`other->get_id()==thread::id()`]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:callable_constructor Thread Constructor]
|
||||
|
||||
template<typename Callable>
|
||||
@@ -521,6 +556,26 @@ value as `this->get_id()` prior to the call.]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:non_member_move Non-member function `move()`]
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Returns:] [`t`.]]
|
||||
|
||||
]
|
||||
|
||||
Enables moving thread objects. e.g.
|
||||
|
||||
extern void some_func();
|
||||
boost::thread t(some_func);
|
||||
boost::thread t2(boost::move(t)); // transfer thread from t to t2
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:id Class `boost::thread::id`]
|
||||
|
||||
@@ -756,11 +811,14 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
|
||||
{
|
||||
template<typename TimeDuration>
|
||||
void sleep(TimeDuration const& rel_time);
|
||||
void sleep(system_time const& abs_time)
|
||||
}
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Suspends the current thread until the specified time has elapsed.]]
|
||||
[[Effects:] [Suspends the current thread until the time period
|
||||
specified by `rel_time` has elapsed or the time point specified by
|
||||
`abs_time` has been reached.]]
|
||||
|
||||
[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]
|
||||
|
||||
|
||||
@@ -19,8 +19,14 @@
|
||||
|
||||
#include "platform.hpp"
|
||||
|
||||
// provided for backwards compatibility, since this
|
||||
// macro was used for several releases by mistake.
|
||||
#if defined(BOOST_THREAD_DYN_DLL)
|
||||
# define BOOST_THREAD_DYN_LINK
|
||||
#endif
|
||||
|
||||
// compatibility with the rest of Boost's auto-linking code:
|
||||
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
|
||||
#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
|
||||
# undef BOOST_THREAD_USE_LIB
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
# define BOOST_THREAD_HPUX
|
||||
#elif defined(__CYGWIN__)
|
||||
# define BOOST_THREAD_CYGWIN
|
||||
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||
#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32)
|
||||
# define BOOST_THREAD_WIN32
|
||||
#elif defined(__BEOS__)
|
||||
# define BOOST_THREAD_BEOS
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
// 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)
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
// (C) Copyright 2007-10 Anthony Williams
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#include <ostream>
|
||||
#endif
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
@@ -113,14 +115,13 @@ namespace boost
|
||||
|
||||
void release_handle();
|
||||
|
||||
mutable boost::mutex thread_info_mutex;
|
||||
detail::thread_data_ptr thread_info;
|
||||
|
||||
void start_thread();
|
||||
|
||||
explicit thread(detail::thread_data_ptr data);
|
||||
|
||||
detail::thread_data_ptr get_thread_info() const;
|
||||
detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename F>
|
||||
@@ -147,7 +148,7 @@ namespace boost
|
||||
#endif
|
||||
struct dummy;
|
||||
public:
|
||||
#ifdef __SUNPRO_CC
|
||||
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
|
||||
thread(const volatile thread&);
|
||||
#endif
|
||||
thread();
|
||||
@@ -157,7 +158,7 @@ namespace boost
|
||||
#ifdef BOOST_MSVC
|
||||
template <class F>
|
||||
explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
|
||||
thread_info(make_thread_info(f))
|
||||
thread_info(make_thread_info(static_cast<F&&>(f)))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
@@ -217,7 +218,7 @@ namespace boost
|
||||
x->thread_info.reset();
|
||||
}
|
||||
|
||||
#ifdef __SUNPRO_CC
|
||||
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
|
||||
thread& operator=(thread x)
|
||||
{
|
||||
swap(x);
|
||||
@@ -394,7 +395,7 @@ namespace boost
|
||||
thread_data(thread_data_)
|
||||
{}
|
||||
friend class thread;
|
||||
friend id this_thread::get_id();
|
||||
friend id BOOST_THREAD_DECL this_thread::get_id();
|
||||
public:
|
||||
id():
|
||||
thread_data()
|
||||
@@ -430,6 +431,8 @@ namespace boost
|
||||
return !(thread_data<y.thread_data);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
template<class charT, class traits>
|
||||
friend std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
|
||||
@@ -443,8 +446,34 @@ namespace boost
|
||||
return os<<"{Not-any-thread}";
|
||||
}
|
||||
}
|
||||
#else
|
||||
template<class charT, class traits>
|
||||
std::basic_ostream<charT, traits>&
|
||||
print(std::basic_ostream<charT, traits>& os) const
|
||||
{
|
||||
if(thread_data)
|
||||
{
|
||||
return os<<thread_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return os<<"{Not-any-thread}";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template<class charT, class traits>
|
||||
std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
|
||||
{
|
||||
return x.print(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool thread::operator==(const thread& other) const
|
||||
{
|
||||
return get_id()==other.get_id();
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread_group:
|
||||
private noncopyable
|
||||
class thread_group
|
||||
{
|
||||
private:
|
||||
thread_group(thread_group const&);
|
||||
thread_group& operator=(thread_group const&);
|
||||
public:
|
||||
thread_group() {}
|
||||
~thread_group()
|
||||
{
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
|
||||
@@ -12,27 +12,9 @@
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
typedef void (__cdecl *thread_exit_handler)(void);
|
||||
|
||||
extern "C" BOOST_THREAD_DECL int at_thread_exit(
|
||||
thread_exit_handler exit_handler
|
||||
);
|
||||
//Add a function to the list of functions that will
|
||||
//be called when a thread is about to exit.
|
||||
//Currently only implemented for Win32, but should
|
||||
//later be implemented for all platforms.
|
||||
//Used by Win32 implementation of Boost.Threads
|
||||
//tss to perform cleanup.
|
||||
//Like the C runtime library atexit() function,
|
||||
//which it mimics, at_thread_exit() returns
|
||||
//zero if successful and a nonzero
|
||||
//value if an error occurs.
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_enter(void);
|
||||
namespace boost
|
||||
{
|
||||
BOOST_THREAD_DECL void __cdecl on_process_enter(void);
|
||||
//Function to be called when the exe or dll
|
||||
//that uses Boost.Threads first starts
|
||||
//or is first loaded.
|
||||
@@ -42,7 +24,7 @@
|
||||
//a method for doing so has been discovered.
|
||||
//May be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_exit(void);
|
||||
BOOST_THREAD_DECL void __cdecl on_process_exit(void);
|
||||
//Function to be called when the exe or dll
|
||||
//that uses Boost.Threads first starts
|
||||
//or is first loaded.
|
||||
@@ -52,7 +34,7 @@
|
||||
//a method for doing so has been discovered.
|
||||
//Must not be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_enter(void);
|
||||
BOOST_THREAD_DECL void __cdecl on_thread_enter(void);
|
||||
//Function to be called just after a thread starts
|
||||
//in an exe or dll that uses Boost.Threads.
|
||||
//Must be called in the context of the thread
|
||||
@@ -61,7 +43,7 @@
|
||||
//a method for doing so has been discovered.
|
||||
//May be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
|
||||
BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
|
||||
//Function to be called just be fore a thread ends
|
||||
//in an exe or dll that uses Boost.Threads.
|
||||
//Must be called in the context of the thread
|
||||
@@ -70,10 +52,11 @@
|
||||
//a method for doing so has been discovered.
|
||||
//Must not be omitted; may be called multiple times.
|
||||
|
||||
extern "C" void tss_cleanup_implemented(void);
|
||||
void tss_cleanup_implemented();
|
||||
//Dummy function used both to detect whether tss cleanup
|
||||
//cleanup has been implemented and to force
|
||||
//it to be linked into the Boost.Threads library.
|
||||
}
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdexcept>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
@@ -140,6 +142,8 @@ namespace boost
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
private:
|
||||
relocker& operator=(relocker const&);
|
||||
};
|
||||
|
||||
void do_callback(boost::unique_lock<boost::mutex>& lock)
|
||||
@@ -388,15 +392,18 @@ namespace boost
|
||||
|
||||
class future_waiter
|
||||
{
|
||||
struct registered_waiter;
|
||||
typedef std::vector<registered_waiter>::size_type count_type;
|
||||
|
||||
struct registered_waiter
|
||||
{
|
||||
boost::shared_ptr<detail::future_object_base> future;
|
||||
detail::future_object_base::waiter_list::iterator wait_iterator;
|
||||
unsigned index;
|
||||
count_type index;
|
||||
|
||||
registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_,
|
||||
detail::future_object_base::waiter_list::iterator wait_iterator_,
|
||||
unsigned index_):
|
||||
count_type index_):
|
||||
future(future_),wait_iterator(wait_iterator_),index(index_)
|
||||
{}
|
||||
|
||||
@@ -404,7 +411,6 @@ namespace boost
|
||||
|
||||
struct all_futures_lock
|
||||
{
|
||||
typedef std::vector<registered_waiter>::size_type count_type;
|
||||
count_type count;
|
||||
boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
|
||||
|
||||
@@ -424,7 +430,7 @@ namespace boost
|
||||
|
||||
void unlock()
|
||||
{
|
||||
for(unsigned i=0;i<count;++i)
|
||||
for(count_type i=0;i<count;++i)
|
||||
{
|
||||
locks[i].unlock();
|
||||
}
|
||||
@@ -433,7 +439,7 @@ namespace boost
|
||||
|
||||
boost::condition_variable_any cv;
|
||||
std::vector<registered_waiter> futures;
|
||||
unsigned future_count;
|
||||
count_type future_count;
|
||||
|
||||
public:
|
||||
future_waiter():
|
||||
@@ -450,12 +456,12 @@ namespace boost
|
||||
++future_count;
|
||||
}
|
||||
|
||||
unsigned wait()
|
||||
count_type wait()
|
||||
{
|
||||
all_futures_lock lk(futures);
|
||||
for(;;)
|
||||
{
|
||||
for(unsigned i=0;i<futures.size();++i)
|
||||
for(count_type i=0;i<futures.size();++i)
|
||||
{
|
||||
if(futures[i].future->done)
|
||||
{
|
||||
@@ -468,7 +474,7 @@ namespace boost
|
||||
|
||||
~future_waiter()
|
||||
{
|
||||
for(unsigned i=0;i<futures.size();++i)
|
||||
for(count_type i=0;i<futures.size();++i)
|
||||
{
|
||||
futures[i].future->remove_external_waiter(futures[i].wait_iterator);
|
||||
}
|
||||
@@ -548,6 +554,9 @@ namespace boost
|
||||
template<typename Iterator>
|
||||
typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
|
||||
{
|
||||
if(begin==end)
|
||||
return end;
|
||||
|
||||
detail::future_waiter waiter;
|
||||
for(Iterator current=begin;current!=end;++current)
|
||||
{
|
||||
@@ -903,10 +912,10 @@ namespace boost
|
||||
|
||||
void lazy_init()
|
||||
{
|
||||
if(!future)
|
||||
if(!atomic_load(&future))
|
||||
{
|
||||
future_obtained=false;
|
||||
future.reset(new detail::future_object<R>);
|
||||
future_ptr blank;
|
||||
atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -936,12 +945,14 @@ namespace boost
|
||||
future_obtained(rhs.future_obtained)
|
||||
{
|
||||
future.swap(rhs.future);
|
||||
rhs.future_obtained=false;
|
||||
}
|
||||
promise & operator=(promise&& rhs)
|
||||
{
|
||||
future.swap(rhs.future);
|
||||
future_obtained=rhs.future_obtained;
|
||||
rhs.future.reset();
|
||||
rhs.future_obtained=false;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
@@ -949,12 +960,14 @@ namespace boost
|
||||
future(rhs->future),future_obtained(rhs->future_obtained)
|
||||
{
|
||||
rhs->future.reset();
|
||||
rhs->future_obtained=false;
|
||||
}
|
||||
promise & operator=(boost::detail::thread_move_t<promise> rhs)
|
||||
{
|
||||
future=rhs->future;
|
||||
future_obtained=rhs->future_obtained;
|
||||
rhs->future.reset();
|
||||
rhs->future_obtained=false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1038,10 +1051,10 @@ namespace boost
|
||||
|
||||
void lazy_init()
|
||||
{
|
||||
if(!future)
|
||||
if(!atomic_load(&future))
|
||||
{
|
||||
future_obtained=false;
|
||||
future.reset(new detail::future_object<void>);
|
||||
future_ptr blank;
|
||||
atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<void>));
|
||||
}
|
||||
}
|
||||
public:
|
||||
@@ -1070,12 +1083,14 @@ namespace boost
|
||||
future_obtained(rhs.future_obtained)
|
||||
{
|
||||
future.swap(rhs.future);
|
||||
rhs.future_obtained=false;
|
||||
}
|
||||
promise & operator=(promise&& rhs)
|
||||
{
|
||||
future.swap(rhs.future);
|
||||
future_obtained=rhs.future_obtained;
|
||||
rhs.future.reset();
|
||||
rhs.future_obtained=false;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
@@ -1083,12 +1098,14 @@ namespace boost
|
||||
future(rhs->future),future_obtained(rhs->future_obtained)
|
||||
{
|
||||
rhs->future.reset();
|
||||
rhs->future_obtained=false;
|
||||
}
|
||||
promise & operator=(boost::detail::thread_move_t<promise> rhs)
|
||||
{
|
||||
future=rhs->future;
|
||||
future_obtained=rhs->future_obtained;
|
||||
rhs->future.reset();
|
||||
rhs->future_obtained=false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <iterator>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -27,40 +28,100 @@ namespace boost
|
||||
#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
#define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \
|
||||
template<typename T, bool=boost::is_class<T>::value> \
|
||||
struct has_member_called_##member_name \
|
||||
{ \
|
||||
BOOST_STATIC_CONSTANT(bool, value=false); \
|
||||
}; \
|
||||
\
|
||||
template<typename T> \
|
||||
struct has_member_called_##member_name<T,true> \
|
||||
{ \
|
||||
typedef char true_type; \
|
||||
struct false_type \
|
||||
{ \
|
||||
true_type dummy[2]; \
|
||||
}; \
|
||||
\
|
||||
struct fallback { int member_name; }; \
|
||||
struct derived: \
|
||||
T, fallback \
|
||||
{ \
|
||||
derived(); \
|
||||
}; \
|
||||
\
|
||||
template<int fallback::*> struct tester; \
|
||||
\
|
||||
template<typename U> \
|
||||
static false_type has_member(tester<&U::member_name>*); \
|
||||
template<typename U> \
|
||||
static true_type has_member(...); \
|
||||
\
|
||||
BOOST_STATIC_CONSTANT( \
|
||||
bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \
|
||||
}
|
||||
|
||||
BOOST_DEFINE_HAS_MEMBER_CALLED(lock);
|
||||
BOOST_DEFINE_HAS_MEMBER_CALLED(unlock);
|
||||
BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock);
|
||||
|
||||
template<typename T,bool=has_member_called_lock<T>::value >
|
||||
struct has_member_lock
|
||||
{
|
||||
typedef char true_type;
|
||||
struct false_type
|
||||
{
|
||||
true_type dummy[2];
|
||||
};
|
||||
|
||||
template<typename U>
|
||||
static true_type has_member(U*,void (U::*dummy)()=&U::lock);
|
||||
static false_type has_member(void*);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_lock<T>::has_member((T*)NULL))==sizeof(true_type));
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_unlock
|
||||
{
|
||||
typedef char true_type;
|
||||
struct false_type
|
||||
{
|
||||
true_type dummy[2];
|
||||
};
|
||||
|
||||
template<typename U>
|
||||
static true_type has_member(U*,void (U::*dummy)()=&U::unlock);
|
||||
static false_type has_member(void*);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_unlock<T>::has_member((T*)NULL))==sizeof(true_type));
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_lock<T,true>
|
||||
{
|
||||
typedef char true_type;
|
||||
struct false_type
|
||||
{
|
||||
true_type dummy[2];
|
||||
};
|
||||
|
||||
template<typename U,typename V>
|
||||
static true_type has_member(V (U::*)());
|
||||
template<typename U>
|
||||
static false_type has_member(U);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
|
||||
};
|
||||
|
||||
template<typename T,bool=has_member_called_unlock<T>::value >
|
||||
struct has_member_unlock
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_unlock<T,true>
|
||||
{
|
||||
typedef char true_type;
|
||||
struct false_type
|
||||
{
|
||||
true_type dummy[2];
|
||||
};
|
||||
|
||||
template<typename U,typename V>
|
||||
static true_type has_member(V (U::*)());
|
||||
template<typename U>
|
||||
static false_type has_member(U);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
|
||||
};
|
||||
|
||||
template<typename T,bool=has_member_called_try_lock<T>::value >
|
||||
struct has_member_try_lock
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_try_lock<T,true>
|
||||
{
|
||||
typedef char true_type;
|
||||
struct false_type
|
||||
@@ -69,10 +130,12 @@ namespace boost
|
||||
};
|
||||
|
||||
template<typename U>
|
||||
static true_type has_member(U*,bool (U::*dummy)()=&U::try_lock);
|
||||
static false_type has_member(void*);
|
||||
static true_type has_member(bool (U::*)());
|
||||
template<typename U>
|
||||
static false_type has_member(U);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_try_lock<T>::has_member((T*)NULL))==sizeof(true_type));
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
|
||||
};
|
||||
|
||||
}
|
||||
@@ -214,7 +277,7 @@ namespace boost
|
||||
unique_lock& operator=(unique_lock&);
|
||||
unique_lock& operator=(upgrade_lock<Mutex>& other);
|
||||
public:
|
||||
#ifdef __SUNPRO_CC
|
||||
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
|
||||
unique_lock(const volatile unique_lock&);
|
||||
#endif
|
||||
unique_lock():
|
||||
@@ -300,7 +363,7 @@ namespace boost
|
||||
return detail::thread_move_t<unique_lock<Mutex> >(*this);
|
||||
}
|
||||
|
||||
#ifdef __SUNPRO_CC
|
||||
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
|
||||
unique_lock& operator=(unique_lock<Mutex> other)
|
||||
{
|
||||
swap(other);
|
||||
@@ -422,6 +485,18 @@ namespace boost
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>&& ul)
|
||||
{
|
||||
return static_cast<upgrade_lock<Mutex>&&>(ul);
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>& ul)
|
||||
{
|
||||
return static_cast<upgrade_lock<Mutex>&&>(ul);
|
||||
}
|
||||
#endif
|
||||
template<typename Mutex>
|
||||
void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
|
||||
@@ -678,6 +753,39 @@ namespace boost
|
||||
{
|
||||
try_lock();
|
||||
}
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
upgrade_lock(upgrade_lock<Mutex>&& other):
|
||||
m(other.m),is_locked(other.is_locked)
|
||||
{
|
||||
other.is_locked=false;
|
||||
other.m=0;
|
||||
}
|
||||
|
||||
upgrade_lock(unique_lock<Mutex>&& other):
|
||||
m(other.m),is_locked(other.is_locked)
|
||||
{
|
||||
if(is_locked)
|
||||
{
|
||||
m->unlock_and_lock_upgrade();
|
||||
}
|
||||
other.is_locked=false;
|
||||
other.m=0;
|
||||
}
|
||||
|
||||
upgrade_lock& operator=(upgrade_lock<Mutex>&& other)
|
||||
{
|
||||
upgrade_lock temp(static_cast<upgrade_lock<Mutex>&&>(other));
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
upgrade_lock& operator=(unique_lock<Mutex>&& other)
|
||||
{
|
||||
upgrade_lock temp(static_cast<unique_lock<Mutex>&&>(other));
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
@@ -720,6 +828,7 @@ namespace boost
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void swap(upgrade_lock& other)
|
||||
{
|
||||
@@ -824,6 +933,20 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other):
|
||||
source(other.source),exclusive(move(other.exclusive))
|
||||
{
|
||||
other.source=0;
|
||||
}
|
||||
|
||||
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other)
|
||||
{
|
||||
upgrade_to_unique_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other):
|
||||
source(other->source),exclusive(move(other->exclusive))
|
||||
{
|
||||
@@ -836,6 +959,7 @@ namespace boost
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
void swap(upgrade_to_unique_lock& other)
|
||||
{
|
||||
std::swap(source,other.source);
|
||||
@@ -923,15 +1047,15 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(try_lock_wrapper& other)
|
||||
{
|
||||
base::swap(other);
|
||||
}
|
||||
void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other)
|
||||
{
|
||||
base::swap(*other);
|
||||
}
|
||||
#endif
|
||||
void swap(try_lock_wrapper& other)
|
||||
{
|
||||
base::swap(other);
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
base::lock();
|
||||
@@ -1116,7 +1240,7 @@ namespace boost
|
||||
{
|
||||
unsigned const lock_count=2;
|
||||
unsigned lock_first=0;
|
||||
while(true)
|
||||
for(;;)
|
||||
{
|
||||
switch(lock_first)
|
||||
{
|
||||
@@ -1169,7 +1293,7 @@ namespace boost
|
||||
{
|
||||
unsigned const lock_count=3;
|
||||
unsigned lock_first=0;
|
||||
while(true)
|
||||
for(;;)
|
||||
{
|
||||
switch(lock_first)
|
||||
{
|
||||
@@ -1201,7 +1325,7 @@ namespace boost
|
||||
{
|
||||
unsigned const lock_count=4;
|
||||
unsigned lock_first=0;
|
||||
while(true)
|
||||
for(;;)
|
||||
{
|
||||
switch(lock_first)
|
||||
{
|
||||
@@ -1239,7 +1363,7 @@ namespace boost
|
||||
{
|
||||
unsigned const lock_count=5;
|
||||
unsigned lock_first=0;
|
||||
while(true)
|
||||
for(;;)
|
||||
{
|
||||
switch(lock_first)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// 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)
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
// (C) Copyright 2007-10 Anthony Williams
|
||||
|
||||
#include "timespec.hpp"
|
||||
#include "pthread_mutex_scoped_lock.hpp"
|
||||
@@ -14,17 +14,55 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace this_thread
|
||||
{
|
||||
void BOOST_THREAD_DECL interruption_point();
|
||||
}
|
||||
|
||||
namespace thread_cv_detail
|
||||
{
|
||||
template<typename MutexType>
|
||||
struct lock_on_exit
|
||||
{
|
||||
MutexType* m;
|
||||
|
||||
lock_on_exit():
|
||||
m(0)
|
||||
{}
|
||||
|
||||
void activate(MutexType& m_)
|
||||
{
|
||||
m_.unlock();
|
||||
m=&m_;
|
||||
}
|
||||
~lock_on_exit()
|
||||
{
|
||||
if(m)
|
||||
{
|
||||
m->lock();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline void condition_variable::wait(unique_lock<mutex>& m)
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,m.mutex()->native_handle()));
|
||||
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
guard.activate(m);
|
||||
int const res=pthread_cond_wait(&cond,&internal_mutex);
|
||||
BOOST_ASSERT(!res);
|
||||
this_thread::interruption_point();
|
||||
}
|
||||
|
||||
inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
guard.activate(m);
|
||||
struct timespec const timeout=detail::get_timespec(wait_until);
|
||||
int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout);
|
||||
int const cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||
this_thread::interruption_point();
|
||||
if(cond_res==ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
@@ -35,11 +73,13 @@ namespace boost
|
||||
|
||||
inline void condition_variable::notify_one()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
inline void condition_variable::notify_all()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
|
||||
}
|
||||
|
||||
@@ -48,8 +88,8 @@ namespace boost
|
||||
pthread_mutex_t internal_mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
condition_variable_any(condition_variable&);
|
||||
condition_variable_any& operator=(condition_variable&);
|
||||
condition_variable_any(condition_variable_any&);
|
||||
condition_variable_any& operator=(condition_variable_any&);
|
||||
|
||||
public:
|
||||
condition_variable_any()
|
||||
@@ -77,13 +117,11 @@ namespace boost
|
||||
{
|
||||
int res=0;
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
m.unlock();
|
||||
res=pthread_cond_wait(&cond,&internal_mutex);
|
||||
}
|
||||
m.lock();
|
||||
thread_cv_detail::lock_on_exit<lock_type> guard;
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
guard.activate(m);
|
||||
res=pthread_cond_wait(&cond,&internal_mutex);
|
||||
this_thread::interruption_point();
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
@@ -103,13 +141,11 @@ namespace boost
|
||||
struct timespec const timeout=detail::get_timespec(wait_until);
|
||||
int res=0;
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
m.unlock();
|
||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||
}
|
||||
m.lock();
|
||||
thread_cv_detail::lock_on_exit<lock_type> guard;
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
guard.activate(m);
|
||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||
this_thread::interruption_point();
|
||||
}
|
||||
if(res==ETIMEDOUT)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace boost
|
||||
class condition_variable
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t internal_mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
condition_variable(condition_variable&);
|
||||
@@ -28,14 +29,21 @@ namespace boost
|
||||
public:
|
||||
condition_variable()
|
||||
{
|
||||
int const res=pthread_cond_init(&cond,NULL);
|
||||
int const res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
}
|
||||
~condition_variable()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
}
|
||||
|
||||
@@ -47,7 +55,8 @@ namespace boost
|
||||
while(!pred()) wait(m);
|
||||
}
|
||||
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until);
|
||||
inline bool timed_wait(unique_lock<mutex>& m,
|
||||
boost::system_time const& wait_until);
|
||||
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until)
|
||||
{
|
||||
return timed_wait(m,system_time(wait_until));
|
||||
|
||||
@@ -27,10 +27,11 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class mutex:
|
||||
boost::noncopyable
|
||||
class mutex
|
||||
{
|
||||
private:
|
||||
mutex(mutex const&);
|
||||
mutex& operator=(mutex const&);
|
||||
pthread_mutex_t m;
|
||||
public:
|
||||
mutex()
|
||||
@@ -48,7 +49,11 @@ namespace boost
|
||||
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
int const res=pthread_mutex_lock(&m);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(lock_error(res));
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
@@ -59,7 +64,11 @@ namespace boost
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
if(res && (res!=EBUSY))
|
||||
{
|
||||
boost::throw_exception(lock_error(res));
|
||||
}
|
||||
|
||||
return !res;
|
||||
}
|
||||
|
||||
@@ -75,9 +84,11 @@ namespace boost
|
||||
|
||||
typedef mutex try_mutex;
|
||||
|
||||
class timed_mutex:
|
||||
boost::noncopyable
|
||||
class timed_mutex
|
||||
{
|
||||
private:
|
||||
timed_mutex(timed_mutex const&);
|
||||
timed_mutex& operator=(timed_mutex const&);
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
|
||||
@@ -18,15 +18,25 @@ namespace boost
|
||||
class pthread_mutex_scoped_lock
|
||||
{
|
||||
pthread_mutex_t* m;
|
||||
bool locked;
|
||||
public:
|
||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
|
||||
m(m_)
|
||||
m(m_),locked(true)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
~pthread_mutex_scoped_lock()
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
locked=false;
|
||||
}
|
||||
|
||||
~pthread_mutex_scoped_lock()
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -26,18 +26,30 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
|
||||
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class recursive_mutex:
|
||||
boost::noncopyable
|
||||
class recursive_mutex
|
||||
{
|
||||
private:
|
||||
recursive_mutex(recursive_mutex const&);
|
||||
recursive_mutex& operator=(recursive_mutex const&);
|
||||
pthread_mutex_t m;
|
||||
#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE
|
||||
pthread_cond_t cond;
|
||||
bool is_locked;
|
||||
pthread_t owner;
|
||||
unsigned count;
|
||||
#endif
|
||||
public:
|
||||
recursive_mutex()
|
||||
{
|
||||
#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
@@ -48,21 +60,42 @@ namespace boost
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
#else
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
is_locked=false;
|
||||
count=0;
|
||||
#endif
|
||||
}
|
||||
~recursive_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
@@ -79,25 +112,70 @@ namespace boost
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
|
||||
typedef pthread_mutex_t* native_handle_type;
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
return &m;
|
||||
}
|
||||
|
||||
#else
|
||||
void lock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(is_locked && pthread_equal(owner,pthread_self()))
|
||||
{
|
||||
++count;
|
||||
return;
|
||||
}
|
||||
|
||||
while(is_locked)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
owner=pthread_self();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(!--count)
|
||||
{
|
||||
is_locked=false;
|
||||
}
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(is_locked && !pthread_equal(owner,pthread_self()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
owner=pthread_self();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef unique_lock<recursive_mutex> scoped_lock;
|
||||
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
|
||||
};
|
||||
|
||||
typedef recursive_mutex recursive_try_mutex;
|
||||
|
||||
class recursive_timed_mutex:
|
||||
boost::noncopyable
|
||||
class recursive_timed_mutex
|
||||
{
|
||||
private:
|
||||
recursive_timed_mutex(recursive_timed_mutex const&);
|
||||
recursive_timed_mutex& operator=(recursive_timed_mutex const&);
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
pthread_cond_t cond;
|
||||
bool is_locked;
|
||||
pthread_t owner;
|
||||
@@ -106,7 +184,7 @@ namespace boost
|
||||
public:
|
||||
recursive_timed_mutex()
|
||||
{
|
||||
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
@@ -146,7 +224,7 @@ namespace boost
|
||||
~recursive_timed_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
@@ -157,7 +235,7 @@ namespace boost
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace boost
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_upgrade(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
return timed_lock_upgrade(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
bool try_lock_upgrade()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
#include "condition_variable_fwd.hpp"
|
||||
#include <map>
|
||||
|
||||
@@ -55,6 +56,7 @@ namespace boost
|
||||
std::map<void const*,boost::detail::tss_data_node> tss_data;
|
||||
bool interrupt_enabled;
|
||||
bool interrupt_requested;
|
||||
pthread_mutex_t* cond_mutex;
|
||||
pthread_cond_t* current_cond;
|
||||
|
||||
thread_data_base():
|
||||
@@ -76,6 +78,8 @@ namespace boost
|
||||
class interruption_checker
|
||||
{
|
||||
thread_data_base* const thread_info;
|
||||
pthread_mutex_t* m;
|
||||
bool set;
|
||||
|
||||
void check_for_interruption()
|
||||
{
|
||||
@@ -88,23 +92,35 @@ namespace boost
|
||||
|
||||
void operator=(interruption_checker&);
|
||||
public:
|
||||
explicit interruption_checker(pthread_cond_t* cond):
|
||||
thread_info(detail::get_current_thread_data())
|
||||
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
|
||||
thread_info(detail::get_current_thread_data()),m(cond_mutex),
|
||||
set(thread_info && thread_info->interrupt_enabled)
|
||||
{
|
||||
if(thread_info && thread_info->interrupt_enabled)
|
||||
if(set)
|
||||
{
|
||||
lock_guard<mutex> guard(thread_info->data_mutex);
|
||||
check_for_interruption();
|
||||
thread_info->cond_mutex=cond_mutex;
|
||||
thread_info->current_cond=cond;
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
}
|
||||
~interruption_checker()
|
||||
{
|
||||
if(thread_info && thread_info->interrupt_enabled)
|
||||
if(set)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
lock_guard<mutex> guard(thread_info->data_mutex);
|
||||
thread_info->cond_mutex=NULL;
|
||||
thread_info->current_cond=NULL;
|
||||
check_for_interruption();
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/date_time/time_clock.hpp>
|
||||
#include <boost/date_time/microsec_time_clock.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
@@ -17,7 +18,11 @@ namespace boost
|
||||
|
||||
inline system_time get_system_time()
|
||||
{
|
||||
#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
|
||||
return boost::date_time::microsec_clock<system_time>::universal_time();
|
||||
#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
|
||||
return boost::date_time::second_clock<system_time>::universal_time();
|
||||
#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
|
||||
}
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -62,6 +62,8 @@ namespace boost
|
||||
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
thread_specific_ptr():
|
||||
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
|
||||
{}
|
||||
|
||||
@@ -20,9 +20,11 @@ namespace boost
|
||||
}
|
||||
|
||||
class mutex:
|
||||
boost::noncopyable,
|
||||
public ::boost::detail::underlying_mutex
|
||||
{
|
||||
private:
|
||||
mutex(mutex const&);
|
||||
mutex& operator=(mutex const&);
|
||||
public:
|
||||
mutex()
|
||||
{
|
||||
@@ -40,9 +42,11 @@ namespace boost
|
||||
typedef mutex try_mutex;
|
||||
|
||||
class timed_mutex:
|
||||
boost::noncopyable,
|
||||
public ::boost::detail::basic_timed_mutex
|
||||
{
|
||||
private:
|
||||
timed_mutex(timed_mutex const&);
|
||||
timed_mutex& operator=(timed_mutex const&);
|
||||
public:
|
||||
timed_mutex()
|
||||
{
|
||||
|
||||
@@ -34,42 +34,85 @@ namespace boost
|
||||
{
|
||||
long status;
|
||||
long count;
|
||||
long throw_count;
|
||||
void* event_handle;
|
||||
|
||||
~once_flag()
|
||||
{
|
||||
if(count)
|
||||
{
|
||||
BOOST_ASSERT(count==throw_count);
|
||||
}
|
||||
|
||||
void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event_handle,0);
|
||||
if(old_event)
|
||||
{
|
||||
::boost::detail::win32::CloseHandle(old_event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_ONCE_INIT {0,0,0,0}
|
||||
#define BOOST_ONCE_INIT {0,0}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline void* allocate_event_handle(void*& handle)
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
typedef wchar_t once_char_type;
|
||||
#else
|
||||
typedef char once_char_type;
|
||||
#endif
|
||||
unsigned const once_mutex_name_fixed_length=54;
|
||||
unsigned const once_mutex_name_length=once_mutex_name_fixed_length+
|
||||
sizeof(void*)*2+sizeof(unsigned long)*2+1;
|
||||
|
||||
template <class I>
|
||||
void int_to_string(I p, once_char_type* buf)
|
||||
{
|
||||
void* const new_handle=::boost::detail::win32::create_anonymous_event(
|
||||
::boost::detail::win32::manual_reset_event,
|
||||
::boost::detail::win32::event_initially_reset);
|
||||
|
||||
void* event_handle=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&handle,
|
||||
new_handle,0);
|
||||
if(event_handle)
|
||||
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
|
||||
{
|
||||
::boost::detail::win32::CloseHandle(new_handle);
|
||||
return event_handle;
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
once_char_type const a=L'A';
|
||||
#else
|
||||
once_char_type const a='A';
|
||||
#endif
|
||||
*buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f);
|
||||
}
|
||||
return new_handle;
|
||||
*buf = 0;
|
||||
}
|
||||
|
||||
inline void name_once_mutex(once_char_type* mutex_name,void* flag_address)
|
||||
{
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#else
|
||||
static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#endif
|
||||
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
|
||||
(sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
|
||||
|
||||
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
|
||||
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
|
||||
mutex_name + once_mutex_name_fixed_length);
|
||||
detail::int_to_string(win32::GetCurrentProcessId(),
|
||||
mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
|
||||
}
|
||||
|
||||
inline void* open_once_event(once_char_type* mutex_name,void* flag_address)
|
||||
{
|
||||
if(!*mutex_name)
|
||||
{
|
||||
name_once_mutex(mutex_name,flag_address);
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return ::boost::detail::win32::OpenEventW(
|
||||
#else
|
||||
return ::boost::detail::win32::OpenEventA(
|
||||
#endif
|
||||
::boost::detail::win32::synchronize |
|
||||
::boost::detail::win32::event_modify_state,
|
||||
false,
|
||||
mutex_name);
|
||||
}
|
||||
|
||||
inline void* create_once_event(once_char_type* mutex_name,void* flag_address)
|
||||
{
|
||||
if(!*mutex_name)
|
||||
{
|
||||
name_once_mutex(mutex_name,flag_address);
|
||||
}
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return ::boost::detail::win32::CreateEventW(
|
||||
#else
|
||||
return ::boost::detail::win32::CreateEventA(
|
||||
#endif
|
||||
0,::boost::detail::win32::manual_reset_event,
|
||||
::boost::detail::win32::event_initially_reset,
|
||||
mutex_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +126,9 @@ namespace boost
|
||||
long const running_value=0x7f0725e3;
|
||||
long status;
|
||||
bool counted=false;
|
||||
void* event_handle=0;
|
||||
long throw_count=0;
|
||||
detail::win32::handle_manager event_handle;
|
||||
detail::once_char_type mutex_name[detail::once_mutex_name_length];
|
||||
mutex_name[0]=0;
|
||||
|
||||
while((status=::boost::detail::interlocked_read_acquire(&flag.status))
|
||||
!=function_complete_flag_value)
|
||||
@@ -96,7 +140,7 @@ namespace boost
|
||||
{
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
|
||||
event_handle=detail::open_once_event(mutex_name,&flag);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
@@ -112,25 +156,20 @@ namespace boost
|
||||
if(!event_handle &&
|
||||
(::boost::detail::interlocked_read_acquire(&flag.count)>1))
|
||||
{
|
||||
event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
|
||||
event_handle=detail::create_once_event(mutex_name,&flag);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
::boost::detail::win32::SetEvent(event_handle);
|
||||
}
|
||||
throw_count=::boost::detail::interlocked_read_acquire(&flag.throw_count);
|
||||
break;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
if(counted)
|
||||
{
|
||||
BOOST_INTERLOCKED_INCREMENT(&flag.throw_count);
|
||||
}
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
|
||||
event_handle=detail::open_once_event(mutex_name,&flag);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
@@ -149,31 +188,15 @@ namespace boost
|
||||
{
|
||||
break;
|
||||
}
|
||||
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
|
||||
event_handle=detail::create_once_event(mutex_name,&flag);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
event_handle,::boost::detail::win32::infinite));
|
||||
}
|
||||
if(counted || throw_count)
|
||||
{
|
||||
if(!BOOST_INTERLOCKED_EXCHANGE_ADD(&flag.count,(counted?-1:0)-throw_count))
|
||||
{
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE_POINTER(&flag.event_handle,0);
|
||||
::boost::detail::win32::CloseHandle(event_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
namespace boost
|
||||
{
|
||||
class recursive_mutex:
|
||||
boost::noncopyable,
|
||||
public ::boost::detail::basic_recursive_mutex
|
||||
{
|
||||
private:
|
||||
recursive_mutex(recursive_mutex const&);
|
||||
recursive_mutex& operator=(recursive_mutex const&);
|
||||
public:
|
||||
recursive_mutex()
|
||||
{
|
||||
@@ -40,9 +42,11 @@ namespace boost
|
||||
typedef recursive_mutex recursive_try_mutex;
|
||||
|
||||
class recursive_timed_mutex:
|
||||
boost::noncopyable,
|
||||
public ::boost::detail::basic_recursive_timed_mutex
|
||||
{
|
||||
private:
|
||||
recursive_timed_mutex(recursive_timed_mutex const&);
|
||||
recursive_timed_mutex& operator=(recursive_timed_mutex const&);
|
||||
public:
|
||||
recursive_timed_mutex()
|
||||
{
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class shared_mutex:
|
||||
private boost::noncopyable
|
||||
class shared_mutex
|
||||
{
|
||||
private:
|
||||
shared_mutex(shared_mutex const&);
|
||||
shared_mutex& operator=(shared_mutex const&);
|
||||
private:
|
||||
struct state_data
|
||||
{
|
||||
@@ -49,33 +51,35 @@ namespace boost
|
||||
return *reinterpret_cast<T const*>(&res);
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
unlock_sem = 0,
|
||||
exclusive_sem = 1
|
||||
};
|
||||
|
||||
state_data state;
|
||||
detail::win32::handle semaphores[2];
|
||||
detail::win32::handle &unlock_sem;
|
||||
detail::win32::handle &exclusive_sem;
|
||||
detail::win32::handle upgrade_sem;
|
||||
|
||||
void release_waiters(state_data old_state)
|
||||
{
|
||||
if(old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
|
||||
}
|
||||
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
shared_mutex():
|
||||
unlock_sem(semaphores[0]),
|
||||
exclusive_sem(semaphores[1])
|
||||
shared_mutex()
|
||||
{
|
||||
unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
state_data state_={0};
|
||||
state=state_;
|
||||
@@ -84,8 +88,8 @@ namespace boost
|
||||
~shared_mutex()
|
||||
{
|
||||
detail::win32::CloseHandle(upgrade_sem);
|
||||
detail::win32::CloseHandle(unlock_sem);
|
||||
detail::win32::CloseHandle(exclusive_sem);
|
||||
detail::win32::CloseHandle(semaphores[unlock_sem]);
|
||||
detail::win32::CloseHandle(semaphores[exclusive_sem]);
|
||||
}
|
||||
|
||||
bool try_lock_shared()
|
||||
@@ -97,6 +101,10 @@ namespace boost
|
||||
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
@@ -131,10 +139,18 @@ namespace boost
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
++new_state.shared_waiting;
|
||||
if(!new_state.shared_waiting)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
@@ -150,7 +166,7 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
|
||||
unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until));
|
||||
if(res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
@@ -166,6 +182,10 @@ namespace boost
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
@@ -282,6 +302,11 @@ namespace boost
|
||||
if(new_state.shared_count || new_state.exclusive)
|
||||
{
|
||||
++new_state.exclusive_waiting;
|
||||
if(!new_state.exclusive_waiting)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
|
||||
new_state.exclusive_waiting_blocked=true;
|
||||
}
|
||||
else
|
||||
@@ -374,10 +399,18 @@ namespace boost
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
|
||||
{
|
||||
++new_state.shared_waiting;
|
||||
if(!new_state.shared_waiting)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
new_state.upgrade=true;
|
||||
}
|
||||
|
||||
@@ -394,7 +427,7 @@ namespace boost
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,6 +444,10 @@ namespace boost
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
new_state.upgrade=true;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,11 @@ namespace boost
|
||||
start(0),milliseconds(~uintmax_t(0)),relative(true)
|
||||
{}
|
||||
};
|
||||
|
||||
inline unsigned long pin_to_zero(long value)
|
||||
{
|
||||
return (value<0)?0u:(unsigned long)value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
@@ -163,7 +168,7 @@ namespace boost
|
||||
template<typename TimeDuration>
|
||||
inline void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
|
||||
interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
|
||||
}
|
||||
inline void sleep(system_time const& abs_time)
|
||||
{
|
||||
|
||||
@@ -31,14 +31,18 @@ namespace boost
|
||||
unsigned const infinite=INFINITE;
|
||||
unsigned const timeout=WAIT_TIMEOUT;
|
||||
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
|
||||
unsigned const event_modify_state=EVENT_MODIFY_STATE;
|
||||
unsigned const synchronize=SYNCHRONIZE;
|
||||
|
||||
# ifdef BOOST_NO_ANSI_APIS
|
||||
using ::CreateMutexW;
|
||||
using ::CreateEventW;
|
||||
using ::OpenEventW;
|
||||
using ::CreateSemaphoreW;
|
||||
# else
|
||||
using ::CreateMutexA;
|
||||
using ::CreateEventA;
|
||||
using ::OpenEventA;
|
||||
using ::CreateSemaphoreA;
|
||||
# endif
|
||||
using ::CloseHandle;
|
||||
@@ -100,6 +104,8 @@ namespace boost
|
||||
unsigned const infinite=~0U;
|
||||
unsigned const timeout=258U;
|
||||
handle const invalid_handle_value=(handle)(-1);
|
||||
unsigned const event_modify_state=2;
|
||||
unsigned const synchronize=0x100000u;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -108,10 +114,12 @@ namespace boost
|
||||
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
|
||||
# else
|
||||
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
|
||||
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
|
||||
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
|
||||
# endif
|
||||
__declspec(dllimport) int __stdcall CloseHandle(void*);
|
||||
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
|
||||
|
||||
0
src/pthread/once.cpp
Executable file → Normal file
0
src/pthread/once.cpp
Executable file → Normal file
@@ -75,7 +75,7 @@ namespace boost
|
||||
{
|
||||
current=next;
|
||||
++next;
|
||||
if(current->second.func && current->second.value)
|
||||
if(current->second.func && (current->second.value!=0))
|
||||
{
|
||||
(*current->second.func)(current->second.value);
|
||||
}
|
||||
@@ -196,15 +196,14 @@ namespace boost
|
||||
detach();
|
||||
}
|
||||
|
||||
detail::thread_data_ptr thread::get_thread_info() const
|
||||
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
||||
{
|
||||
lock_guard<mutex> l(thread_info_mutex);
|
||||
return thread_info;
|
||||
}
|
||||
|
||||
void thread::join()
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
bool do_join=false;
|
||||
@@ -238,7 +237,6 @@ namespace boost
|
||||
local_thread_info->done_condition.notify_all();
|
||||
}
|
||||
|
||||
lock_guard<mutex> l1(thread_info_mutex);
|
||||
if(thread_info==local_thread_info)
|
||||
{
|
||||
thread_info.reset();
|
||||
@@ -248,7 +246,7 @@ namespace boost
|
||||
|
||||
bool thread::timed_join(system_time const& wait_until)
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
bool do_join=false;
|
||||
@@ -285,7 +283,6 @@ namespace boost
|
||||
local_thread_info->done_condition.notify_all();
|
||||
}
|
||||
|
||||
lock_guard<mutex> l1(thread_info_mutex);
|
||||
if(thread_info==local_thread_info)
|
||||
{
|
||||
thread_info.reset();
|
||||
@@ -296,17 +293,14 @@ namespace boost
|
||||
|
||||
bool thread::joinable() const
|
||||
{
|
||||
return get_thread_info();
|
||||
return (get_thread_info)();
|
||||
}
|
||||
|
||||
|
||||
void thread::detach()
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info;
|
||||
{
|
||||
lock_guard<mutex> l1(thread_info_mutex);
|
||||
thread_info.swap(local_thread_info);
|
||||
}
|
||||
thread_info.swap(local_thread_info);
|
||||
|
||||
if(local_thread_info)
|
||||
{
|
||||
@@ -381,8 +375,6 @@ namespace boost
|
||||
{
|
||||
#if defined(PTW32_VERSION) || defined(__hpux)
|
||||
return pthread_num_processors_np();
|
||||
#elif defined(_GNU_SOURCE)
|
||||
return get_nprocs();
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
int count;
|
||||
size_t size=sizeof(count);
|
||||
@@ -390,6 +382,8 @@ namespace boost
|
||||
#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)
|
||||
int const count=sysconf(_SC_NPROCESSORS_ONLN);
|
||||
return (count>0)?count:0;
|
||||
#elif defined(_GNU_SOURCE)
|
||||
return get_nprocs();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@@ -397,7 +391,7 @@ namespace boost
|
||||
|
||||
thread::id thread::get_id() const
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
return id(local_thread_info);
|
||||
@@ -410,13 +404,14 @@ namespace boost
|
||||
|
||||
void thread::interrupt()
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
lock_guard<mutex> lk(local_thread_info->data_mutex);
|
||||
local_thread_info->interrupt_requested=true;
|
||||
if(local_thread_info->current_cond)
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(local_thread_info->cond_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond));
|
||||
}
|
||||
}
|
||||
@@ -424,7 +419,7 @@ namespace boost
|
||||
|
||||
bool thread::interruption_requested() const
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
lock_guard<mutex> lk(local_thread_info->data_mutex);
|
||||
@@ -438,7 +433,7 @@ namespace boost
|
||||
|
||||
thread::native_handle_type thread::native_handle()
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
lock_guard<mutex> lk(local_thread_info->data_mutex);
|
||||
@@ -582,11 +577,11 @@ namespace boost
|
||||
{
|
||||
if(tss_data_node* const current_node=find_tss_data(key))
|
||||
{
|
||||
if(cleanup_existing && current_node->func && current_node->value)
|
||||
if(cleanup_existing && current_node->func && (current_node->value!=0))
|
||||
{
|
||||
(*current_node->func)(current_node->value);
|
||||
}
|
||||
if(func || tss_data)
|
||||
if(func || (tss_data!=0))
|
||||
{
|
||||
current_node->func=func;
|
||||
current_node->value=tss_data;
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE))
|
||||
|
||||
namespace boost
|
||||
{
|
||||
/*
|
||||
This file is a "null" implementation of tss cleanup; it's
|
||||
purpose is to to eliminate link errors in cases
|
||||
where it is known that tss cleanup is not needed.
|
||||
*/
|
||||
|
||||
extern "C" void tss_cleanup_implemented(void)
|
||||
void tss_cleanup_implemented(void)
|
||||
{
|
||||
/*
|
||||
This function's sole purpose is to cause a link error in cases where
|
||||
@@ -30,5 +32,7 @@
|
||||
longer needed and can be removed.
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)
|
||||
|
||||
@@ -244,17 +244,17 @@ namespace boost
|
||||
|
||||
thread::id thread::get_id() const
|
||||
{
|
||||
return thread::id(get_thread_info());
|
||||
return thread::id((get_thread_info)());
|
||||
}
|
||||
|
||||
bool thread::joinable() const
|
||||
{
|
||||
return get_thread_info();
|
||||
return (get_thread_info)();
|
||||
}
|
||||
|
||||
void thread::join()
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
|
||||
@@ -264,7 +264,7 @@ namespace boost
|
||||
|
||||
bool thread::timed_join(boost::system_time const& wait_until)
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until)))
|
||||
@@ -283,13 +283,12 @@ namespace boost
|
||||
|
||||
void thread::release_handle()
|
||||
{
|
||||
lock_guard<mutex> l1(thread_info_mutex);
|
||||
thread_info=0;
|
||||
}
|
||||
|
||||
void thread::interrupt()
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
local_thread_info->interrupt();
|
||||
@@ -298,26 +297,25 @@ namespace boost
|
||||
|
||||
bool thread::interruption_requested() const
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
|
||||
}
|
||||
|
||||
unsigned thread::hardware_concurrency()
|
||||
{
|
||||
SYSTEM_INFO info={0};
|
||||
SYSTEM_INFO info={{0}};
|
||||
GetSystemInfo(&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
thread::native_handle_type thread::native_handle()
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=get_thread_info();
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value;
|
||||
}
|
||||
|
||||
detail::thread_data_ptr thread::get_thread_info() const
|
||||
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
||||
{
|
||||
boost::mutex::scoped_lock l(thread_info_mutex);
|
||||
return thread_info;
|
||||
}
|
||||
|
||||
@@ -327,7 +325,7 @@ namespace boost
|
||||
{
|
||||
LARGE_INTEGER get_due_time(detail::timeout const& target_time)
|
||||
{
|
||||
LARGE_INTEGER due_time={0};
|
||||
LARGE_INTEGER due_time={{0}};
|
||||
if(target_time.relative)
|
||||
{
|
||||
unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start;
|
||||
@@ -356,7 +354,23 @@ namespace boost
|
||||
else
|
||||
{
|
||||
long const hundred_nanoseconds_in_one_second=10000000;
|
||||
due_time.QuadPart+=target_time.abs_time.time_of_day().fractional_seconds()*(hundred_nanoseconds_in_one_second/target_time.abs_time.time_of_day().ticks_per_second());
|
||||
posix_time::time_duration::tick_type const ticks_per_second=
|
||||
target_time.abs_time.time_of_day().ticks_per_second();
|
||||
if(ticks_per_second>hundred_nanoseconds_in_one_second)
|
||||
{
|
||||
posix_time::time_duration::tick_type const
|
||||
ticks_per_hundred_nanoseconds=
|
||||
ticks_per_second/hundred_nanoseconds_in_one_second;
|
||||
due_time.QuadPart+=
|
||||
target_time.abs_time.time_of_day().fractional_seconds()/
|
||||
ticks_per_hundred_nanoseconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
due_time.QuadPart+=
|
||||
target_time.abs_time.time_of_day().fractional_seconds()*
|
||||
(hundred_nanoseconds_in_one_second/ticks_per_second);
|
||||
}
|
||||
}
|
||||
}
|
||||
return due_time;
|
||||
@@ -577,22 +591,22 @@ namespace boost
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_DECL void __cdecl on_process_enter()
|
||||
{}
|
||||
|
||||
BOOST_THREAD_DECL void __cdecl on_thread_enter()
|
||||
{}
|
||||
|
||||
BOOST_THREAD_DECL void __cdecl on_process_exit()
|
||||
{
|
||||
boost::cleanup_tls_key();
|
||||
}
|
||||
|
||||
BOOST_THREAD_DECL void __cdecl on_thread_exit()
|
||||
{
|
||||
boost::run_thread_exit_callbacks();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_enter()
|
||||
{}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_enter()
|
||||
{}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_exit()
|
||||
{
|
||||
boost::cleanup_tls_key();
|
||||
}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_exit()
|
||||
{
|
||||
boost::run_thread_exit_callbacks();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,27 +24,27 @@
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
on_process_enter();
|
||||
on_thread_enter();
|
||||
boost::on_process_enter();
|
||||
boost::on_thread_enter();
|
||||
break;
|
||||
}
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
{
|
||||
on_thread_enter();
|
||||
boost::on_thread_enter();
|
||||
break;
|
||||
}
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
{
|
||||
on_thread_exit();
|
||||
boost::on_thread_exit();
|
||||
break;
|
||||
}
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
{
|
||||
on_thread_exit();
|
||||
on_process_exit();
|
||||
boost::on_thread_exit();
|
||||
boost::on_process_exit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,9 @@
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern "C" void tss_cleanup_implemented(void)
|
||||
namespace boost
|
||||
{
|
||||
void tss_cleanup_implemented()
|
||||
{
|
||||
/*
|
||||
This function's sole purpose is to cause a link error in cases where
|
||||
@@ -68,5 +70,7 @@
|
||||
longer needed and can be removed.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
extern "C" void tss_cleanup_implemented(void) {}
|
||||
namespace boost
|
||||
{
|
||||
void tss_cleanup_implemented() {}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv)
|
||||
@@ -28,33 +31,24 @@ namespace {
|
||||
{
|
||||
case DLL_THREAD_DETACH:
|
||||
{
|
||||
on_thread_exit();
|
||||
boost::on_thread_exit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void on_after_ctors(void)
|
||||
{
|
||||
on_process_enter();
|
||||
}
|
||||
|
||||
void on_before_dtors(void)
|
||||
{
|
||||
on_thread_exit();
|
||||
}
|
||||
|
||||
void on_after_dtors(void)
|
||||
{
|
||||
on_process_exit();
|
||||
}
|
||||
}
|
||||
|
||||
#if (__MINGW32_MAJOR_VERSION >3) || ((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
|
||||
extern "C"
|
||||
{
|
||||
PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
|
||||
}
|
||||
#else
|
||||
extern "C" {
|
||||
|
||||
void (* after_ctors )(void) __attribute__((section(".ctors"))) = on_after_ctors;
|
||||
void (* before_dtors)(void) __attribute__((section(".dtors"))) = on_before_dtors;
|
||||
void (* after_dtors )(void) __attribute__((section(".dtors.zzz"))) = on_after_dtors;
|
||||
void (* after_ctors )() __attribute__((section(".ctors"))) = boost::on_process_enter;
|
||||
void (* before_dtors)() __attribute__((section(".dtors"))) = boost::on_thread_exit;
|
||||
void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit;
|
||||
|
||||
ULONG __tls_index__ = 0;
|
||||
char __tls_end__ __attribute__((section(".tls$zzz"))) = 0;
|
||||
@@ -62,10 +56,8 @@ extern "C" {
|
||||
|
||||
|
||||
PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0;
|
||||
PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
|
||||
PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0;
|
||||
}
|
||||
|
||||
extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) =
|
||||
{
|
||||
(DWORD) &__tls_start__,
|
||||
@@ -75,6 +67,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
(DWORD) 0,
|
||||
(DWORD) 0
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#elif defined(_MSC_VER) && !defined(UNDER_CE)
|
||||
@@ -89,13 +82,13 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
//Definitions required by implementation
|
||||
|
||||
#if (_MSC_VER < 1300) // 1300 == VC++ 7.0
|
||||
typedef void (__cdecl *_PVFV)(void);
|
||||
typedef void (__cdecl *_PVFV)();
|
||||
#define INIRETSUCCESS
|
||||
#define PVAPI void
|
||||
#define PVAPI void __cdecl
|
||||
#else
|
||||
typedef int (__cdecl *_PVFV)(void);
|
||||
typedef int (__cdecl *_PVFV)();
|
||||
#define INIRETSUCCESS 0
|
||||
#define PVAPI int
|
||||
#define PVAPI int __cdecl
|
||||
#endif
|
||||
|
||||
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
|
||||
@@ -112,9 +105,9 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
{
|
||||
//Forward declarations
|
||||
|
||||
static PVAPI on_tls_prepare(void);
|
||||
static PVAPI on_process_init(void);
|
||||
static PVAPI on_process_term(void);
|
||||
static PVAPI on_tls_prepare();
|
||||
static PVAPI on_process_init();
|
||||
static PVAPI on_process_term();
|
||||
static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
|
||||
|
||||
//The .CRT$Xxx information is taken from Codeguru:
|
||||
@@ -169,7 +162,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
#pragma warning(disable:4189)
|
||||
#endif
|
||||
|
||||
PVAPI on_tls_prepare(void)
|
||||
PVAPI on_tls_prepare()
|
||||
{
|
||||
//The following line has an important side effect:
|
||||
//if the TLS directory is not already there, it will
|
||||
@@ -210,7 +203,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
PVAPI on_process_init(void)
|
||||
PVAPI on_process_init()
|
||||
{
|
||||
//Schedule on_thread_exit() to be called for the main
|
||||
//thread before destructors of global objects have been
|
||||
@@ -221,18 +214,18 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
//for destructors of global objects, so that
|
||||
//shouldn't be a problem.
|
||||
|
||||
atexit(on_thread_exit);
|
||||
atexit(boost::on_thread_exit);
|
||||
|
||||
//Call Boost process entry callback here
|
||||
|
||||
on_process_enter();
|
||||
boost::on_process_enter();
|
||||
|
||||
return INIRETSUCCESS;
|
||||
}
|
||||
|
||||
PVAPI on_process_term(void)
|
||||
PVAPI on_process_term()
|
||||
{
|
||||
on_process_exit();
|
||||
boost::on_process_exit();
|
||||
return INIRETSUCCESS;
|
||||
}
|
||||
|
||||
@@ -241,7 +234,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_THREAD_DETACH:
|
||||
on_thread_exit();
|
||||
boost::on_thread_exit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -251,10 +244,10 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_THREAD_DETACH:
|
||||
on_thread_exit();
|
||||
boost::on_thread_exit();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
on_process_exit();
|
||||
boost::on_process_exit();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@@ -265,8 +258,9 @@ extern "C"
|
||||
{
|
||||
extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback;
|
||||
}
|
||||
|
||||
extern "C" void tss_cleanup_implemented(void)
|
||||
namespace boost
|
||||
{
|
||||
void tss_cleanup_implemented()
|
||||
{
|
||||
/*
|
||||
This function's sole purpose is to cause a link error in cases where
|
||||
@@ -282,6 +276,8 @@ extern "C"
|
||||
longer needed and can be removed.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#endif //defined(_MSC_VER) && !defined(UNDER_CE)
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
template<typename T>
|
||||
typename boost::remove_reference<T>::type&& cast_to_rval(T&& t)
|
||||
{
|
||||
return t;
|
||||
return static_cast<typename boost::remove_reference<T>::type&&>(t);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
@@ -556,7 +556,7 @@ void wait_callback(boost::promise<int>& pi)
|
||||
}
|
||||
}
|
||||
|
||||
void do_nothing_callback(boost::promise<int>& pi)
|
||||
void do_nothing_callback(boost::promise<int>& /*pi*/)
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lk(callback_mutex);
|
||||
++callback_called;
|
||||
@@ -1041,6 +1041,8 @@ void test_wait_for_any_from_range()
|
||||
}
|
||||
boost::thread(::cast_to_rval(tasks[i]));
|
||||
|
||||
BOOST_CHECK(boost::wait_for_any(futures,futures)==futures);
|
||||
|
||||
boost::unique_future<int>* const future=boost::wait_for_any(futures,futures+count);
|
||||
|
||||
BOOST_CHECK(future==(futures+i));
|
||||
|
||||
@@ -296,10 +296,80 @@ void test_lock_five_in_range()
|
||||
}
|
||||
}
|
||||
|
||||
void test_lock_ten_in_range()
|
||||
class dummy_iterator:
|
||||
public std::iterator<std::forward_iterator_tag,
|
||||
dummy_mutex>
|
||||
{
|
||||
private:
|
||||
dummy_mutex* p;
|
||||
public:
|
||||
explicit dummy_iterator(dummy_mutex* p_):
|
||||
p(p_)
|
||||
{}
|
||||
|
||||
bool operator==(dummy_iterator const& other) const
|
||||
{
|
||||
return p==other.p;
|
||||
}
|
||||
|
||||
bool operator!=(dummy_iterator const& other) const
|
||||
{
|
||||
return p!=other.p;
|
||||
}
|
||||
|
||||
bool operator<(dummy_iterator const& other) const
|
||||
{
|
||||
return p<other.p;
|
||||
}
|
||||
|
||||
dummy_mutex& operator*() const
|
||||
{
|
||||
return *p;
|
||||
}
|
||||
|
||||
dummy_mutex* operator->() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
dummy_iterator operator++(int)
|
||||
{
|
||||
dummy_iterator temp(*this);
|
||||
++p;
|
||||
return temp;
|
||||
}
|
||||
|
||||
dummy_iterator& operator++()
|
||||
{
|
||||
++p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
void test_lock_five_in_range_custom_iterator()
|
||||
{
|
||||
unsigned const num_mutexes=5;
|
||||
dummy_mutex mutexes[num_mutexes];
|
||||
|
||||
boost::lock(dummy_iterator(mutexes),dummy_iterator(mutexes+num_mutexes));
|
||||
|
||||
for(unsigned i=0;i<num_mutexes;++i)
|
||||
{
|
||||
BOOST_CHECK(mutexes[i].is_locked);
|
||||
}
|
||||
}
|
||||
|
||||
class dummy_mutex2:
|
||||
public dummy_mutex
|
||||
{};
|
||||
|
||||
|
||||
void test_lock_ten_in_range_inherited_mutex()
|
||||
{
|
||||
unsigned const num_mutexes=10;
|
||||
dummy_mutex mutexes[num_mutexes];
|
||||
dummy_mutex2 mutexes[num_mutexes];
|
||||
|
||||
boost::lock(mutexes,mutexes+num_mutexes);
|
||||
|
||||
@@ -510,7 +580,8 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_ten_in_range));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_in_range_custom_iterator));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_ten_in_range_inherited_mutex));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));
|
||||
|
||||
@@ -138,6 +138,14 @@ void test_can_lock_upgrade_if_currently_locked_shared()
|
||||
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
|
||||
}
|
||||
|
||||
void test_can_lock_upgrade_to_unique_if_currently_locked_upgrade()
|
||||
{
|
||||
boost::shared_mutex mtx;
|
||||
boost::upgrade_lock<boost::shared_mutex> l(mtx);
|
||||
boost::upgrade_to_unique_lock<boost::shared_mutex> ul(l);
|
||||
BOOST_CHECK(ul.owns_lock());
|
||||
}
|
||||
|
||||
void test_if_other_thread_has_write_lock_try_lock_shared_returns_false()
|
||||
{
|
||||
|
||||
@@ -282,6 +290,7 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_only_one_upgrade_lock_permitted));
|
||||
test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_if_currently_locked_shared));
|
||||
test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_to_unique_if_currently_locked_upgrade));
|
||||
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_write_lock_try_lock_shared_returns_false));
|
||||
test->add(BOOST_TEST_CASE(&test_if_no_thread_has_lock_try_lock_shared_returns_true));
|
||||
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_shared_lock_try_lock_shared_returns_true));
|
||||
|
||||
Reference in New Issue
Block a user