2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 09:42:16 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Beman Dawes
120ccc87dd Release 1.41.0 Beta 1
[SVN r57353]
2009-11-04 12:14:07 +00:00
22 changed files with 196 additions and 402 deletions

View File

@@ -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);

View File

@@ -916,13 +916,6 @@ 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]

View File

@@ -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()

View File

@@ -39,13 +39,10 @@ namespace boost
public detail::thread_data_base
{
public:
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
thread_data(F&& f_):
f(static_cast<F&&>(f_))
{}
thread_data(F& f_):
f(f_)
{}
#else
thread_data(F f_):
f(f_)
@@ -122,7 +119,7 @@ namespace boost
detail::thread_data_ptr get_thread_info() const;
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename F>
static inline detail::thread_data_ptr make_thread_info(F&& f)
{
@@ -130,7 +127,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(*)()> >(static_cast<void(*&&)()>(f)));
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
}
#else
template<typename F>
@@ -144,8 +141,8 @@ namespace boost
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
#endif
struct dummy;
#endif
public:
#ifdef __SUNPRO_CC
thread(const volatile thread&);
@@ -153,22 +150,13 @@ namespace boost
thread();
~thread();
#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
#ifdef BOOST_HAS_RVALUE_REFS
template <class F>
thread(F&& f):
thread_info(make_thread_info(static_cast<F&&>(f)))
{
start_thread();
}
#endif
thread(thread&& other)
{
@@ -355,14 +343,10 @@ namespace boost
return lhs.swap(rhs);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
inline thread&& move(thread& t)
{
return static_cast<thread&&>(t);
}
#ifdef BOOST_HAS_RVALUE_REFS
inline thread&& move(thread&& t)
{
return static_cast<thread&&>(t);
return t;
}
#else
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
@@ -461,7 +445,7 @@ namespace boost
{
virtual ~thread_exit_function_base()
{}
virtual void operator()()=0;
virtual void operator()() const=0;
};
template<typename F>
@@ -474,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

View File

@@ -1,4 +1,4 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2008-9 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -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>
@@ -219,7 +218,7 @@ namespace boost
struct future_traits
{
typedef boost::scoped_ptr<T> storage_type;
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
typedef T const& source_reference_type;
struct dummy;
typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
@@ -324,7 +323,7 @@ namespace boost
move_dest_type get()
{
wait();
return static_cast<move_dest_type>(*result);
return *result;
}
future_state::state get_state()
@@ -404,14 +403,13 @@ namespace boost
struct all_futures_lock
{
typedef std::vector<registered_waiter>::size_type count_type;
count_type count;
unsigned 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(count_type i=0;i<count;++i)
for(unsigned i=0;i<count;++i)
{
locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
}
@@ -634,7 +632,7 @@ namespace boost
~unique_future()
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
unique_future(unique_future && other)
{
future.swap(other.future);
@@ -675,7 +673,7 @@ namespace boost
{
if(!future)
{
boost::throw_exception(future_uninitialized());
throw future_uninitialized();
}
return future->get();
@@ -711,7 +709,7 @@ namespace boost
{
if(!future)
{
boost::throw_exception(future_uninitialized());
throw future_uninitialized();
}
future->wait(false);
}
@@ -726,7 +724,7 @@ namespace boost
{
if(!future)
{
boost::throw_exception(future_uninitialized());
throw future_uninitialized();
}
return future->timed_wait_until(abs_time);
}
@@ -769,7 +767,7 @@ namespace boost
future=other.future;
return *this;
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
shared_future(shared_future && other)
{
future.swap(other.future);
@@ -832,7 +830,7 @@ namespace boost
{
if(!future)
{
boost::throw_exception(future_uninitialized());
throw future_uninitialized();
}
return future->get();
@@ -868,7 +866,7 @@ namespace boost
{
if(!future)
{
boost::throw_exception(future_uninitialized());
throw future_uninitialized();
}
future->wait(false);
}
@@ -883,7 +881,7 @@ namespace boost
{
if(!future)
{
boost::throw_exception(future_uninitialized());
throw future_uninitialized();
}
return future->timed_wait_until(abs_time);
}
@@ -931,7 +929,7 @@ namespace boost
}
// Assignment
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
promise(promise && rhs):
future_obtained(rhs.future_obtained)
{
@@ -976,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);
@@ -988,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);
}
@@ -1000,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));
}
@@ -1011,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);
}
@@ -1065,7 +1063,7 @@ namespace boost
}
// Assignment
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
promise(promise && rhs):
future_obtained(rhs.future_obtained)
{
@@ -1111,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);
@@ -1123,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();
}
@@ -1134,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);
}
@@ -1166,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;
}
@@ -1285,7 +1283,7 @@ namespace boost
}
// assignment
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
packaged_task(packaged_task&& other):
future_obtained(other.future_obtained)
{
@@ -1328,7 +1326,7 @@ namespace boost
{
if(!task)
{
boost::throw_exception(task_moved());
throw task_moved();
}
else if(!future_obtained)
{
@@ -1337,7 +1335,7 @@ namespace boost
}
else
{
boost::throw_exception(future_already_retrieved());
throw future_already_retrieved();
}
}
@@ -1347,7 +1345,7 @@ namespace boost
{
if(!task)
{
boost::throw_exception(task_moved());
throw task_moved();
}
task->run();
}

View File

@@ -248,7 +248,7 @@ namespace boost
{
timed_lock(target_time);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
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())
{
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;
@@ -416,30 +416,25 @@ namespace boost
friend class upgrade_lock<Mutex>;
};
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename Mutex>
void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs)
{
lhs.swap(rhs);
}
#endif
#else
template<typename Mutex>
void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
{
lhs.swap(rhs);
}
#endif
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename Mutex>
inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& 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);
return ul;
}
#endif
@@ -540,24 +535,24 @@ namespace boost
return *this;
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
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
{
@@ -575,7 +570,7 @@ namespace boost
{
if(owns_lock())
{
boost::throw_exception(boost::lock_error());
throw boost::lock_error();
}
m->lock_shared();
is_locked=true;
@@ -584,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;
@@ -593,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;
@@ -603,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;
@@ -612,7 +607,7 @@ namespace boost
{
if(!owns_lock())
{
boost::throw_exception(boost::lock_error());
throw boost::lock_error();
}
m->unlock_shared();
is_locked=false;
@@ -634,7 +629,7 @@ namespace boost
};
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename Mutex>
void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs)
{
@@ -738,7 +733,7 @@ namespace boost
{
if(owns_lock())
{
boost::throw_exception(boost::lock_error());
throw boost::lock_error();
}
m->lock_upgrade();
is_locked=true;
@@ -747,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;
@@ -756,7 +751,7 @@ namespace boost
{
if(!owns_lock())
{
boost::throw_exception(boost::lock_error());
throw boost::lock_error();
}
m->unlock_upgrade();
is_locked=false;
@@ -780,7 +775,7 @@ namespace boost
};
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename Mutex>
unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other):
m(other.m),is_locked(other.is_locked)
@@ -880,7 +875,7 @@ namespace boost
try_lock_wrapper(Mutex& m_,try_to_lock_t):
base(m_,try_to_lock)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
try_lock_wrapper(try_lock_wrapper&& other):
base(other.move())
{}
@@ -968,7 +963,7 @@ namespace boost
}
};
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename Mutex>
void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs)
{

View File

@@ -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;
}

View File

@@ -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()

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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;

View File

@@ -17,7 +17,7 @@ namespace boost
return new T();
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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;
}
@@ -87,7 +86,7 @@ namespace boost
}
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 ]

View File

@@ -1,4 +1,4 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2008-9 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>
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
template<typename T>
typename boost::remove_reference<T>::type&& cast_to_rval(T&& t)
{
@@ -41,7 +41,7 @@ public:
X():
i(42)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_HAS_RVALUE_REFS
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);

View File

@@ -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;
}