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

Fixed thread join bugs. Fixed mutex creation bugs.

[SVN r18176]
This commit is contained in:
William E. Kempf
2003-04-03 22:56:50 +00:00
parent 46b1a4d1e3
commit c1283bb731
5 changed files with 84 additions and 155 deletions

View File

@@ -56,102 +56,16 @@ inline int wait(void* mutex, int time)
{
unsigned int res = 0;
res = WaitForSingleObject(mutex_cast(mutex), time);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
// assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
return res;
}
inline void release(void* mutex)
{
int res = 0;
BOOL res = FALSE;
res = ReleaseMutex(mutex_cast(mutex));
assert(res);
}
class critsect_impl
{
public:
critsect_impl()
{
}
~critsect_impl()
{
DeleteCriticalSection(&m_critsect);
}
void lock()
{
EnterCriticalSection(&m_critsect);
}
void unlock()
{
LeaveCriticalSection(&m_critsect);
}
private:
CRITICAL_SECTION m_critsect;
};
class mutex_impl
{
public:
mutex_impl(const char* name=0)
{
m_mutex = CreateMutexA(0, 0, name);
if (m_mutex == INVALID_HANDLE_VALUE)
throw boost::thread_resource_error();
}
~mutex_impl()
{
int res = 0;
res = CloseHandle(m_mutex);
assert(res);
}
void lock()
{
unsigned int res = 0;
res = WaitForSingleObject(m_mutex, INFINITE);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
}
bool trylock()
{
unsigned int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
return res == WAIT_OBJECT_0;
}
bool timedlock(const boost::xtime& xt)
{
unsigned int res = 0;
for (;;)
{
int milliseconds;
to_duration(xt, milliseconds);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex),
milliseconds);
if (res == WAIT_TIMEOUT)
{
boost::xtime cur;
boost::xtime_get(&cur, boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) > 0)
continue;
}
return res == WAIT_OBJECT_0;
}
}
void unlock()
{
int res = 0;
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
}
private:
HANDLE m_mutex;
};
#endif
} // namesapce
@@ -168,21 +82,16 @@ mutex::mutex(const char* name)
HANDLE mutex = CreateMutex(0, 0, effective_name());
if (mutex == INVALID_HANDLE_VALUE)
throw thread_resource_error();
m_mutex = reinterpret_cast<void*>(mutex);
m_critsect = false;
}
else
{
try
{
LPCRITICAL_SECTION cs = new CRITICAL_SECTION;
InitializeCriticalSection(cs);
m_mutex = reinterpret_cast<void*>(cs);
m_critsect = true;
}
catch (std::bad_alloc&)
{
throw thread_resource_error();
}
LPCRITICAL_SECTION cs = new CRITICAL_SECTION;
if (cs == 0) throw std::bad_alloc();
InitializeCriticalSection(cs);
m_mutex = reinterpret_cast<void*>(cs);
m_critsect = true;
}
}
@@ -226,6 +135,7 @@ try_mutex::try_mutex(const char* name)
HANDLE mutex = CreateMutex(0, 0, effective_name());
if (mutex == INVALID_HANDLE_VALUE)
throw thread_resource_error();
m_mutex = reinterpret_cast<void*>(mutex);
}
try_mutex::~try_mutex()
@@ -264,6 +174,7 @@ timed_mutex::timed_mutex(const char* name)
HANDLE mutex = CreateMutex(0, 0, effective_name());
if (mutex == INVALID_HANDLE_VALUE)
throw thread_resource_error();
m_mutex = reinterpret_cast<void*>(mutex);
}
timed_mutex::~timed_mutex()
@@ -288,7 +199,7 @@ bool timed_mutex::do_timedlock(const xtime& xt)
int milliseconds;
to_duration(xt, milliseconds);
int res = wait(m_mutex, milliseconds);
int res = wait(m_mutex, milliseconds);
if (res == WAIT_TIMEOUT)
{
@@ -304,7 +215,7 @@ bool timed_mutex::do_timedlock(const xtime& xt)
void timed_mutex::do_unlock()
{
release(m_mutex);
release(m_mutex);
}
void timed_mutex::do_lock(cv_state&)

View File

@@ -61,8 +61,7 @@ public:
{
creating,
running,
finished,
// joining,
finished,
joined
};
@@ -177,62 +176,71 @@ bool thread_data::release()
void thread_data::join()
{
boost::mutex::scoped_lock lock(m_mutex);
while (m_state != joined && m_state != finished)
m_cond.wait(lock);
if (m_state == finished)
{
int res = 0;
bool do_join=false;
{
boost::mutex::scoped_lock lock(m_mutex);
while (m_state != joined && m_state != finished)
m_cond.wait(lock);
do_join = (m_state == finished);
}
if (do_join)
{
int res = 0;
#if defined(BOOST_HAS_WINTHREADS)
res = WaitForSingleObject(m_thread, INFINITE);
assert(res == WAIT_OBJECT_0);
res = CloseHandle(m_thread);
assert(res);
res = WaitForSingleObject(m_thread, INFINITE);
assert(res == WAIT_OBJECT_0);
res = CloseHandle(m_thread);
assert(res);
#elif defined(BOOST_HAS_PTHREADS)
res = pthread_join(m_thread, 0);
assert(res == 0);
res = pthread_join(m_thread, 0);
assert(res == 0);
#elif defined(BOOST_HAS_MPTASKS)
OSStatus lStatus =
threads::mac::detail::safe_wait_on_queue(m_pJoinQueueID, NULL,
NULL, NULL,
kDurationForever);
assert(lStatus == noErr);
OSStatus lStatus =
threads::mac::detail::safe_wait_on_queue(m_pJoinQueueID, NULL,
NULL, NULL,
kDurationForever);
assert(lStatus == noErr);
#endif
m_state = joined;
m_cond.notify_all();
}
boost::mutex::scoped_lock lock(m_mutex);
m_state = joined;
m_cond.notify_all();
}
}
bool thread_data::timed_join(const boost::xtime& xt)
{
boost::mutex::scoped_lock lock(m_mutex);
while (m_state != joined && m_state != finished)
{
if (!m_cond.timed_wait(lock, xt))
return false;
}
if (m_state == finished)
{
int res = 0;
bool do_join=false;
{
boost::mutex::scoped_lock lock(m_mutex);
while (m_state != joined && m_state != finished)
{
if (!m_cond.timed_wait(lock, xt))
return false;
}
}
if (do_join)
{
int res = 0;
#if defined(BOOST_HAS_WINTHREADS)
res = WaitForSingleObject(m_thread, INFINITE);
assert(res == WAIT_OBJECT_0);
res = CloseHandle(m_thread);
assert(res);
res = WaitForSingleObject(m_thread, INFINITE);
assert(res == WAIT_OBJECT_0);
res = CloseHandle(m_thread);
assert(res);
#elif defined(BOOST_HAS_PTHREADS)
res = pthread_join(m_thread, 0);
assert(res == 0);
res = pthread_join(m_thread, 0);
assert(res == 0);
#elif defined(BOOST_HAS_MPTASKS)
OSStatus lStatus =
threads::mac::detail::safe_wait_on_queue(m_pJoinQueueID, NULL,
NULL, NULL,
kDurationForever);
assert(lStatus == noErr);
OSStatus lStatus =
threads::mac::detail::safe_wait_on_queue(m_pJoinQueueID, NULL,
NULL, NULL,
kDurationForever);
assert(lStatus == noErr);
#endif
m_state = joined;
m_cond.notify_all();
}
return true;
boost::mutex::scoped_lock lock(m_mutex);
m_state = joined;
m_cond.notify_all();
}
return true;
}
void thread_data::cancel()
@@ -282,7 +290,16 @@ void thread_data::run()
m_state = running;
m_cond.notify_all();
}
m_threadfunc();
try
{
m_threadfunc();
}
catch (boost::thread_cancel)
{
}
boost::mutex::scoped_lock lock(m_mutex);
m_state = finished;
m_cond.notify_all();
}
boost::thread::id_type thread_data::id() const
@@ -395,9 +412,6 @@ extern "C" {
tss_thread_data.reset(data);
data->run();
}
catch (boost::thread_cancel)
{
}
catch (...)
{
using namespace std;
@@ -842,7 +856,7 @@ void thread::sleep(const xtime& xt)
AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds));
threads::mac::detail::safe_delay_until(&sWakeTime);
#endif
thread::test_cancel();
thread::test_cancel();
xtime cur;
xtime_get(&cur, TIME_UTC);
if (xtime_cmp(xt, cur) <= 0)