mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
7 Commits
boost-1.44
...
boost-1.45
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c045b98b5f | ||
|
|
70584af9c0 | ||
|
|
381554f8bc | ||
|
|
4dc1cb1ba1 | ||
|
|
506019dd62 | ||
|
|
e30be60bc4 | ||
|
|
7bfafec128 |
@@ -449,7 +449,7 @@ namespace boost
|
||||
#else
|
||||
template<class charT, class traits>
|
||||
std::basic_ostream<charT, traits>&
|
||||
print(std::basic_ostream<charT, traits>& os)
|
||||
print(std::basic_ostream<charT, traits>& os) const
|
||||
{
|
||||
if(thread_data)
|
||||
{
|
||||
|
||||
@@ -912,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>));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,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
|
||||
@@ -958,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;
|
||||
}
|
||||
|
||||
@@ -1047,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:
|
||||
@@ -1079,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
|
||||
@@ -1092,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
0
src/pthread/once.cpp
Executable file → Normal file
0
src/pthread/once.cpp
Executable file → Normal file
@@ -411,6 +411,7 @@ namespace boost
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -56,7 +56,10 @@ namespace boost
|
||||
void set_current_thread_data(detail::thread_data_base* new_data)
|
||||
{
|
||||
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
|
||||
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
|
||||
if(current_thread_tls_key)
|
||||
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
|
||||
else
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_THREADEX
|
||||
@@ -221,7 +224,15 @@ namespace boost
|
||||
void make_external_thread_data()
|
||||
{
|
||||
externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
|
||||
set_current_thread_data(me);
|
||||
try
|
||||
{
|
||||
set_current_thread_data(me);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
detail::heap_delete(me);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
detail::thread_data_base* get_or_make_current_thread_data()
|
||||
@@ -540,8 +551,8 @@ namespace boost
|
||||
{
|
||||
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
|
||||
thread_exit_callback_node* const new_node=
|
||||
heap_new<thread_exit_callback_node>(func,
|
||||
current_thread_data->thread_exit_callbacks);
|
||||
heap_new<thread_exit_callback_node>(
|
||||
func,current_thread_data->thread_exit_callbacks);
|
||||
current_thread_data->thread_exit_callbacks=new_node;
|
||||
}
|
||||
|
||||
@@ -583,10 +594,11 @@ namespace boost
|
||||
current_node->func=func;
|
||||
current_node->value=tss_data;
|
||||
}
|
||||
else
|
||||
else if(func && tss_data)
|
||||
{
|
||||
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
|
||||
tss_data_node* const new_node=heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
|
||||
tss_data_node* const new_node=
|
||||
heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
|
||||
current_thread_data->tss_data=new_node;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
#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 )() __attribute__((section(".ctors"))) = boost::on_process_enter;
|
||||
@@ -50,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__,
|
||||
@@ -63,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)
|
||||
|
||||
Reference in New Issue
Block a user