mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
3 Commits
svn-branch
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c09b4110d7 | ||
|
|
b75a32b913 | ||
|
|
c6b8f21bde |
@@ -62,9 +62,9 @@ lib boost_thread
|
||||
#######################
|
||||
# Stage the generated targets.
|
||||
|
||||
stage bin-stage
|
||||
: <lib>boost_thread $(threadmon)
|
||||
: <tag><runtime-link-static>"s"
|
||||
<tag><debug>"d"
|
||||
: debug release <runtime-link>static/dynamic
|
||||
;
|
||||
#stage bin-stage
|
||||
# : <lib>boost_thread $(threadmon)
|
||||
# : <tag><runtime-link-static>"s"
|
||||
# <tag><debug>"d"
|
||||
# : debug release <runtime-link>static/dynamic
|
||||
#;
|
||||
|
||||
@@ -39,7 +39,13 @@ struct xtime
|
||||
int_fast32_t nsec;
|
||||
};
|
||||
|
||||
int xtime_get(struct xtime* xtp, int clock_type);
|
||||
int xtime_get(xtime* xtp, int clock_type);
|
||||
inline int xtime_cmp(const xtime& xtp1, const xtime& xtp2)
|
||||
{
|
||||
int res = xtp1.sec - xtp2.sec;
|
||||
if (res == 0) res = xtp1.nsec - xtp2.nsec;
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <cassert>
|
||||
#include "timeconv.inl"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
@@ -242,71 +244,103 @@ void condition::do_wait()
|
||||
}
|
||||
}
|
||||
|
||||
//#define DOFIX
|
||||
|
||||
bool condition::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
bool ret = false;
|
||||
unsigned int res = 0;
|
||||
|
||||
unsigned int res = 0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
#if defined(DOFIX)
|
||||
for (;;)
|
||||
{
|
||||
#endif
|
||||
int milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
if (milliseconds < 0)
|
||||
std::cout << "milliseconds < 0" << std::endl;
|
||||
if (milliseconds > 10000)
|
||||
std::cout << "milliseconds > 10000" << std::endl;
|
||||
// assert(milliseconds > 0);
|
||||
|
||||
bool ret = (res == WAIT_OBJECT_0);
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
ret = (res == WAIT_OBJECT_0);
|
||||
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
was_waiting = m_waiting;
|
||||
was_gone = m_gone;
|
||||
if (was_waiting != 0)
|
||||
{
|
||||
if (!ret) // timeout
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
--m_blocked;
|
||||
else
|
||||
++m_gone; // count spurious wakeups
|
||||
}
|
||||
if (--m_waiting == 0)
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
|
||||
assert(res);
|
||||
was_waiting = 0;
|
||||
}
|
||||
else if (m_gone != 0)
|
||||
m_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
|
||||
{
|
||||
// timeout occured, normalize the m_gone count
|
||||
// this may occur if many calls to wait with a timeout are made and
|
||||
// no call to notify_* is made
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
m_blocked -= m_gone;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
m_gone = 0;
|
||||
}
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
#if defined(DOFIX)
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
xtime now;
|
||||
xtime_get(&now, TIME_UTC);
|
||||
if (xtime_cmp(xt, now) >= 0)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
was_waiting = m_waiting;
|
||||
was_gone = m_gone;
|
||||
if (was_waiting != 0)
|
||||
{
|
||||
if (!ret) // timeout?
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
--m_blocked;
|
||||
else
|
||||
++m_gone; // count spurious wakeups
|
||||
}
|
||||
if (--m_waiting == 0)
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
|
||||
assert(res);
|
||||
was_waiting = 0;
|
||||
}
|
||||
else if (m_gone != 0)
|
||||
m_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
|
||||
{
|
||||
// timeout occured, normalize the m_gone count
|
||||
// this may occur if many calls to wait with a timeout are made and
|
||||
// no call to notify_* is made
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
m_blocked -= m_gone;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
m_gone = 0;
|
||||
}
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
// if (!ret)
|
||||
// {
|
||||
// xtime now;
|
||||
// xtime_get(&now, TIME_UTC);
|
||||
// if (xtime_cmp(xt, now) >= 0)
|
||||
// break;
|
||||
// }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -571,7 +605,7 @@ void condition::do_wait()
|
||||
|
||||
bool condition::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
int milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
OSStatus lStatus = noErr;
|
||||
|
||||
@@ -145,7 +145,7 @@ bool timed_mutex::do_trylock()
|
||||
|
||||
bool timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
int milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
unsigned int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds);
|
||||
@@ -500,7 +500,7 @@ bool timed_mutex::do_trylock()
|
||||
|
||||
bool timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
unsigned microseconds;
|
||||
int microseconds;
|
||||
to_microduration(xt, microseconds);
|
||||
Duration lDuration = kDurationMicrosecond * microseconds;
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ bool recursive_timed_mutex::do_trylock()
|
||||
|
||||
bool recursive_timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
int milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
unsigned int res = 0;
|
||||
@@ -936,7 +936,7 @@ bool recursive_timed_mutex::do_trylock()
|
||||
|
||||
bool recursive_timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
unsigned microseconds;
|
||||
int microseconds;
|
||||
to_microduration(xt, microseconds);
|
||||
Duration lDuration = kDurationMicrosecond * microseconds;
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
@@ -72,6 +74,8 @@ static OSStatus thread_proxy(void* param)
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
using namespace std;
|
||||
terminate();
|
||||
}
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
::boost::detail::thread_cleanup();
|
||||
@@ -192,13 +196,13 @@ void thread::join()
|
||||
void thread::sleep(const xtime& xt)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned milliseconds;
|
||||
int milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
Sleep(milliseconds);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
to_timespec_duration(xt, ts);
|
||||
int res = 0;
|
||||
res = pthread_delay_np(&ts);
|
||||
assert(res == 0);
|
||||
@@ -216,7 +220,7 @@ void thread::sleep(const xtime& xt)
|
||||
cond.timed_wait(lock, xt);
|
||||
# endif
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
unsigned microseconds;
|
||||
int microseconds;
|
||||
to_microduration(xt, microseconds);
|
||||
Duration lMicroseconds(kDurationMicrosecond * microseconds);
|
||||
AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds));
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
namespace {
|
||||
const unsigned MILLISECONDS_PER_SECOND = 1000;
|
||||
const unsigned NANOSECONDS_PER_SECOND = 1000000000;
|
||||
const unsigned NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
|
||||
const unsigned MICROSECONDS_PER_SECOND = 1000000;
|
||||
const unsigned NANOSECONDS_PER_MICROSECOND = 1000;
|
||||
const int MICROSECONDS_PER_SECOND = 1000000;
|
||||
const int NANOSECONDS_PER_MICROSECOND = 1000;
|
||||
|
||||
inline void to_time(unsigned milliseconds, boost::xtime& xt)
|
||||
inline void to_time(int milliseconds, boost::xtime& xt)
|
||||
{
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
@@ -45,7 +45,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_time(unsigned milliseconds, timespec& ts)
|
||||
inline void to_time(int milliseconds, timespec& ts)
|
||||
{
|
||||
boost::xtime xt;
|
||||
to_time(milliseconds, xt);
|
||||
@@ -59,7 +59,7 @@ namespace {
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (xt.sec < cur.sec || (xt.sec == cur.sec && xt.nsec < cur.nsec))
|
||||
if (boost::xtime_cmp(xt, cur) < 0)
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
@@ -83,37 +83,37 @@ namespace {
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void to_duration(const boost::xtime& xt, unsigned& milliseconds)
|
||||
inline void to_duration(const boost::xtime& xt, int& milliseconds)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (xt.sec < cur.sec || (xt.sec == cur.sec && xt.nsec < cur.nsec))
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
milliseconds = 0;
|
||||
else
|
||||
{
|
||||
milliseconds = static_cast<unsigned>(((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
|
||||
milliseconds = ((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
|
||||
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
|
||||
NANOSECONDS_PER_MILLISECOND));
|
||||
NANOSECONDS_PER_MILLISECOND);
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_microduration(const boost::xtime& xt, unsigned& microseconds)
|
||||
inline void to_microduration(const boost::xtime& xt, int& microseconds)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (xt.sec < cur.sec || (xt.sec == cur.sec && xt.nsec < cur.nsec))
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
microseconds = 0;
|
||||
else
|
||||
{
|
||||
microseconds = static_cast<unsigned long>(((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
|
||||
microseconds = ((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
|
||||
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
|
||||
NANOSECONDS_PER_MICROSECOND));
|
||||
NANOSECONDS_PER_MICROSECOND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ void test_lock(M* dummy=0)
|
||||
BOOST_TEST(condition.timed_wait(lock, xt) == false);
|
||||
BOOST_TEST(lock);
|
||||
|
||||
// boost::xtime now;
|
||||
// BOOST_TEST(boost::xtime_get(&now, boost::TIME_UTC) == boost::TIME_UTC);
|
||||
// BOOST_TEST(boost::xtime_cmp(xt, now) >= 0);
|
||||
|
||||
// Test the lock and unlock methods.
|
||||
lock.unlock();
|
||||
BOOST_TEST(!lock);
|
||||
@@ -438,14 +442,23 @@ void test_once()
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
boost::xtime xt1, xt2;
|
||||
BOOST_TEST(boost::xtime_get(&xt1, boost::TIME_UTC) == boost::TIME_UTC);
|
||||
// for (int j = 0; j < 1000000000; ++j) ;
|
||||
BOOST_TEST(boost::xtime_get(&xt2, boost::TIME_UTC) == boost::TIME_UTC);
|
||||
BOOST_TEST(boost::xtime_cmp(xt1, xt2) <= 0);
|
||||
}
|
||||
|
||||
test_mutex();
|
||||
test_try_mutex();
|
||||
test_timed_mutex();
|
||||
test_recursive_mutex();
|
||||
test_recursive_try_mutex();
|
||||
test_recursive_timed_mutex();
|
||||
test_condition();
|
||||
test_tss();
|
||||
test_once();
|
||||
// test_try_mutex();
|
||||
// test_timed_mutex();
|
||||
// test_recursive_mutex();
|
||||
// test_recursive_try_mutex();
|
||||
// test_recursive_timed_mutex();
|
||||
// test_condition();
|
||||
// test_tss();
|
||||
// test_once();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user