mirror of
https://github.com/boostorg/thread.git
synced 2026-02-07 23:02:13 +00:00
Compare commits
84 Commits
svn-branch
...
boost-1.42
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8584eea537 | ||
|
|
9087fd904d | ||
|
|
66ac6942b6 | ||
|
|
20980fe54d | ||
|
|
fb54acfe69 | ||
|
|
0e69edd066 | ||
|
|
9255a035f4 | ||
|
|
fbdc23f482 | ||
|
|
8ab0d5acdd | ||
|
|
5af323102a | ||
|
|
0997fad8ec | ||
|
|
8749696538 | ||
|
|
9beea23f63 | ||
|
|
2978d43a5d | ||
|
|
a264766584 | ||
|
|
f03a9bfcf3 | ||
|
|
60fdcddcb5 | ||
|
|
525d190f91 | ||
|
|
1e0154335b | ||
|
|
413c29a5e4 | ||
|
|
30bb6143c1 | ||
|
|
991ac727c6 | ||
|
|
569a78649f | ||
|
|
7caec1ec33 | ||
|
|
7fd3fb48b1 | ||
|
|
a32a3b37db | ||
|
|
88f6076f3c | ||
|
|
b4d12e08dd | ||
|
|
1c0f470032 | ||
|
|
92b8789532 | ||
|
|
8f61694057 | ||
|
|
67f7de5305 | ||
|
|
6faecefb73 | ||
|
|
68c5bd44e8 | ||
|
|
3656277053 | ||
|
|
19846ff356 | ||
|
|
db2aaa04fd | ||
|
|
b48f9aa609 | ||
|
|
7915ab1ec6 | ||
|
|
f0faf88d66 | ||
|
|
7dd7537f5f | ||
|
|
f51680e8d9 | ||
|
|
a6bc072c6d | ||
|
|
85f2508157 | ||
|
|
ebb6c8d637 | ||
|
|
ddc83e270c | ||
|
|
0173148a2e | ||
|
|
69a4ec6c00 | ||
|
|
2d52219af2 | ||
|
|
1f87a9e4c0 | ||
|
|
ba8afde42b | ||
|
|
93f677cba6 | ||
|
|
dfd865d67d | ||
|
|
96a04402db | ||
|
|
78e644c7c1 | ||
|
|
89cc7fc34e | ||
|
|
974754598e | ||
|
|
87acbb406d | ||
|
|
597517157c | ||
|
|
a0b816be8c | ||
|
|
4a056924d2 | ||
|
|
d5a81f990c | ||
|
|
da8c92f057 | ||
|
|
866b33c808 | ||
|
|
182daf0b17 | ||
|
|
2552febc2a | ||
|
|
eb9db9b683 | ||
|
|
11dbdfca4d | ||
|
|
f49de9ec10 | ||
|
|
3a7e569a65 | ||
|
|
c376c1a62a | ||
|
|
fbbc52063a | ||
|
|
78b4fe3d07 | ||
|
|
b8c8b250b1 | ||
|
|
b26d01c8d7 | ||
|
|
4dbd8a66af | ||
|
|
cb4d739fd1 | ||
|
|
11f913e8fb | ||
|
|
0b6054a919 | ||
|
|
e7620a1050 | ||
|
|
811a03f281 | ||
|
|
2528bd0b8f | ||
|
|
ed587be470 | ||
|
|
55b48874a4 |
@@ -45,15 +45,6 @@ all subsequent `call_once` invocations on the same `once_flag` object. ]]
|
||||
|
||||
[[Throws:] [`thread_resource_error` when the effects cannot be achieved. or any exception propagated from `func`.]]
|
||||
|
||||
[[Note:] [The function passed to `call_once` must not also call
|
||||
`call_once` passing the same `once_flag` object. This may cause
|
||||
deadlock, or invoking the passed function a second time. The
|
||||
alternative is to allow the second call to return immediately, but
|
||||
that assumes the code knows it has been called recursively, and can
|
||||
proceed even though the call to `call_once` didn't actually call the
|
||||
function, in which case it could also avoid calling `call_once`
|
||||
recursively.]]
|
||||
|
||||
]
|
||||
|
||||
void call_once(void (*func)(),once_flag& flag);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#define BOOST_BARRIER_JDM030602_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
@@ -28,7 +27,7 @@ namespace boost
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
boost::throw_exception(std::invalid_argument("count cannot be zero."));
|
||||
throw std::invalid_argument("count cannot be zero.");
|
||||
}
|
||||
|
||||
bool wait()
|
||||
|
||||
@@ -445,7 +445,7 @@ namespace boost
|
||||
{
|
||||
virtual ~thread_exit_function_base()
|
||||
{}
|
||||
virtual void operator()()=0;
|
||||
virtual void operator()() const=0;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
@@ -458,13 +458,13 @@ namespace boost
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
void operator()() const
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
|
||||
void add_thread_exit_function(thread_exit_function_base*);
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <algorithm>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
@@ -674,7 +673,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
throw future_uninitialized();
|
||||
}
|
||||
|
||||
return future->get();
|
||||
@@ -710,7 +709,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
throw future_uninitialized();
|
||||
}
|
||||
future->wait(false);
|
||||
}
|
||||
@@ -725,7 +724,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return future->timed_wait_until(abs_time);
|
||||
}
|
||||
@@ -831,7 +830,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
throw future_uninitialized();
|
||||
}
|
||||
|
||||
return future->get();
|
||||
@@ -867,7 +866,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
throw future_uninitialized();
|
||||
}
|
||||
future->wait(false);
|
||||
}
|
||||
@@ -882,7 +881,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
throw future_uninitialized();
|
||||
}
|
||||
return future->timed_wait_until(abs_time);
|
||||
}
|
||||
@@ -975,7 +974,7 @@ namespace boost
|
||||
lazy_init();
|
||||
if(future_obtained)
|
||||
{
|
||||
boost::throw_exception(future_already_retrieved());
|
||||
throw future_already_retrieved();
|
||||
}
|
||||
future_obtained=true;
|
||||
return unique_future<R>(future);
|
||||
@@ -987,7 +986,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
future->mark_finished_with_result_internal(r);
|
||||
}
|
||||
@@ -999,7 +998,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
|
||||
}
|
||||
@@ -1010,7 +1009,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
future->mark_exceptional_finish_internal(p);
|
||||
}
|
||||
@@ -1110,7 +1109,7 @@ namespace boost
|
||||
|
||||
if(future_obtained)
|
||||
{
|
||||
boost::throw_exception(future_already_retrieved());
|
||||
throw future_already_retrieved();
|
||||
}
|
||||
future_obtained=true;
|
||||
return unique_future<void>(future);
|
||||
@@ -1122,7 +1121,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
future->mark_finished_with_result_internal();
|
||||
}
|
||||
@@ -1133,7 +1132,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
throw promise_already_satisfied();
|
||||
}
|
||||
future->mark_exceptional_finish_internal(p);
|
||||
}
|
||||
@@ -1165,7 +1164,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lk(this->mutex);
|
||||
if(started)
|
||||
{
|
||||
boost::throw_exception(task_already_started());
|
||||
throw task_already_started();
|
||||
}
|
||||
started=true;
|
||||
}
|
||||
@@ -1327,7 +1326,7 @@ namespace boost
|
||||
{
|
||||
if(!task)
|
||||
{
|
||||
boost::throw_exception(task_moved());
|
||||
throw task_moved();
|
||||
}
|
||||
else if(!future_obtained)
|
||||
{
|
||||
@@ -1336,7 +1335,7 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::throw_exception(future_already_retrieved());
|
||||
throw future_already_retrieved();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1346,7 +1345,7 @@ namespace boost
|
||||
{
|
||||
if(!task)
|
||||
{
|
||||
boost::throw_exception(task_moved());
|
||||
throw task_moved();
|
||||
}
|
||||
task->run();
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock();
|
||||
is_locked=true;
|
||||
@@ -353,7 +353,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock();
|
||||
return is_locked;
|
||||
@@ -379,7 +379,7 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock();
|
||||
is_locked=false;
|
||||
@@ -570,7 +570,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock_shared();
|
||||
is_locked=true;
|
||||
@@ -579,7 +579,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock_shared();
|
||||
return is_locked;
|
||||
@@ -588,7 +588,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -598,7 +598,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -607,7 +607,7 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock_shared();
|
||||
is_locked=false;
|
||||
@@ -733,7 +733,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock_upgrade();
|
||||
is_locked=true;
|
||||
@@ -742,7 +742,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock_upgrade();
|
||||
return is_locked;
|
||||
@@ -751,7 +751,7 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock_upgrade();
|
||||
is_locked=false;
|
||||
|
||||
@@ -57,13 +57,13 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw 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());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
~condition_variable_any()
|
||||
@@ -87,7 +87,7 @@ namespace boost
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(condition_error());
|
||||
throw condition_error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace boost
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(condition_error());
|
||||
throw condition_error();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <pthread.h>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
@@ -31,7 +30,7 @@ namespace boost
|
||||
int const res=pthread_cond_init(&cond,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
~condition_variable()
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
@@ -38,7 +37,7 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
~mutex()
|
||||
@@ -90,14 +89,14 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
is_locked=false;
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
@@ -59,13 +58,10 @@ namespace boost
|
||||
if(flag.epoch==uninitialized_flag)
|
||||
{
|
||||
flag.epoch=being_initialized;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif
|
||||
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
|
||||
f();
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -73,7 +69,6 @@ namespace boost
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
flag.epoch=--detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
@@ -43,18 +42,18 @@ namespace boost
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
if(init_attr_res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
}
|
||||
@@ -112,32 +111,32 @@ namespace boost
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
if(init_attr_res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw 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());
|
||||
throw 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());
|
||||
throw 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());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
is_locked=false;
|
||||
count=0;
|
||||
|
||||
@@ -61,30 +61,15 @@ namespace boost
|
||||
|
||||
void lock()
|
||||
{
|
||||
if(try_lock())
|
||||
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
|
||||
}
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
{
|
||||
if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
long old_count=active_count;
|
||||
mark_waiting_and_try_lock(old_count);
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
bool lock_acquired=false;
|
||||
void* const sem=get_event();
|
||||
|
||||
do
|
||||
{
|
||||
BOOST_VERIFY(win32::WaitForSingleObject(
|
||||
sem,::boost::detail::win32::infinite)==0);
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
}
|
||||
while(!lock_acquired);
|
||||
}
|
||||
}
|
||||
void mark_waiting_and_try_lock(long& old_count)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
|
||||
@@ -95,33 +80,6 @@ namespace boost
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_waiting_and_try_lock(long& old_count)
|
||||
{
|
||||
old_count&=~lock_flag_value;
|
||||
old_count|=event_set_flag_value;
|
||||
for(;;)
|
||||
{
|
||||
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
|
||||
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
|
||||
if(current==old_count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
{
|
||||
if(try_lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
long old_count=active_count;
|
||||
mark_waiting_and_try_lock(old_count);
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
@@ -135,7 +93,18 @@ namespace boost
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
old_count&=~lock_flag_value;
|
||||
old_count|=event_set_flag_value;
|
||||
for(;;)
|
||||
{
|
||||
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
|
||||
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
|
||||
if(current==old_count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
}
|
||||
while(!lock_acquired);
|
||||
|
||||
@@ -30,47 +30,81 @@ namespace std
|
||||
|
||||
namespace boost
|
||||
{
|
||||
struct once_flag
|
||||
{
|
||||
long status;
|
||||
long count;
|
||||
long throw_count;
|
||||
void* event_handle;
|
||||
typedef long once_flag;
|
||||
|
||||
~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
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline void* allocate_event_handle(void*& handle)
|
||||
struct win32_mutex_scoped_lock
|
||||
{
|
||||
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)
|
||||
void* const mutex_handle;
|
||||
explicit win32_mutex_scoped_lock(void* mutex_handle_):
|
||||
mutex_handle(mutex_handle_)
|
||||
{
|
||||
::boost::detail::win32::CloseHandle(new_handle);
|
||||
return event_handle;
|
||||
BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
|
||||
}
|
||||
return new_handle;
|
||||
~win32_mutex_scoped_lock()
|
||||
{
|
||||
BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
|
||||
}
|
||||
private:
|
||||
void operator=(win32_mutex_scoped_lock&);
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
template <class I>
|
||||
void int_to_string(I p, wchar_t* buf)
|
||||
{
|
||||
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
|
||||
{
|
||||
*buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f);
|
||||
}
|
||||
*buf = 0;
|
||||
}
|
||||
#else
|
||||
template <class I>
|
||||
void int_to_string(I p, char* buf)
|
||||
{
|
||||
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
|
||||
{
|
||||
*buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
|
||||
}
|
||||
*buf = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// create a named mutex. It doesn't really matter what this name is
|
||||
// as long as it is unique both to this process, and to the address of "flag":
|
||||
inline void* create_once_mutex(void* flag_address)
|
||||
{
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
typedef wchar_t char_type;
|
||||
static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#else
|
||||
typedef char char_type;
|
||||
static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#endif
|
||||
unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type);
|
||||
unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1;
|
||||
unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
|
||||
char_type mutex_name[once_mutex_name_length];
|
||||
|
||||
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
|
||||
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);
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return win32::CreateMutexW(0, 0, mutex_name);
|
||||
#else
|
||||
return win32::CreateMutexA(0, 0, mutex_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -80,98 +114,18 @@ namespace boost
|
||||
// Try for a quick win: if the procedure has already been called
|
||||
// just skip through:
|
||||
long const function_complete_flag_value=0xc15730e2;
|
||||
long const running_value=0x7f0725e3;
|
||||
long status;
|
||||
bool counted=false;
|
||||
void* event_handle=0;
|
||||
long throw_count=0;
|
||||
|
||||
while((status=::boost::detail::interlocked_read_acquire(&flag.status))
|
||||
!=function_complete_flag_value)
|
||||
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
|
||||
{
|
||||
status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
|
||||
if(!status)
|
||||
void* const mutex_handle(::boost::detail::create_once_mutex(&flag));
|
||||
BOOST_ASSERT(mutex_handle);
|
||||
detail::win32::handle_manager const closer(mutex_handle);
|
||||
detail::win32_mutex_scoped_lock const lock(mutex_handle);
|
||||
|
||||
if(flag!=function_complete_flag_value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
::boost::detail::win32::ResetEvent(event_handle);
|
||||
}
|
||||
f();
|
||||
if(!counted)
|
||||
{
|
||||
BOOST_INTERLOCKED_INCREMENT(&flag.count);
|
||||
counted=true;
|
||||
}
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value);
|
||||
if(!event_handle &&
|
||||
(::boost::detail::interlocked_read_acquire(&flag.count)>1))
|
||||
{
|
||||
event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
::boost::detail::win32::SetEvent(event_handle);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if(!counted)
|
||||
{
|
||||
BOOST_INTERLOCKED_INCREMENT(&flag.count);
|
||||
counted=true;
|
||||
status=::boost::detail::interlocked_read_acquire(&flag.status);
|
||||
if(status==function_complete_flag_value)
|
||||
{
|
||||
break;
|
||||
}
|
||||
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
|
||||
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);
|
||||
}
|
||||
f();
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "thread_primitives.hpp"
|
||||
#include <stdexcept>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
@@ -61,7 +60,7 @@ namespace boost
|
||||
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
|
||||
if(!heap_memory)
|
||||
{
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return heap_memory;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
@@ -178,7 +177,7 @@ namespace boost
|
||||
#endif
|
||||
if(!res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -192,7 +191,7 @@ namespace boost
|
||||
#endif
|
||||
if(!res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -205,7 +204,7 @@ namespace boost
|
||||
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
if(!success)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#ifdef __linux__
|
||||
#include <sys/sysinfo.h>
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
@@ -187,7 +186,7 @@ namespace boost
|
||||
if (res != 0)
|
||||
{
|
||||
thread_info->self.reset();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 2009 Anthony Williams
|
||||
//
|
||||
// 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)
|
||||
|
||||
// boostinspect:nounnamed
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace {
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||
@@ -21,7 +18,7 @@ inline void to_time(int milliseconds, boost::xtime& xt)
|
||||
{
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
|
||||
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
|
||||
@@ -58,7 +55,7 @@ inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
{
|
||||
@@ -89,7 +86,7 @@ inline void to_duration(boost::xtime xt, int& milliseconds)
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
milliseconds = 0;
|
||||
@@ -111,7 +108,7 @@ inline void to_microduration(boost::xtime xt, int& microseconds)
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
microseconds = 0;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/detail/tss_hooks.hpp>
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
|
||||
@@ -189,7 +188,7 @@ namespace boost
|
||||
uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
|
||||
if(!new_thread)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
intrusive_ptr_add_ref(thread_info.get());
|
||||
thread_info->thread_handle=(detail::win32::handle)(new_thread);
|
||||
|
||||
@@ -42,7 +42,6 @@ rule thread-run ( sources )
|
||||
[ thread-run test_thread_move_return.cpp ]
|
||||
[ thread-run test_thread_launching.cpp ]
|
||||
[ thread-run test_thread_mf.cpp ]
|
||||
[ thread-run test_thread_exit.cpp ]
|
||||
[ thread-run test_move_function.cpp ]
|
||||
[ thread-run test_mutex.cpp ]
|
||||
[ thread-run test_condition_notify_one.cpp ]
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// (C) Copyright 2009 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "boost/thread/thread.hpp"
|
||||
#include "boost/thread/mutex.hpp"
|
||||
#include "boost/thread/condition.hpp"
|
||||
#include "boost/thread/future.hpp"
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
boost::thread::id exit_func_thread_id;
|
||||
|
||||
void exit_func()
|
||||
{
|
||||
exit_func_thread_id=boost::this_thread::get_id();
|
||||
}
|
||||
|
||||
void tf1()
|
||||
{
|
||||
boost::this_thread::at_thread_exit(exit_func);
|
||||
BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id());
|
||||
}
|
||||
|
||||
void test_thread_exit_func_runs_when_thread_exits()
|
||||
{
|
||||
exit_func_thread_id=boost::thread::id();
|
||||
boost::thread t(tf1);
|
||||
boost::thread::id const t_id=t.get_id();
|
||||
t.join();
|
||||
BOOST_CHECK(exit_func_thread_id==t_id);
|
||||
}
|
||||
|
||||
struct fo
|
||||
{
|
||||
void operator()()
|
||||
{
|
||||
exit_func_thread_id=boost::this_thread::get_id();
|
||||
}
|
||||
};
|
||||
|
||||
void tf2()
|
||||
{
|
||||
boost::this_thread::at_thread_exit(fo());
|
||||
BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id());
|
||||
}
|
||||
|
||||
|
||||
void test_can_use_function_object_for_exit_func()
|
||||
{
|
||||
exit_func_thread_id=boost::thread::id();
|
||||
boost::thread t(tf2);
|
||||
boost::thread::id const t_id=t.get_id();
|
||||
t.join();
|
||||
BOOST_CHECK(exit_func_thread_id==t_id);
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: futures test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(test_thread_exit_func_runs_when_thread_exits));
|
||||
test->add(BOOST_TEST_CASE(test_can_use_function_object_for_exit_func));
|
||||
|
||||
return test;
|
||||
}
|
||||
Reference in New Issue
Block a user