mirror of
https://github.com/boostorg/thread.git
synced 2026-01-24 06:22:12 +00:00
Merged revisions 41399-41442 via svnmerge from
https://svn.boost.org/svn/boost/trunk ........ r41400 | igaztanaga | 2007-11-26 08:34:13 -0800 (Mon, 26 Nov 2007) | 1 line Added missing #include <typeinfo> ........ r41401 | anthonyw | 2007-11-26 09:01:08 -0800 (Mon, 26 Nov 2007) | 1 line once_flag uses zero-initialization on POSIX as well as windows ........ r41402 | niels_dekker | 2007-11-26 09:36:52 -0800 (Mon, 26 Nov 2007) | 1 line Marked value_init_test failures on Borland C++ as "expected failures", as discussed with Fernando Cacciola. ........ r41404 | rwgk | 2007-11-26 12:46:28 -0800 (Mon, 26 Nov 2007) | 1 line g++ 4.3.0 compatibility (4.3.0 20071125 (experimental)) ........ r41405 | anthonyw | 2007-11-26 13:15:04 -0800 (Mon, 26 Nov 2007) | 1 line reverted accidental checkin of new timed_wait functions on condition_variable ........ r41406 | nasonov | 2007-11-26 13:29:04 -0800 (Mon, 26 Nov 2007) | 3 lines Remove redundant BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION. ........ r41407 | chris_kohlhoff | 2007-11-26 13:29:38 -0800 (Mon, 26 Nov 2007) | 3 lines WinCE doesn't work with all multicast addresses, and even though it doesn't support the multicast::enable_loopback option you can still get the value. ........ r41408 | dave | 2007-11-26 14:01:50 -0800 (Mon, 26 Nov 2007) | 2 lines Try to extend the workaround to SunPro 5.9, since we're marked as not working on 5.8 ........ r41409 | dave | 2007-11-26 17:40:01 -0800 (Mon, 26 Nov 2007) | 3 lines Allow Sun-5.7 and Sun-5.8 to fail loudly for Boost.Python so I can see what's really wrong. ........ r41413 | anthonyw | 2007-11-27 06:24:29 -0800 (Tue, 27 Nov 2007) | 1 line add support for relative timeouts to condition timed_wait ........ r41414 | grafik | 2007-11-27 09:53:56 -0800 (Tue, 27 Nov 2007) | 1 line Remove non-existent option info. ........ r41415 | grafik | 2007-11-27 09:55:13 -0800 (Tue, 27 Nov 2007) | 1 line Add some utility output formatting functions. ........ r41416 | grafik | 2007-11-27 09:57:15 -0800 (Tue, 27 Nov 2007) | 1 line Check empty string invariants, instead of assuming all strings are allocated. And reset strings when they are freed. ........ r41417 | grafik | 2007-11-27 09:58:50 -0800 (Tue, 27 Nov 2007) | 1 line Fix buffer overrun bug in expanding @() subexpressions. ........ r41418 | hkaiser | 2007-11-27 10:18:10 -0800 (Tue, 27 Nov 2007) | 1 line Wave: Fixed gcc warning, bumped version number. ........ r41419 | djenkins | 2007-11-27 10:57:48 -0800 (Tue, 27 Nov 2007) | 1 line Changes for msvc-9.0 /clr flag ........ r41420 | djenkins | 2007-11-27 10:59:06 -0800 (Tue, 27 Nov 2007) | 1 line Changes for msvc-9.0 /clr flag ........ r41423 | niels_dekker | 2007-11-27 13:34:08 -0800 (Tue, 27 Nov 2007) | 1 line Added value_init test for struct as used in MSVC bug report regarding value-initialization. ........ r41429 | noel_belcourt | 2007-11-27 18:27:13 -0800 (Tue, 27 Nov 2007) | 3 lines Fix pathscale rpath issue per Alain Minussi's suggestion. ........ r41430 | grafik | 2007-11-27 23:08:13 -0800 (Tue, 27 Nov 2007) | 1 line Add test for result status values of simple actions, i.e. empty actions. ........ r41431 | grafik | 2007-11-27 23:21:49 -0800 (Tue, 27 Nov 2007) | 19 lines build-system.jam * Reflect added start/end timestamps for actions in xml output. And update action rules for new args. execcmd.h * Add start/end timestamps to action timing info. execnt.c * Fix filetime_seconds calculation when time is larger than low 32 bit value. * Add calc of C time_t from Windows FILETIME. * Add start/end timestamps recording to action timing info. execunix.c * Add start/end timestamps recording to action timing info. jam.c * Change JAMDATE to use common ISO date format. make1.c * Redo __TIMING_RULE__ and __ACTION__RULE__ invocations to new argument ordering and added end/result timestamp values. ........ r41432 | chris_kohlhoff | 2007-11-28 05:26:33 -0800 (Wed, 28 Nov 2007) | 3 lines Make async operations fail with an error if the socket descriptor doesn't fit into the select call's fd_set. ........ r41433 | bgubenko | 2007-11-28 07:33:16 -0800 (Wed, 28 Nov 2007) | 1 line add "gcc*hpux*" toolset for serialization library bug on big endian platforms ........ r41436 | niels_dekker | 2007-11-28 09:19:37 -0800 (Wed, 28 Nov 2007) | 1 line Added tests for two more struct types to value_init_test -- discussed with Fernando Cacciola ........ r41439 | bgubenko | 2007-11-28 11:04:53 -0800 (Wed, 28 Nov 2007) | 1 line add "<linkflags>-lrt" for acc* toolsets ........ r41440 | grafik | 2007-11-28 12:24:17 -0800 (Wed, 28 Nov 2007) | 1 line Fix for latest Doxygen namespace file names. And support for method groups. From Samuel Debionne. ........ [SVN r41444]
This commit is contained in:
@@ -5,11 +5,9 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <limits.h>
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <pthread.h>
|
||||
#include "timespec.hpp"
|
||||
#include "pthread_mutex_scoped_lock.hpp"
|
||||
@@ -150,6 +148,12 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -44,6 +46,12 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename duration_type,typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
#include "pthread_mutex_scoped_lock.hpp"
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace boost {
|
||||
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
|
||||
}
|
||||
|
||||
#define BOOST_ONCE_INITIAL_FLAG_VALUE -1
|
||||
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
|
||||
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@ namespace boost {
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
|
||||
static boost::uintmax_t const being_initialized=uninitialized_flag-1;
|
||||
static boost::uintmax_t const being_initialized=uninitialized_flag+1;
|
||||
boost::uintmax_t const epoch=flag.epoch;
|
||||
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
|
||||
|
||||
if(epoch>this_thread_epoch)
|
||||
if(epoch<this_thread_epoch)
|
||||
{
|
||||
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
|
||||
|
||||
while(flag.epoch>=being_initialized)
|
||||
while(flag.epoch<=being_initialized)
|
||||
{
|
||||
if(flag.epoch==uninitialized_flag)
|
||||
{
|
||||
@@ -66,7 +66,7 @@ namespace boost {
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
throw;
|
||||
}
|
||||
flag.epoch=++detail::once_global_epoch;
|
||||
flag.epoch=--detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include "interlocked_read.hpp"
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -111,8 +113,78 @@ namespace boost
|
||||
|
||||
|
||||
protected:
|
||||
struct timeout
|
||||
{
|
||||
unsigned long start;
|
||||
uintmax_t milliseconds;
|
||||
bool relative;
|
||||
boost::system_time abs_time;
|
||||
|
||||
static unsigned long const max_non_infinite_wait=0xfffffffe;
|
||||
|
||||
timeout(uintmax_t milliseconds_):
|
||||
start(win32::GetTickCount()),
|
||||
milliseconds(milliseconds_),
|
||||
relative(true),
|
||||
abs_time(boost::get_system_time())
|
||||
{}
|
||||
|
||||
timeout(boost::system_time const& abs_time_):
|
||||
start(win32::GetTickCount()),
|
||||
milliseconds(0),
|
||||
relative(false),
|
||||
abs_time(abs_time_)
|
||||
{}
|
||||
|
||||
struct remaining_time
|
||||
{
|
||||
bool more;
|
||||
unsigned long milliseconds;
|
||||
|
||||
remaining_time(uintmax_t remaining):
|
||||
more(remaining>max_non_infinite_wait),
|
||||
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
|
||||
{}
|
||||
};
|
||||
|
||||
remaining_time remaining_milliseconds() const
|
||||
{
|
||||
if(milliseconds==~uintmax_t(0))
|
||||
{
|
||||
return remaining_time(win32::infinite);
|
||||
}
|
||||
else if(relative)
|
||||
{
|
||||
unsigned long const now=win32::GetTickCount();
|
||||
unsigned long const elapsed=now-start;
|
||||
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
|
||||
}
|
||||
else
|
||||
{
|
||||
system_time const now=get_system_time();
|
||||
if(abs_time<now)
|
||||
{
|
||||
return remaining_time(0);
|
||||
}
|
||||
return remaining_time((abs_time-get_system_time()).total_milliseconds()+1);
|
||||
}
|
||||
}
|
||||
|
||||
static timeout sentinel()
|
||||
{
|
||||
return timeout(sentinel_type());
|
||||
}
|
||||
private:
|
||||
struct sentinel_type
|
||||
{};
|
||||
|
||||
explicit timeout(sentinel_type):
|
||||
start(0),milliseconds(~uintmax_t(0)),relative(true)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename lock_type>
|
||||
bool do_wait(lock_type& lock,::boost::system_time const& wait_until)
|
||||
bool do_wait(lock_type& lock,timeout wait_until)
|
||||
{
|
||||
detail::win32::handle_manager local_wake_sem;
|
||||
detail::win32::handle_manager sem;
|
||||
@@ -155,9 +227,21 @@ namespace boost
|
||||
++generations[0].count;
|
||||
sem=detail::win32::duplicate_handle(generations[0].semaphore);
|
||||
}
|
||||
if(!this_thread::interruptible_wait(sem,::boost::detail::get_milliseconds_until(wait_until)))
|
||||
while(true)
|
||||
{
|
||||
break;
|
||||
timeout::remaining_time const remaining=wait_until.remaining_milliseconds();
|
||||
if(this_thread::interruptible_wait(sem,remaining.milliseconds))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if(!remaining.more)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(wait_until.relative)
|
||||
{
|
||||
wait_until.milliseconds-=timeout::max_non_infinite_wait;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
|
||||
@@ -167,6 +251,17 @@ namespace boost
|
||||
}
|
||||
return woken;
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool do_wait(lock_type& m,timeout const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!do_wait(m, wait_until))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
basic_condition_variable(const basic_condition_variable& other);
|
||||
basic_condition_variable& operator=(const basic_condition_variable& other);
|
||||
@@ -238,7 +333,7 @@ namespace boost
|
||||
public:
|
||||
void wait(unique_lock<mutex>& m)
|
||||
{
|
||||
do_wait(m,::boost::detail::get_system_time_sentinel());
|
||||
do_wait(m,timeout::sentinel());
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
@@ -256,17 +351,17 @@ namespace boost
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, wait_until))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return do_wait(m,wait_until,pred);
|
||||
}
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
template<typename duration_type,typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||
return do_wait(m,wait_duration.total_milliseconds(),pred);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -277,7 +372,7 @@ namespace boost
|
||||
template<typename lock_type>
|
||||
void wait(lock_type& m)
|
||||
{
|
||||
do_wait(m,::boost::detail::get_system_time_sentinel());
|
||||
do_wait(m,timeout::sentinel());
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
@@ -295,18 +390,19 @@ namespace boost
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, wait_until))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return do_wait(m,wait_until,pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||
return timed_wait(m,wait_duration.total_milliseconds(),pred);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace boost
|
||||
using ::SleepEx;
|
||||
using ::Sleep;
|
||||
using ::QueueUserAPC;
|
||||
using ::GetTickCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,6 +121,8 @@ namespace boost
|
||||
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
|
||||
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
|
||||
|
||||
__declspec(dllimport) unsigned long __stdcall GetTickCount();
|
||||
|
||||
# ifndef UNDER_CE
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <pthread.h>
|
||||
@@ -12,7 +13,7 @@ namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=0;
|
||||
BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=UINTMAX_C(~0);
|
||||
BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
@@ -41,7 +42,7 @@ namespace boost
|
||||
{
|
||||
data=malloc(sizeof(boost::uintmax_t));
|
||||
BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data));
|
||||
*static_cast<boost::uintmax_t*>(data)=0;
|
||||
*static_cast<boost::uintmax_t*>(data)=UINTMAX_C(~0);
|
||||
}
|
||||
return *static_cast<boost::uintmax_t*>(data);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 2007 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)
|
||||
@@ -19,7 +20,7 @@ struct condition_test_data
|
||||
condition_test_data() : notified(0), awoken(0) { }
|
||||
|
||||
boost::mutex mutex;
|
||||
boost::condition condition;
|
||||
boost::condition_variable condition;
|
||||
int notified;
|
||||
int awoken;
|
||||
};
|
||||
@@ -82,6 +83,15 @@ void condition_test_waits(condition_test_data* data)
|
||||
BOOST_CHECK_EQUAL(data->notified, 4);
|
||||
data->awoken++;
|
||||
data->condition.notify_one();
|
||||
|
||||
// Test predicate timed_wait with relative timeout
|
||||
cond_predicate pred_rel(data->notified, 5);
|
||||
BOOST_CHECK(data->condition.timed_wait(lock, boost::posix_time::seconds(10), pred_rel));
|
||||
BOOST_CHECK(lock ? true : false);
|
||||
BOOST_CHECK(pred_rel());
|
||||
BOOST_CHECK_EQUAL(data->notified, 5);
|
||||
data->awoken++;
|
||||
data->condition.notify_one();
|
||||
}
|
||||
|
||||
void do_test_condition_notify_one()
|
||||
@@ -185,10 +195,19 @@ void do_test_condition_waits()
|
||||
data.condition.wait(lock);
|
||||
BOOST_CHECK(lock ? true : false);
|
||||
BOOST_CHECK_EQUAL(data.awoken, 4);
|
||||
|
||||
|
||||
boost::thread::sleep(delay(1));
|
||||
data.notified++;
|
||||
data.condition.notify_one();
|
||||
while (data.awoken != 5)
|
||||
data.condition.wait(lock);
|
||||
BOOST_CHECK(lock ? true : false);
|
||||
BOOST_CHECK_EQUAL(data.awoken, 5);
|
||||
}
|
||||
|
||||
thread.join();
|
||||
BOOST_CHECK_EQUAL(data.awoken, 4);
|
||||
BOOST_CHECK_EQUAL(data.awoken, 5);
|
||||
}
|
||||
|
||||
void test_condition_waits()
|
||||
@@ -216,6 +235,32 @@ void test_condition_wait_is_a_interruption_point()
|
||||
timed_test(&do_test_condition_wait_is_a_interruption_point, 1);
|
||||
}
|
||||
|
||||
bool fake_predicate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void do_test_timed_wait_times_out()
|
||||
{
|
||||
boost::condition_variable cond;
|
||||
boost::mutex m;
|
||||
|
||||
boost::posix_time::seconds const delay(5);
|
||||
boost::mutex::scoped_lock lock(m);
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
bool const res=cond.timed_wait(lock,delay,fake_predicate);
|
||||
boost::system_time const end=boost::get_system_time();
|
||||
BOOST_CHECK(!res);
|
||||
BOOST_CHECK((delay-boost::posix_time::milliseconds(10))<=(end-start));
|
||||
}
|
||||
|
||||
|
||||
void test_timed_wait_times_out()
|
||||
{
|
||||
timed_test(&do_test_timed_wait_times_out, 15);
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
@@ -226,6 +271,7 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
test->add(BOOST_TEST_CASE(&test_condition_notify_all));
|
||||
test->add(BOOST_TEST_CASE(&test_condition_waits));
|
||||
test->add(BOOST_TEST_CASE(&test_condition_wait_is_a_interruption_point));
|
||||
test->add(BOOST_TEST_CASE(&test_timed_wait_times_out));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user