mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
194 Commits
boost-1.41
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5664452c47 | ||
|
|
58fd27399e | ||
|
|
5f88ba1e47 | ||
|
|
ab569461d8 | ||
|
|
7093fc670b | ||
|
|
6f2b030253 | ||
|
|
0e61e679af | ||
|
|
b40998e1b5 | ||
|
|
174d701bc3 | ||
|
|
f2143d08b9 | ||
|
|
1273e2620d | ||
|
|
c719f6e37e | ||
|
|
37922d8ce0 | ||
|
|
7b79a31f40 | ||
|
|
9a09406f77 | ||
|
|
9bdb778478 | ||
|
|
9621dafe46 | ||
|
|
d7c9837844 | ||
|
|
27bb7803ae | ||
|
|
c0e1086f2c | ||
|
|
ffa751c617 | ||
|
|
b8ad60a2d6 | ||
|
|
5db0aac816 | ||
|
|
3fae7c5184 | ||
|
|
47889a8f22 | ||
|
|
8d22c3869b | ||
|
|
235ed4afe0 | ||
|
|
627cb7f774 | ||
|
|
09021af350 | ||
|
|
31c280d1fa | ||
|
|
629f344f34 | ||
|
|
db5f924e24 | ||
|
|
9be3eb282a | ||
|
|
effd891a16 | ||
|
|
13db35cbf5 | ||
|
|
0f2d480e3c | ||
|
|
9edc61e37b | ||
|
|
f4dab6aac5 | ||
|
|
9e0550d140 | ||
|
|
0d1701c509 | ||
|
|
f2f62f93ea | ||
|
|
8a329f66fb | ||
|
|
05d4c52918 | ||
|
|
8fd0dd0cc0 | ||
|
|
8eea5811ba | ||
|
|
a154c2adab | ||
|
|
10bf4ed576 | ||
|
|
60d12dd395 | ||
|
|
b4e9be3c52 | ||
|
|
dcebae6d4a | ||
|
|
0d776bcd26 | ||
|
|
2d6ed47cf2 | ||
|
|
ea06434425 | ||
|
|
6508eff95e | ||
|
|
69930684a9 | ||
|
|
b1931a3eda | ||
|
|
63b44d4e32 | ||
|
|
f7cb8d8141 | ||
|
|
48c857e02c | ||
|
|
442dc58e0f | ||
|
|
25460c652c | ||
|
|
31a98f0a1e | ||
|
|
36c44b6f45 | ||
|
|
27426b18d1 | ||
|
|
3ea9ce1c8c | ||
|
|
4dfc636c84 | ||
|
|
5fe4312c6c | ||
|
|
63e675a6bb | ||
|
|
e92aeac7d7 | ||
|
|
f1f7eac1f2 | ||
|
|
eff0c84553 | ||
|
|
58c8ce61c7 | ||
|
|
6ac5e6953a | ||
|
|
5d9ad59af2 | ||
|
|
3c48a05437 | ||
|
|
4462124ff2 | ||
|
|
373f557ef7 | ||
|
|
495e561398 | ||
|
|
d24a579033 | ||
|
|
77130424b4 | ||
|
|
eb30688937 | ||
|
|
880bac0633 | ||
|
|
851d6a987f | ||
|
|
9bebd7b35f | ||
|
|
309acb9597 | ||
|
|
a56887167e | ||
|
|
e984dff4e4 | ||
|
|
685e4d446b | ||
|
|
8af680f307 | ||
|
|
6c60cce60d | ||
|
|
5882a675bb | ||
|
|
a5e95845b3 | ||
|
|
5b83d81e40 | ||
|
|
c8e5ad564d | ||
|
|
5edfa273ff | ||
|
|
4db57bcb10 | ||
|
|
3f13340903 | ||
|
|
6abb53c9d3 | ||
|
|
fdd20a519e | ||
|
|
67cc49f333 | ||
|
|
31a34cd0b5 | ||
|
|
ef8c08ba99 | ||
|
|
2991ca6c6f | ||
|
|
52bace18b2 | ||
|
|
767d14ae4f | ||
|
|
1a5c911e36 | ||
|
|
6e42a04e43 | ||
|
|
28be2cfeef | ||
|
|
8be168fd87 | ||
|
|
eee95fef57 | ||
|
|
9ea179b052 | ||
|
|
6868280409 | ||
|
|
e00b764454 | ||
|
|
999613c686 | ||
|
|
c2661d7eb5 | ||
|
|
4d21dd1f47 | ||
|
|
a0a0e57527 | ||
|
|
d8af0d0b4e | ||
|
|
113288e3b0 | ||
|
|
afecfd7c2d | ||
|
|
94d89aac5f | ||
|
|
8831b13efc | ||
|
|
01f99da03a | ||
|
|
080654e3ef | ||
|
|
2ac2eb2a61 | ||
|
|
61b940b705 | ||
|
|
4a4f87e017 | ||
|
|
6d5e7f63a7 | ||
|
|
f77285f375 | ||
|
|
dc5d03a6dc | ||
|
|
ea0961b7f6 | ||
|
|
33d9f9774c | ||
|
|
86097fa038 | ||
|
|
70d9dbc45a | ||
|
|
3926fd3a20 | ||
|
|
7861cf1146 | ||
|
|
0516b86a6e | ||
|
|
ec735d3e9b | ||
|
|
1c5c070983 | ||
|
|
a5c02b73dc | ||
|
|
918b920670 | ||
|
|
de67d2e27e | ||
|
|
bc89df04cb | ||
|
|
c26a4cf082 | ||
|
|
6e1a866b13 | ||
|
|
f91986ad0d | ||
|
|
795cc23f3e | ||
|
|
a3695bd4a0 | ||
|
|
08dc521daf | ||
|
|
8b916d21b1 | ||
|
|
c40f47a78a | ||
|
|
e9fb470b06 | ||
|
|
343d049772 | ||
|
|
86f9480da4 | ||
|
|
8696b610ca | ||
|
|
6f13227eda | ||
|
|
58d5110e61 | ||
|
|
76e53c7bc5 | ||
|
|
cfb08be1a8 | ||
|
|
b5bbb7fb1c | ||
|
|
a76c33f8cc | ||
|
|
810306b8f3 | ||
|
|
6c22bdb3bd | ||
|
|
6a0d3e98bc | ||
|
|
3809321037 | ||
|
|
eef695bdf0 | ||
|
|
ab01ab1e4d | ||
|
|
c8d8a108a7 | ||
|
|
7afd9efcc5 | ||
|
|
56ded87ad2 | ||
|
|
82e503339b | ||
|
|
713d0c7ace | ||
|
|
25ad6e3f8f | ||
|
|
df0197b617 | ||
|
|
a89c4f01ad | ||
|
|
ae67099633 | ||
|
|
57542d3a5c | ||
|
|
9a1da14116 | ||
|
|
ed050d753d | ||
|
|
8bec363710 | ||
|
|
7c68e190a9 | ||
|
|
7ebf5ea3d1 | ||
|
|
11e0435a4b | ||
|
|
d15ee57cd1 | ||
|
|
56d660b7fd | ||
|
|
792958e693 | ||
|
|
914e67dc04 | ||
|
|
b50a7ccb61 | ||
|
|
f827709d42 | ||
|
|
36abb42175 | ||
|
|
40f3b1b4c8 | ||
|
|
4f35e25688 | ||
|
|
270e88edd7 | ||
|
|
5ded171247 |
@@ -45,6 +45,15 @@ 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);
|
||||
|
||||
@@ -916,6 +916,13 @@ exits (even if the thread has been interrupted).]]
|
||||
[[Throws:] [`std::bad_alloc` if memory cannot be allocated for the copy of the function, __thread_resource_error__ if any other
|
||||
error occurs within the thread library. Any exception thrown whilst copying `func` into internal storage.]]
|
||||
|
||||
[[Note:] [This function is *not* called if the thread was terminated
|
||||
forcefully using platform-specific APIs, or if the thread is
|
||||
terminated due to a call to `exit()`, `abort()` or
|
||||
`std::terminate()`. In particular, returning from `main()` is
|
||||
equivalent to call to `exit()`, so will not call any functions
|
||||
registered with `at_thread_exit()`]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#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>
|
||||
@@ -27,7 +28,7 @@ namespace boost
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
throw std::invalid_argument("count cannot be zero.");
|
||||
boost::throw_exception(std::invalid_argument("count cannot be zero."));
|
||||
}
|
||||
|
||||
bool wait()
|
||||
|
||||
@@ -39,10 +39,13 @@ namespace boost
|
||||
public detail::thread_data_base
|
||||
{
|
||||
public:
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
thread_data(F&& f_):
|
||||
f(static_cast<F&&>(f_))
|
||||
{}
|
||||
thread_data(F& f_):
|
||||
f(f_)
|
||||
{}
|
||||
#else
|
||||
thread_data(F f_):
|
||||
f(f_)
|
||||
@@ -119,7 +122,7 @@ namespace boost
|
||||
|
||||
detail::thread_data_ptr get_thread_info() const;
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename F>
|
||||
static inline detail::thread_data_ptr make_thread_info(F&& f)
|
||||
{
|
||||
@@ -127,7 +130,7 @@ namespace boost
|
||||
}
|
||||
static inline detail::thread_data_ptr make_thread_info(void (*f)())
|
||||
{
|
||||
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
|
||||
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f)));
|
||||
}
|
||||
#else
|
||||
template<typename F>
|
||||
@@ -141,8 +144,8 @@ namespace boost
|
||||
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
|
||||
}
|
||||
|
||||
struct dummy;
|
||||
#endif
|
||||
struct dummy;
|
||||
public:
|
||||
#ifdef __SUNPRO_CC
|
||||
thread(const volatile thread&);
|
||||
@@ -150,13 +153,22 @@ namespace boost
|
||||
thread();
|
||||
~thread();
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#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))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
#else
|
||||
template <class F>
|
||||
thread(F&& f):
|
||||
thread_info(make_thread_info(static_cast<F&&>(f)))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
#endif
|
||||
|
||||
thread(thread&& other)
|
||||
{
|
||||
@@ -343,10 +355,14 @@ namespace boost
|
||||
return lhs.swap(rhs);
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
inline thread&& move(thread& t)
|
||||
{
|
||||
return static_cast<thread&&>(t);
|
||||
}
|
||||
inline thread&& move(thread&& t)
|
||||
{
|
||||
return t;
|
||||
return static_cast<thread&&>(t);
|
||||
}
|
||||
#else
|
||||
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
|
||||
@@ -445,7 +461,7 @@ namespace boost
|
||||
{
|
||||
virtual ~thread_exit_function_base()
|
||||
{}
|
||||
virtual void operator()() const=0;
|
||||
virtual void operator()()=0;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
@@ -458,13 +474,13 @@ namespace boost
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void operator()() const
|
||||
void operator()()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
void add_thread_exit_function(thread_exit_function_base*);
|
||||
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// (C) Copyright 2008-9 Anthony Williams
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -16,6 +16,7 @@
|
||||
#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>
|
||||
@@ -218,7 +219,7 @@ namespace boost
|
||||
struct future_traits
|
||||
{
|
||||
typedef boost::scoped_ptr<T> storage_type;
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
typedef T const& source_reference_type;
|
||||
struct dummy;
|
||||
typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
|
||||
@@ -323,7 +324,7 @@ namespace boost
|
||||
move_dest_type get()
|
||||
{
|
||||
wait();
|
||||
return *result;
|
||||
return static_cast<move_dest_type>(*result);
|
||||
}
|
||||
|
||||
future_state::state get_state()
|
||||
@@ -403,13 +404,14 @@ namespace boost
|
||||
|
||||
struct all_futures_lock
|
||||
{
|
||||
unsigned count;
|
||||
typedef std::vector<registered_waiter>::size_type count_type;
|
||||
count_type count;
|
||||
boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
|
||||
|
||||
all_futures_lock(std::vector<registered_waiter>& futures):
|
||||
count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
|
||||
{
|
||||
for(unsigned i=0;i<count;++i)
|
||||
for(count_type i=0;i<count;++i)
|
||||
{
|
||||
locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
|
||||
}
|
||||
@@ -632,7 +634,7 @@ namespace boost
|
||||
~unique_future()
|
||||
{}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
unique_future(unique_future && other)
|
||||
{
|
||||
future.swap(other.future);
|
||||
@@ -673,7 +675,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
throw future_uninitialized();
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
|
||||
return future->get();
|
||||
@@ -709,7 +711,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
throw future_uninitialized();
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
future->wait(false);
|
||||
}
|
||||
@@ -724,7 +726,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
throw future_uninitialized();
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
return future->timed_wait_until(abs_time);
|
||||
}
|
||||
@@ -767,7 +769,7 @@ namespace boost
|
||||
future=other.future;
|
||||
return *this;
|
||||
}
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
shared_future(shared_future && other)
|
||||
{
|
||||
future.swap(other.future);
|
||||
@@ -830,7 +832,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
throw future_uninitialized();
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
|
||||
return future->get();
|
||||
@@ -866,7 +868,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
throw future_uninitialized();
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
future->wait(false);
|
||||
}
|
||||
@@ -881,7 +883,7 @@ namespace boost
|
||||
{
|
||||
if(!future)
|
||||
{
|
||||
throw future_uninitialized();
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
return future->timed_wait_until(abs_time);
|
||||
}
|
||||
@@ -929,7 +931,7 @@ namespace boost
|
||||
}
|
||||
|
||||
// Assignment
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
promise(promise && rhs):
|
||||
future_obtained(rhs.future_obtained)
|
||||
{
|
||||
@@ -974,7 +976,7 @@ namespace boost
|
||||
lazy_init();
|
||||
if(future_obtained)
|
||||
{
|
||||
throw future_already_retrieved();
|
||||
boost::throw_exception(future_already_retrieved());
|
||||
}
|
||||
future_obtained=true;
|
||||
return unique_future<R>(future);
|
||||
@@ -986,7 +988,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
throw promise_already_satisfied();
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
}
|
||||
future->mark_finished_with_result_internal(r);
|
||||
}
|
||||
@@ -998,7 +1000,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
throw promise_already_satisfied();
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
}
|
||||
future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
|
||||
}
|
||||
@@ -1009,7 +1011,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
throw promise_already_satisfied();
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
}
|
||||
future->mark_exceptional_finish_internal(p);
|
||||
}
|
||||
@@ -1063,7 +1065,7 @@ namespace boost
|
||||
}
|
||||
|
||||
// Assignment
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
promise(promise && rhs):
|
||||
future_obtained(rhs.future_obtained)
|
||||
{
|
||||
@@ -1109,7 +1111,7 @@ namespace boost
|
||||
|
||||
if(future_obtained)
|
||||
{
|
||||
throw future_already_retrieved();
|
||||
boost::throw_exception(future_already_retrieved());
|
||||
}
|
||||
future_obtained=true;
|
||||
return unique_future<void>(future);
|
||||
@@ -1121,7 +1123,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
throw promise_already_satisfied();
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
}
|
||||
future->mark_finished_with_result_internal();
|
||||
}
|
||||
@@ -1132,7 +1134,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lock(future->mutex);
|
||||
if(future->done)
|
||||
{
|
||||
throw promise_already_satisfied();
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
}
|
||||
future->mark_exceptional_finish_internal(p);
|
||||
}
|
||||
@@ -1164,7 +1166,7 @@ namespace boost
|
||||
boost::lock_guard<boost::mutex> lk(this->mutex);
|
||||
if(started)
|
||||
{
|
||||
throw task_already_started();
|
||||
boost::throw_exception(task_already_started());
|
||||
}
|
||||
started=true;
|
||||
}
|
||||
@@ -1283,7 +1285,7 @@ namespace boost
|
||||
}
|
||||
|
||||
// assignment
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
packaged_task(packaged_task&& other):
|
||||
future_obtained(other.future_obtained)
|
||||
{
|
||||
@@ -1326,7 +1328,7 @@ namespace boost
|
||||
{
|
||||
if(!task)
|
||||
{
|
||||
throw task_moved();
|
||||
boost::throw_exception(task_moved());
|
||||
}
|
||||
else if(!future_obtained)
|
||||
{
|
||||
@@ -1335,7 +1337,7 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
throw future_already_retrieved();
|
||||
boost::throw_exception(future_already_retrieved());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,7 +1347,7 @@ namespace boost
|
||||
{
|
||||
if(!task)
|
||||
{
|
||||
throw task_moved();
|
||||
boost::throw_exception(task_moved());
|
||||
}
|
||||
task->run();
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace boost
|
||||
{
|
||||
timed_lock(target_time);
|
||||
}
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
unique_lock(unique_lock&& other):
|
||||
m(other.m),is_locked(other.is_locked)
|
||||
{
|
||||
@@ -321,17 +321,17 @@ namespace boost
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
void swap(unique_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
void swap(detail::thread_move_t<unique_lock<Mutex> > other)
|
||||
{
|
||||
std::swap(m,other->m);
|
||||
std::swap(is_locked,other->is_locked);
|
||||
}
|
||||
#endif
|
||||
void swap(unique_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
|
||||
~unique_lock()
|
||||
{
|
||||
@@ -344,7 +344,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
m->lock();
|
||||
is_locked=true;
|
||||
@@ -353,7 +353,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
is_locked=m->try_lock();
|
||||
return is_locked;
|
||||
@@ -379,7 +379,7 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
m->unlock();
|
||||
is_locked=false;
|
||||
@@ -416,25 +416,36 @@ namespace boost
|
||||
friend class upgrade_lock<Mutex>;
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename Mutex>
|
||||
void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
#else
|
||||
|
||||
template<typename Mutex>
|
||||
inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>&& ul)
|
||||
{
|
||||
return ul;
|
||||
}
|
||||
#endif
|
||||
template<typename Mutex>
|
||||
void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename Mutex>
|
||||
inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul)
|
||||
{
|
||||
return ul;
|
||||
return static_cast<unique_lock<Mutex>&&>(ul);
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
inline unique_lock<Mutex>&& move(unique_lock<Mutex>& ul)
|
||||
{
|
||||
return static_cast<unique_lock<Mutex>&&>(ul);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -535,24 +546,24 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
void swap(shared_lock&& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
#else
|
||||
void swap(shared_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other)
|
||||
{
|
||||
std::swap(m,other->m);
|
||||
std::swap(is_locked,other->is_locked);
|
||||
}
|
||||
#endif
|
||||
void swap(shared_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
|
||||
Mutex* mutex() const
|
||||
{
|
||||
@@ -570,7 +581,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
m->lock_shared();
|
||||
is_locked=true;
|
||||
@@ -579,7 +590,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
is_locked=m->try_lock_shared();
|
||||
return is_locked;
|
||||
@@ -588,7 +599,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -598,7 +609,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -607,7 +618,7 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
m->unlock_shared();
|
||||
is_locked=false;
|
||||
@@ -629,7 +640,7 @@ namespace boost
|
||||
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename Mutex>
|
||||
void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs)
|
||||
{
|
||||
@@ -673,6 +684,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(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
upgrade_lock& operator=(unique_lock<Mutex>&& other)
|
||||
{
|
||||
upgrade_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
@@ -715,6 +759,7 @@ namespace boost
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void swap(upgrade_lock& other)
|
||||
{
|
||||
@@ -733,7 +778,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
m->lock_upgrade();
|
||||
is_locked=true;
|
||||
@@ -742,7 +787,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
is_locked=m->try_lock_upgrade();
|
||||
return is_locked;
|
||||
@@ -751,7 +796,7 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
m->unlock_upgrade();
|
||||
is_locked=false;
|
||||
@@ -775,7 +820,7 @@ namespace boost
|
||||
};
|
||||
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename Mutex>
|
||||
unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other):
|
||||
m(other.m),is_locked(other.is_locked)
|
||||
@@ -819,6 +864,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))
|
||||
{
|
||||
@@ -831,6 +890,7 @@ namespace boost
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
void swap(upgrade_to_unique_lock& other)
|
||||
{
|
||||
std::swap(source,other.source);
|
||||
@@ -875,7 +935,7 @@ namespace boost
|
||||
try_lock_wrapper(Mutex& m_,try_to_lock_t):
|
||||
base(m_,try_to_lock)
|
||||
{}
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
try_lock_wrapper(try_lock_wrapper&& other):
|
||||
base(other.move())
|
||||
{}
|
||||
@@ -963,7 +1023,7 @@ namespace boost
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename Mutex>
|
||||
void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs)
|
||||
{
|
||||
|
||||
@@ -57,13 +57,13 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
}
|
||||
~condition_variable_any()
|
||||
@@ -87,7 +87,7 @@ namespace boost
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
throw condition_error();
|
||||
boost::throw_exception(condition_error());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace boost
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
throw condition_error();
|
||||
boost::throw_exception(condition_error());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// (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>
|
||||
@@ -30,7 +31,7 @@ namespace boost
|
||||
int const res=pthread_cond_init(&cond,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
}
|
||||
~condition_variable()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#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>
|
||||
@@ -37,7 +38,7 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
}
|
||||
~mutex()
|
||||
@@ -89,14 +90,14 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
is_locked=false;
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// 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>
|
||||
@@ -58,10 +59,13 @@ 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(...)
|
||||
{
|
||||
@@ -69,6 +73,7 @@ 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,6 +7,7 @@
|
||||
|
||||
#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>
|
||||
@@ -42,18 +43,18 @@ namespace boost
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
if(init_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
}
|
||||
@@ -111,32 +112,32 @@ namespace boost
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
if(init_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
#else
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
is_locked=false;
|
||||
count=0;
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace boost
|
||||
return new T();
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename T,typename A1>
|
||||
inline T* heap_new(A1&& a1)
|
||||
{
|
||||
|
||||
@@ -61,15 +61,30 @@ namespace boost
|
||||
|
||||
void 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))
|
||||
if(try_lock())
|
||||
{
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
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);
|
||||
@@ -80,6 +95,33 @@ 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)
|
||||
{
|
||||
@@ -93,18 +135,7 @@ namespace boost
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
}
|
||||
while(!lock_acquired);
|
||||
|
||||
@@ -30,81 +30,47 @@ namespace std
|
||||
|
||||
namespace boost
|
||||
{
|
||||
typedef long once_flag;
|
||||
struct once_flag
|
||||
{
|
||||
long status;
|
||||
long count;
|
||||
long throw_count;
|
||||
void* event_handle;
|
||||
|
||||
#define BOOST_ONCE_INIT 0
|
||||
~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}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct win32_mutex_scoped_lock
|
||||
inline void* allocate_event_handle(void*& handle)
|
||||
{
|
||||
void* const mutex_handle;
|
||||
explicit win32_mutex_scoped_lock(void* mutex_handle_):
|
||||
mutex_handle(mutex_handle_)
|
||||
{
|
||||
BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
|
||||
}
|
||||
~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];
|
||||
void* const new_handle=::boost::detail::win32::create_anonymous_event(
|
||||
::boost::detail::win32::manual_reset_event,
|
||||
::boost::detail::win32::event_initially_reset);
|
||||
|
||||
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
|
||||
void* event_handle=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&handle,
|
||||
new_handle,0);
|
||||
if(event_handle)
|
||||
{
|
||||
::boost::detail::win32::CloseHandle(new_handle);
|
||||
return event_handle;
|
||||
}
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -114,18 +80,98 @@ 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;
|
||||
|
||||
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
|
||||
while((status=::boost::detail::interlocked_read_acquire(&flag.status))
|
||||
!=function_complete_flag_value)
|
||||
{
|
||||
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)
|
||||
status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
|
||||
if(!status)
|
||||
{
|
||||
f();
|
||||
BOOST_INTERLOCKED_EXCHANGE(&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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "thread_primitives.hpp"
|
||||
#include <stdexcept>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
@@ -60,7 +61,7 @@ namespace boost
|
||||
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
|
||||
if(!heap_memory)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
}
|
||||
return heap_memory;
|
||||
}
|
||||
@@ -86,7 +87,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename T,typename A1>
|
||||
inline T* heap_new(A1&& a1)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
// 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>
|
||||
@@ -177,7 +178,7 @@ namespace boost
|
||||
#endif
|
||||
if(!res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -191,7 +192,7 @@ namespace boost
|
||||
#endif
|
||||
if(!res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -204,7 +205,7 @@ namespace boost
|
||||
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
if(!success)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#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__)
|
||||
@@ -186,7 +187,7 @@ namespace boost
|
||||
if (res != 0)
|
||||
{
|
||||
thread_info->self.reset();
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
// 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;
|
||||
@@ -18,7 +21,7 @@ inline void to_time(int milliseconds, boost::xtime& xt)
|
||||
{
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
|
||||
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
|
||||
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
|
||||
@@ -55,7 +58,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);
|
||||
assert(res == boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
{
|
||||
@@ -86,7 +89,7 @@ inline void to_duration(boost::xtime xt, int& milliseconds)
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
milliseconds = 0;
|
||||
@@ -108,7 +111,7 @@ inline void to_microduration(boost::xtime xt, int& microseconds)
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
microseconds = 0;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#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>
|
||||
|
||||
@@ -188,7 +189,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)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
intrusive_ptr_add_ref(thread_info.get());
|
||||
thread_info->thread_handle=(detail::win32::handle)(new_thread);
|
||||
|
||||
@@ -42,6 +42,7 @@ 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,4 +1,4 @@
|
||||
// (C) Copyright 2008-9 Anthony Williams
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
template<typename T>
|
||||
typename boost::remove_reference<T>::type&& cast_to_rval(T&& t)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
X():
|
||||
i(42)
|
||||
{}
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
X(X&& other):
|
||||
i(other.i)
|
||||
{
|
||||
@@ -89,7 +89,7 @@ void set_promise_exception_thread(boost::promise<int>* p)
|
||||
void test_store_value_from_thread()
|
||||
{
|
||||
boost::promise<int> pi2;
|
||||
boost::unique_future<int> fi2=pi2.get_future();
|
||||
boost::unique_future<int> fi2(pi2.get_future());
|
||||
boost::thread(set_promise_thread,&pi2);
|
||||
int j=fi2.get();
|
||||
BOOST_CHECK(j==42);
|
||||
|
||||
73
test/test_thread_exit.cpp
Normal file
73
test/test_thread_exit.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// (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