mirror of
https://github.com/boostorg/thread.git
synced 2026-01-23 18:12:12 +00:00
Fixed coding style to match proposed Boost guidelines.
[SVN r10550]
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/semaphore.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <iostream>
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
@@ -1,25 +1,16 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 22 May 01 Modified to use xtime for time outs.
|
||||
* 23 May 01 Removed "duration" timed_waits, as they are too difficult
|
||||
* to use with spurious wakeups.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_CONDITION_HPP
|
||||
#define BOOST_CONDITION_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_CONDITION_WEK070601_HPP
|
||||
#define BOOST_CONDITION_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
@@ -27,130 +18,138 @@
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
class condition : private noncopyable
|
||||
{
|
||||
class condition : private noncopyable
|
||||
public:
|
||||
condition();
|
||||
~condition();
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
public:
|
||||
condition();
|
||||
~condition();
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const xtime& xt)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
return do_timed_wait(lock.m_mutex, xt);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const xtime& xt, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
do_wait(lock._mutex);
|
||||
if (!do_timed_wait(lock.m_mutex, xt))
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
do_wait(lock._mutex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const xtime& xt)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
return do_timed_wait(lock._mutex, xt);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const xtime& xt, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_timed_wait(lock._mutex, xt))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename M>
|
||||
void do_wait(M& mutex)
|
||||
{
|
||||
private:
|
||||
template <typename M>
|
||||
void do_wait(M& mutex)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
enter_wait();
|
||||
enter_wait();
|
||||
#endif
|
||||
|
||||
typename M::cv_state state;
|
||||
mutex.do_unlock(state);
|
||||
typename M::cv_state state;
|
||||
mutex.do_unlock(state);
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
do_wait(state.pmutex);
|
||||
do_wait(state.pmutex);
|
||||
#elif defined(BOOST_HAS_WINTHREADS)
|
||||
do_wait();
|
||||
do_wait();
|
||||
#endif
|
||||
|
||||
mutex.do_lock(state);
|
||||
}
|
||||
mutex.do_lock(state);
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
bool do_timed_wait(M& mutex, const xtime& xt)
|
||||
{
|
||||
template <typename M>
|
||||
bool do_timed_wait(M& mutex, const xtime& xt)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
enter_wait();
|
||||
enter_wait();
|
||||
#endif
|
||||
|
||||
typename M::cv_state state;
|
||||
mutex.do_unlock(state);
|
||||
typename M::cv_state state;
|
||||
mutex.do_unlock(state);
|
||||
|
||||
bool ret = false;
|
||||
bool ret = false;
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
ret = do_timed_wait(xt, state.pmutex);
|
||||
ret = do_timed_wait(xt, state.pmutex);
|
||||
#elif defined(BOOST_HAS_WINTHREADS)
|
||||
ret = do_timed_wait(xt);
|
||||
ret = do_timed_wait(xt);
|
||||
#endif
|
||||
|
||||
mutex.do_lock(state);
|
||||
mutex.do_lock(state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void enter_wait();
|
||||
void do_wait();
|
||||
bool do_timed_wait(const xtime& xt);
|
||||
void enter_wait();
|
||||
void do_wait();
|
||||
bool do_timed_wait(const xtime& xt);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
void do_wait(pthread_mutex_t* pmutex);
|
||||
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
|
||||
void do_wait(pthread_mutex_t* pmutex);
|
||||
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _gate;
|
||||
unsigned long _queue;
|
||||
unsigned long _mutex;
|
||||
unsigned _gone; // # threads that timed out and never made it to the _queue
|
||||
long _blocked; // # threads _blocked _waiting for the condition
|
||||
unsigned _waiting; // # threads _waiting no longer _waiting for the condition but still
|
||||
// _waiting to be removed from the _queue
|
||||
unsigned long m_gate;
|
||||
unsigned long m_queue;
|
||||
unsigned long m_mutex;
|
||||
unsigned m_gone; // # threads that timed out and never made it to the m_queue
|
||||
long m_blocked; // # threads m_blocked m_waiting for the condition
|
||||
unsigned m_waiting; // # threads m_waiting no longer m_waiting for the condition but still
|
||||
// m_waiting to be removed from the m_queue
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_cond_t _cond;
|
||||
pthread_cond_t m_condition;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_CONDITION_HPP
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too difficult
|
||||
// to use with spurious wakeups.
|
||||
|
||||
#endif // BOOST_CONDITION_WEK070601_HPP
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
// This file is used to configure Boost.Threads during development
|
||||
// in order to decouple dependency on any Boost release. Once
|
||||
// accepted into Boost these contents will be moved to <boost/config>
|
||||
@@ -5,8 +16,8 @@
|
||||
// #include <boost/thread/config.hpp> statements will be changed
|
||||
// accordingly.
|
||||
|
||||
#ifndef BOOST_THREAD_CONFIG_HPP
|
||||
#define BOOST_THREAD_CONFIG_HPP
|
||||
#ifndef BOOST_THREAD_CONFIG_WEK070601_HPP
|
||||
#define BOOST_THREAD_CONFIG_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
@@ -52,7 +63,7 @@
|
||||
# if defined(_MT)
|
||||
# define BOOST_HAS_THREADS
|
||||
# endif
|
||||
# define BOOST_HAS_WINTHREADS // comment out this to test pthreads-win32.
|
||||
//# define BOOST_HAS_WINTHREADS // comment out this to test pthreads-win32.
|
||||
# if !defined(BOOST_HAS_WINTHREADS)
|
||||
# define BOOST_HAS_PTHREADS
|
||||
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
@@ -62,4 +73,4 @@
|
||||
# define BOOST_HAS_FTIME
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // BOOST_THREAD_CONFIG_WEK070601_HPP
|
||||
@@ -1,23 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 22 May 01 Modified to use xtime for time outs. Factored out
|
||||
* to three classes, mutex, try_mutex and timed_mutex.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MUTEX_HPP
|
||||
#define BOOST_MUTEX_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_MUTEX_WEK070601_HPP
|
||||
#define BOOST_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
@@ -25,123 +18,129 @@
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/xlock.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
class mutex : private noncopyable
|
||||
{
|
||||
class condition;
|
||||
public:
|
||||
friend class basic_lock<mutex>;
|
||||
friend class condition;
|
||||
|
||||
class mutex : private noncopyable
|
||||
typedef basic_lock<mutex> lock;
|
||||
|
||||
mutex();
|
||||
~mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<mutex> lock;
|
||||
|
||||
mutex();
|
||||
~mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t _mutex;
|
||||
#endif
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
class try_mutex : private noncopyable
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class try_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<try_mutex>;
|
||||
friend class basic_trylock<try_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<try_mutex> lock;
|
||||
typedef basic_trylock<try_mutex> trylock;
|
||||
|
||||
try_mutex();
|
||||
~try_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<try_mutex>;
|
||||
friend class basic_trylock<try_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<try_mutex> lock;
|
||||
typedef basic_trylock<try_mutex> trylock;
|
||||
|
||||
try_mutex();
|
||||
~try_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t _mutex;
|
||||
#endif
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
class timed_mutex : private noncopyable
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class timed_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<timed_mutex>;
|
||||
friend class basic_trylock<timed_mutex>;
|
||||
friend class basic_timedlock<timed_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<timed_mutex> lock;
|
||||
typedef basic_trylock<timed_mutex> trylock;
|
||||
typedef basic_timedlock<timed_mutex> timedlock;
|
||||
|
||||
timed_mutex();
|
||||
~timed_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<timed_mutex>;
|
||||
friend class basic_trylock<timed_mutex>;
|
||||
friend class basic_timedlock<timed_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<timed_mutex> lock;
|
||||
typedef basic_trylock<timed_mutex> trylock;
|
||||
typedef basic_timedlock<timed_mutex> timedlock;
|
||||
|
||||
timed_mutex();
|
||||
~timed_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t _mutex;
|
||||
pthread_cond_t _cond;
|
||||
bool _locked;
|
||||
#endif
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_condition;
|
||||
bool m_locked;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MUTEX_HPP
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs. Factored out
|
||||
// to three classes, mutex, try_mutex and timed_mutex.
|
||||
|
||||
#endif // BOOST_MUTEX_WEK070601_HPP
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 1 Jun 01 Modified to use xtime for time outs. Factored out
|
||||
* to three classes, mutex, try_mutex and timed_mutex.
|
||||
* 11 Jun 01 Modified to use PTHREAD_MUTEX_RECURSIVE if available.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
@@ -32,136 +24,144 @@
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
class recursive_mutex : private noncopyable
|
||||
{
|
||||
class condition;
|
||||
public:
|
||||
friend class basic_lock<recursive_mutex>;
|
||||
friend class condition;
|
||||
|
||||
class recursive_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<recursive_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<recursive_mutex> lock;
|
||||
|
||||
recursive_mutex();
|
||||
~recursive_mutex();
|
||||
|
||||
private:
|
||||
typedef basic_lock<recursive_mutex> lock;
|
||||
|
||||
recursive_mutex();
|
||||
~recursive_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef size_t cv_state;
|
||||
typedef size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _mutex;
|
||||
unsigned long _count;
|
||||
unsigned long m_mutex;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t _mutex;
|
||||
unsigned _count;
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t _unlocked;
|
||||
pthread_t _thread_id;
|
||||
bool _valid_id;
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
# endif
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
class recursive_try_mutex : private noncopyable
|
||||
class recursive_try_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<recursive_try_mutex>;
|
||||
friend class basic_trylock<recursive_try_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<recursive_try_mutex> lock;
|
||||
typedef basic_trylock<recursive_try_mutex> trylock;
|
||||
|
||||
recursive_try_mutex();
|
||||
~recursive_try_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<recursive_try_mutex>;
|
||||
friend class basic_trylock<recursive_try_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<recursive_try_mutex> lock;
|
||||
typedef basic_trylock<recursive_try_mutex> trylock;
|
||||
|
||||
recursive_try_mutex();
|
||||
~recursive_try_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _mutex;
|
||||
unsigned long _count;
|
||||
unsigned long m_mutex;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t _mutex;
|
||||
unsigned _count;
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t _unlocked;
|
||||
pthread_t _thread_id;
|
||||
bool _valid_id;
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
# endif
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
class recursive_timed_mutex : private noncopyable
|
||||
class recursive_timed_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<recursive_timed_mutex>;
|
||||
friend class basic_trylock<recursive_timed_mutex>;
|
||||
friend class basic_timedlock<recursive_timed_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<recursive_timed_mutex> lock;
|
||||
typedef basic_trylock<recursive_timed_mutex> trylock;
|
||||
typedef basic_timedlock<recursive_timed_mutex> timedlock;
|
||||
|
||||
recursive_timed_mutex();
|
||||
~recursive_timed_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
public:
|
||||
friend class basic_lock<recursive_timed_mutex>;
|
||||
friend class basic_trylock<recursive_timed_mutex>;
|
||||
friend class basic_timedlock<recursive_timed_mutex>;
|
||||
friend class condition;
|
||||
|
||||
typedef basic_lock<recursive_timed_mutex> lock;
|
||||
typedef basic_trylock<recursive_timed_mutex> trylock;
|
||||
typedef basic_timedlock<recursive_timed_mutex> timedlock;
|
||||
|
||||
recursive_timed_mutex();
|
||||
~recursive_timed_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _mutex;
|
||||
unsigned long _count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t _mutex;
|
||||
pthread_cond_t _unlocked;
|
||||
pthread_t _thread_id;
|
||||
bool _valid_id;
|
||||
unsigned _count;
|
||||
#endif
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
unsigned m_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_HPP
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out
|
||||
// to three classes, mutex, try_mutex and timed_mutex.
|
||||
// 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available.
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 22 May 01 Modified to use xtime for time outs.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_SEMAPHORE_HPP
|
||||
#define BOOST_SEMAPHORE_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_SEMAPHORE_WEK070601_HPP
|
||||
#define BOOST_SEMAPHORE_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
@@ -25,33 +18,40 @@
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
class semaphore : private noncopyable
|
||||
{
|
||||
public:
|
||||
explicit semaphore(unsigned count=0, unsigned max=0);
|
||||
~semaphore();
|
||||
|
||||
bool up(unsigned count=1, unsigned* prev=0);
|
||||
void down();
|
||||
bool down(const xtime& xt);
|
||||
|
||||
private:
|
||||
|
||||
struct xtime;
|
||||
|
||||
class semaphore : private noncopyable
|
||||
{
|
||||
public:
|
||||
explicit semaphore(unsigned count=0, unsigned max=0);
|
||||
~semaphore();
|
||||
|
||||
bool up(unsigned count=1, unsigned* prev=0);
|
||||
void down();
|
||||
bool down(const xtime& xt);
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _sema;
|
||||
unsigned long m_sema;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t _mutex;
|
||||
pthread_cond_t _cond;
|
||||
unsigned _available;
|
||||
unsigned _max;
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_condition;
|
||||
unsigned m_available;
|
||||
unsigned m_max;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SEMAPHORE_HPP
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
|
||||
#endif // BOOST_SEMAPHORE_WEK070601_HPP
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 1 Jun 01 Added boost::thread initial implementation.
|
||||
* 3 Jul 01 Redesigned boost::thread to be noncopyable.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_THREAD_HPP
|
||||
#define BOOST_THREAD_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_THREAD_WEK070601_HPP
|
||||
#define BOOST_THREAD_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
@@ -26,7 +19,6 @@
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <stdexcept>
|
||||
@@ -36,62 +28,70 @@
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
class lock_error : public std::runtime_error
|
||||
{
|
||||
class lock_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
lock_error();
|
||||
};
|
||||
public:
|
||||
lock_error();
|
||||
};
|
||||
|
||||
class thread : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
thread();
|
||||
thread(const boost::function0<void>& threadfunc);
|
||||
~thread();
|
||||
class thread : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread();
|
||||
thread(const function0<void>& threadfunc);
|
||||
~thread();
|
||||
|
||||
bool operator==(const thread& other);
|
||||
bool operator!=(const thread& other);
|
||||
bool operator==(const thread& other) const;
|
||||
bool operator!=(const thread& other) const;
|
||||
|
||||
void join();
|
||||
bool try_join();
|
||||
bool timed_join(const xtime& xt);
|
||||
void join();
|
||||
bool try_join();
|
||||
bool timed_join(const xtime& xt);
|
||||
|
||||
static void sleep(const xtime& xt);
|
||||
static void yield();
|
||||
static void sleep(const xtime& xt);
|
||||
static void yield();
|
||||
|
||||
private:
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_thread;
|
||||
unsigned int m_id;
|
||||
unsigned long m_thread;
|
||||
unsigned int m_id;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
class thread_list;
|
||||
friend class thread_list;
|
||||
class thread_list;
|
||||
friend class thread_list;
|
||||
|
||||
pthread_t m_thread;
|
||||
mutex m_mutex;
|
||||
condition m_cond;
|
||||
bool m_alive;
|
||||
thread_list* m_list;
|
||||
pthread_t m_thread;
|
||||
mutex m_mutex;
|
||||
condition m_condition;
|
||||
bool m_alive;
|
||||
thread_list* m_state_manager;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
class thread_group : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
~thread_group();
|
||||
class thread_group : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
~thread_group();
|
||||
|
||||
thread* create_thread(const boost::function0<void>& threadfunc);
|
||||
void add_thread(thread* thrd);
|
||||
void remove_thread(thread* thrd);
|
||||
void join_all();
|
||||
thread* create_thread(const function0<void>& threadfunc);
|
||||
void add_thread(thread* thrd);
|
||||
void remove_thread(thread* thrd);
|
||||
void join_all();
|
||||
|
||||
private:
|
||||
std::list<thread*> m_threads;
|
||||
mutex m_mutex;
|
||||
};
|
||||
|
||||
private:
|
||||
std::list<thread*> m_threads;
|
||||
mutex m_mutex;
|
||||
};
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_HPP
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Added boost::thread initial implementation.
|
||||
// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable.
|
||||
|
||||
#endif // BOOST_THREAD_WEK070601_HPP
|
||||
|
||||
@@ -1,49 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 6 Jun 01 Initial version.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_TSS_HPP
|
||||
#define BOOST_TSS_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_TSS_WEK070601_HPP
|
||||
#define BOOST_TSS_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
class tss : private noncopyable
|
||||
{
|
||||
class tss
|
||||
{
|
||||
public:
|
||||
tss();
|
||||
~tss();
|
||||
public:
|
||||
tss();
|
||||
~tss();
|
||||
|
||||
void* get() const;
|
||||
bool set(void* value);
|
||||
void* get() const;
|
||||
bool set(void* value);
|
||||
|
||||
private:
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long _key;
|
||||
unsigned long m_key;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_key_t _key;
|
||||
pthread_key_t m_key;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BOOST_TSS_HPP
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 6 Jun 01 WEKEMPF Initial version.
|
||||
|
||||
#endif // BOOST_TSS_WEK070601_HPP
|
||||
@@ -1,162 +1,162 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 22 May 01 Modified to use xtime for time outs.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_XLOCK_HPP
|
||||
#define BOOST_XLOCK_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_XLOCK_WEK070601_HPP
|
||||
#define BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
namespace boost {
|
||||
class condition;
|
||||
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
template <typename M>
|
||||
class basic_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class condition;
|
||||
|
||||
template <typename M>
|
||||
class basic_lock : noncopyable
|
||||
{
|
||||
public:
|
||||
friend class condition;
|
||||
|
||||
typedef M mutex_type;
|
||||
|
||||
explicit basic_lock(M& mx, bool lock_it=true)
|
||||
: _mutex(mx), _locked(false)
|
||||
{
|
||||
if (lock_it) lock();
|
||||
}
|
||||
~basic_lock()
|
||||
{
|
||||
if (_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (_locked) throw lock_error();
|
||||
_mutex.do_lock();
|
||||
_locked = true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!_locked) throw lock_error();
|
||||
_mutex.do_unlock();
|
||||
_locked = false;
|
||||
}
|
||||
|
||||
operator const void*() const { return _locked ? this : 0; }
|
||||
|
||||
private:
|
||||
M& _mutex;
|
||||
bool _locked;
|
||||
};
|
||||
typedef M mutex_type;
|
||||
|
||||
template <typename M>
|
||||
class basic_trylock : private noncopyable
|
||||
explicit basic_lock(M& mx, bool lock_it=true)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
public:
|
||||
friend class condition;
|
||||
|
||||
typedef M mutex_type;
|
||||
|
||||
explicit basic_trylock(M& mx)
|
||||
: _mutex(mx), _locked(false)
|
||||
{
|
||||
try_lock();
|
||||
}
|
||||
basic_trylock(M& mx, bool lock_it)
|
||||
: _mutex(mx), _locked(false)
|
||||
{
|
||||
if (lock_it) lock();
|
||||
}
|
||||
~basic_trylock()
|
||||
{
|
||||
if (_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (_locked) throw lock_error();
|
||||
_mutex.do_lock();
|
||||
_locked = true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if (_locked) throw lock_error();
|
||||
return (_locked = _mutex.do_trylock());
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!_locked) throw lock_error();
|
||||
_mutex.do_unlock();
|
||||
_locked = false;
|
||||
}
|
||||
|
||||
operator const void*() const { return _locked ? this : 0; }
|
||||
|
||||
private:
|
||||
M& _mutex;
|
||||
bool _locked;
|
||||
};
|
||||
if (lock_it) lock();
|
||||
}
|
||||
~basic_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
class basic_timedlock : private noncopyable
|
||||
void lock()
|
||||
{
|
||||
public:
|
||||
friend class condition;
|
||||
|
||||
typedef M mutex_type;
|
||||
|
||||
basic_timedlock(M& mx, const xtime& xt)
|
||||
: _mutex(mx), _locked(false)
|
||||
{
|
||||
timed_lock(xt);
|
||||
}
|
||||
basic_timedlock(M& mx, bool lock_it)
|
||||
: _mutex(mx), _locked(false)
|
||||
{
|
||||
if (lock_it) lock();
|
||||
}
|
||||
~basic_timedlock()
|
||||
{
|
||||
if (_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (_locked) throw lock_error();
|
||||
_mutex.do_lock();
|
||||
_locked = true;
|
||||
}
|
||||
bool timed_lock(const xtime& xt)
|
||||
{
|
||||
if (_locked) throw lock_error();
|
||||
return (_locked = _mutex.do_timedlock(xt));
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!_locked) throw lock_error();
|
||||
_mutex.do_unlock();
|
||||
_locked = false;
|
||||
}
|
||||
|
||||
operator const void*() const { return _locked ? this : 0; }
|
||||
|
||||
private:
|
||||
M& _mutex;
|
||||
bool _locked;
|
||||
};
|
||||
if (m_locked) throw lock_error();
|
||||
m_mutex.do_lock();
|
||||
m_locked = true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
m_mutex.do_unlock();
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
M& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
class basic_trylock : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class condition;
|
||||
|
||||
typedef M mutex_type;
|
||||
|
||||
explicit basic_trylock(M& mx)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
try_lock();
|
||||
}
|
||||
basic_trylock(M& mx, bool lock_it)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (lock_it) lock();
|
||||
}
|
||||
~basic_trylock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
m_mutex.do_lock();
|
||||
m_locked = true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = m_mutex.do_trylock());
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
m_mutex.do_unlock();
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
M& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
class basic_timedlock : private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class condition;
|
||||
|
||||
typedef M mutex_type;
|
||||
|
||||
basic_timedlock(M& mx, const xtime& xt)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
timed_lock(xt);
|
||||
}
|
||||
basic_timedlock(M& mx, bool lock_it)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (lock_it) lock();
|
||||
}
|
||||
~basic_timedlock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
m_mutex.do_lock();
|
||||
m_locked = true;
|
||||
}
|
||||
bool timed_lock(const xtime& xt)
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = m_mutex.do_timedlock(xt));
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
m_mutex.do_unlock();
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
M& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_XLOCK_HPP
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
|
||||
#endif // BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
@@ -1,49 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_XTIME_HPP
|
||||
#define BOOST_XTIME_HPP
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_XTIME_WEK070601_HPP
|
||||
#define BOOST_XTIME_WEK070601_HPP
|
||||
|
||||
#include <boost/stdint.h>
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
TIME_UTC=1,
|
||||
TIME_TAI,
|
||||
TIME_MONOTONIC,
|
||||
TIME_PROCESS,
|
||||
TIME_THREAD,
|
||||
TIME_LOCAL,
|
||||
TIME_SYNC,
|
||||
TIME_RESOLUTION
|
||||
};
|
||||
TIME_UTC=1,
|
||||
TIME_TAI,
|
||||
TIME_MONOTONIC,
|
||||
TIME_PROCESS,
|
||||
TIME_THREAD,
|
||||
TIME_LOCAL,
|
||||
TIME_SYNC,
|
||||
TIME_RESOLUTION
|
||||
};
|
||||
|
||||
struct xtime
|
||||
{
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
int_fast32_t sec;
|
||||
int_fast32_t sec;
|
||||
#else
|
||||
int_fast64_t sec;
|
||||
int_fast64_t sec;
|
||||
#endif
|
||||
int_fast32_t nsec;
|
||||
};
|
||||
int_fast32_t nsec;
|
||||
};
|
||||
|
||||
int xtime_get(struct xtime* xtp, int clock_type);
|
||||
}
|
||||
int xtime_get(struct xtime* xtp, int clock_type);
|
||||
|
||||
#endif // BOOST_XTIME_HPP
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
|
||||
#endif // BOOST_XTIME_WEK070601_HPP
|
||||
@@ -1,23 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 22 May 01 Modified to use xtime for time outs.
|
||||
*/
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <limits>
|
||||
#include <cassert>
|
||||
#include "timeconv.inl"
|
||||
@@ -28,312 +22,317 @@
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace boost {
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
condition::condition()
|
||||
: _gone(0), _blocked(0), _waiting(0)
|
||||
condition::condition()
|
||||
: m_gone(0), m_blocked(0), m_waiting(0)
|
||||
{
|
||||
m_gate = reinterpret_cast<unsigned long>(CreateSemaphore(0, 1, 1, 0));
|
||||
m_queue = reinterpret_cast<unsigned long>(CreateSemaphore(0, 0, std::numeric_limits<long>::max(), 0));
|
||||
m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
|
||||
if (!m_gate || !m_queue || !m_mutex)
|
||||
{
|
||||
_gate = reinterpret_cast<unsigned long>(CreateSemaphore(0, 1, 1, 0));
|
||||
_queue = reinterpret_cast<unsigned long>(CreateSemaphore(0, 0, std::numeric_limits<long>::max(), 0));
|
||||
_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (!_gate || !_queue || !_mutex)
|
||||
throw std::runtime_error("boost::condition : failure to construct");
|
||||
}
|
||||
}
|
||||
|
||||
condition::~condition()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void condition::notify_one()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
if (m_waiting != 0) // the m_gate is already closed
|
||||
{
|
||||
if (m_blocked == 0)
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(_gate));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(_queue));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(_mutex));
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
return;
|
||||
}
|
||||
|
||||
throw std::runtime_error("boost::condition : failure to construct");
|
||||
++m_waiting;
|
||||
--m_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
if (m_blocked > m_gone)
|
||||
{
|
||||
if (m_gone != 0)
|
||||
{
|
||||
m_blocked -= m_gone;
|
||||
m_gone = 0;
|
||||
}
|
||||
signals = m_waiting = 1;
|
||||
--m_blocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void condition::notify_all()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
if (m_waiting != 0) // the m_gate is already closed
|
||||
{
|
||||
if (m_blocked == 0)
|
||||
{
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
return;
|
||||
}
|
||||
|
||||
m_waiting += (signals = m_blocked);
|
||||
m_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
if (m_blocked > m_gone)
|
||||
{
|
||||
if (m_gone != 0)
|
||||
{
|
||||
m_blocked -= m_gone;
|
||||
m_gone = 0;
|
||||
}
|
||||
signals = m_waiting = m_blocked;
|
||||
m_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void condition::enter_wait()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
++m_blocked;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void condition::do_wait()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
condition::~condition()
|
||||
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)
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(_gate));
|
||||
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);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(_queue));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(_mutex));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void condition::notify_one()
|
||||
bool condition::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
|
||||
bool ret = (res == WAIT_OBJECT_0);
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
if (_waiting != 0) // the _gate is already closed
|
||||
if (!ret) // timeout
|
||||
{
|
||||
if (_blocked == 0)
|
||||
{
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
return;
|
||||
}
|
||||
|
||||
++_waiting;
|
||||
--_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
if (_blocked > _gone)
|
||||
{
|
||||
if (_gone != 0)
|
||||
{
|
||||
_blocked -= _gone;
|
||||
_gone = 0;
|
||||
}
|
||||
signals = _waiting = 1;
|
||||
--_blocked;
|
||||
}
|
||||
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>(_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_queue), signals, 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;
|
||||
}
|
||||
}
|
||||
|
||||
void condition::notify_all()
|
||||
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), INFINITE);
|
||||
// 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);
|
||||
|
||||
if (_waiting != 0) // the _gate is already closed
|
||||
{
|
||||
if (_blocked == 0)
|
||||
{
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
return;
|
||||
}
|
||||
|
||||
_waiting += (signals = _blocked);
|
||||
_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
if (_blocked > _gone)
|
||||
{
|
||||
if (_gone != 0)
|
||||
{
|
||||
_blocked -= _gone;
|
||||
_gone = 0;
|
||||
}
|
||||
signals = _waiting = _blocked;
|
||||
_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_queue), signals, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
void condition::enter_wait()
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
++_blocked;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
void condition::do_wait()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_queue), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
was_waiting = _waiting;
|
||||
was_gone = _gone;
|
||||
if (was_waiting != 0)
|
||||
{
|
||||
if (--_waiting == 0)
|
||||
{
|
||||
if (_blocked != 0)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0); // open _gate
|
||||
assert(res);
|
||||
was_waiting = 0;
|
||||
}
|
||||
else if (_gone != 0)
|
||||
_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++_gone == (std::numeric_limits<unsigned>::max() / 2))
|
||||
{
|
||||
// timeout occured, normalize the _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>(_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
_blocked -= _gone;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0);
|
||||
assert(res);
|
||||
_gone = 0;
|
||||
}
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(_queue), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
bool condition::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_queue), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
|
||||
bool ret = (res == WAIT_OBJECT_0);
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
was_waiting = _waiting;
|
||||
was_gone = _gone;
|
||||
if (was_waiting != 0)
|
||||
{
|
||||
if (!ret) // timeout
|
||||
{
|
||||
if (_blocked != 0)
|
||||
--_blocked;
|
||||
else
|
||||
++_gone; // count spurious wakeups
|
||||
}
|
||||
if (--_waiting == 0)
|
||||
{
|
||||
if (_blocked != 0)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0); // open _gate
|
||||
assert(res);
|
||||
was_waiting = 0;
|
||||
}
|
||||
else if (_gone != 0)
|
||||
_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++_gone == (std::numeric_limits<unsigned>::max() / 2))
|
||||
{
|
||||
// timeout occured, normalize the _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>(_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
_blocked -= _gone;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0);
|
||||
assert(res);
|
||||
_gone = 0;
|
||||
}
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(_queue), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
condition::condition()
|
||||
{
|
||||
int res = pthread_cond_init(&_cond, 0);
|
||||
assert(res == 0);
|
||||
condition::condition()
|
||||
{
|
||||
int res = pthread_cond_init(&m_condition, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::condition : failure to construct");
|
||||
}
|
||||
|
||||
condition::~condition()
|
||||
{
|
||||
int res = pthread_cond_destroy(&_cond);
|
||||
assert(res == 0);
|
||||
}
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::condition : failure to construct");
|
||||
}
|
||||
|
||||
void condition::notify_one()
|
||||
{
|
||||
int res = pthread_cond_signal(&_cond);
|
||||
assert(res == 0);
|
||||
}
|
||||
condition::~condition()
|
||||
{
|
||||
int res = pthread_cond_destroy(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition::notify_all()
|
||||
{
|
||||
int res = pthread_cond_broadcast(&_cond);
|
||||
assert(res == 0);
|
||||
}
|
||||
void condition::notify_one()
|
||||
{
|
||||
int res = pthread_cond_signal(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition::do_wait(pthread_mutex_t* pmutex)
|
||||
{
|
||||
int res = pthread_cond_wait(&_cond, pmutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
void condition::notify_all()
|
||||
{
|
||||
int res = pthread_cond_broadcast(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
|
||||
{
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
void condition::do_wait(pthread_mutex_t* pmutex)
|
||||
{
|
||||
int res = pthread_cond_wait(&m_condition, pmutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
int res = pthread_cond_timedwait(&_cond, pmutex, &ts);
|
||||
assert(res == 0 || res == ETIMEDOUT);
|
||||
bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
|
||||
{
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
|
||||
return res != ETIMEDOUT;
|
||||
}
|
||||
int res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
|
||||
assert(res == 0 || res == ETIMEDOUT);
|
||||
|
||||
return res != ETIMEDOUT;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
|
||||
701
src/mutex.cpp
701
src/mutex.cpp
@@ -1,24 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
*/
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <ctime>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include "timeconv.inl"
|
||||
|
||||
@@ -29,371 +24,365 @@
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hack around various namespace challenged compilers
|
||||
*/
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std {
|
||||
using ::clock_t;
|
||||
using ::clock;
|
||||
} // namespace std
|
||||
#endif
|
||||
namespace boost {
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
mutex::mutex()
|
||||
{
|
||||
_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
assert(_mutex);
|
||||
mutex::mutex()
|
||||
{
|
||||
m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
assert(m_mutex);
|
||||
|
||||
if (!_mutex)
|
||||
throw std::runtime_error("boost::mutex : failure to construct");
|
||||
}
|
||||
if (!m_mutex)
|
||||
throw std::runtime_error("boost::mutex : failure to construct");
|
||||
}
|
||||
|
||||
mutex::~mutex()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void mutex::do_lock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
void mutex::do_unlock()
|
||||
{
|
||||
int res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void mutex::do_lock(cv_state& state)
|
||||
{
|
||||
do_lock();
|
||||
}
|
||||
|
||||
void mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
do_unlock();
|
||||
}
|
||||
mutex::~mutex()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
try_mutex::try_mutex()
|
||||
{
|
||||
_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
assert(_mutex);
|
||||
void mutex::do_lock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
if (!_mutex)
|
||||
throw std::runtime_error("boost::try_mutex : failure to construct");
|
||||
}
|
||||
void mutex::do_unlock()
|
||||
{
|
||||
int res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
try_mutex::~try_mutex()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
bool try_mutex::do_trylock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), 0);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock()
|
||||
{
|
||||
int res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
do_lock();
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
do_unlock();
|
||||
}
|
||||
void mutex::do_lock(cv_state& state)
|
||||
{
|
||||
do_lock();
|
||||
}
|
||||
|
||||
timed_mutex::timed_mutex()
|
||||
{
|
||||
_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
assert(_mutex);
|
||||
void mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
do_unlock();
|
||||
}
|
||||
|
||||
if (!_mutex)
|
||||
throw std::runtime_error("boost::timed_mutex : failure to construct");
|
||||
}
|
||||
try_mutex::try_mutex()
|
||||
{
|
||||
m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
assert(m_mutex);
|
||||
|
||||
timed_mutex::~timed_mutex()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
bool timed_mutex::do_trylock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), 0);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
bool timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
if (!m_mutex)
|
||||
throw std::runtime_error("boost::try_mutex : failure to construct");
|
||||
}
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_mutex), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
void timed_mutex::do_unlock()
|
||||
{
|
||||
int res = ReleaseMutex(reinterpret_cast<HANDLE>(_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
do_lock();
|
||||
}
|
||||
|
||||
void timed_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
do_unlock();
|
||||
}
|
||||
try_mutex::~try_mutex()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
bool try_mutex::do_trylock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock()
|
||||
{
|
||||
int res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
do_lock();
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
do_unlock();
|
||||
}
|
||||
|
||||
timed_mutex::timed_mutex()
|
||||
{
|
||||
m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
assert(m_mutex);
|
||||
|
||||
if (!m_mutex)
|
||||
throw std::runtime_error("boost::timed_mutex : failure to construct");
|
||||
}
|
||||
|
||||
timed_mutex::~timed_mutex()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
bool timed_mutex::do_trylock()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
bool timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
void timed_mutex::do_unlock()
|
||||
{
|
||||
int res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
do_lock();
|
||||
}
|
||||
|
||||
void timed_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
do_unlock();
|
||||
}
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
mutex::mutex()
|
||||
{
|
||||
int res = pthread_mutex_init(&_mutex, 0);
|
||||
assert(res == 0);
|
||||
mutex::mutex()
|
||||
{
|
||||
int res = pthread_mutex_init(&m_mutex, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::mutex : failure to construct");
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::mutex : failure to construct");
|
||||
}
|
||||
|
||||
mutex::~mutex()
|
||||
{
|
||||
int res = pthread_mutex_destroy(&m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void mutex::do_lock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
if (res == EDEADLK) throw lock_error();
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void mutex::do_unlock()
|
||||
{
|
||||
int res = pthread_mutex_unlock(&m_mutex);
|
||||
if (res == EPERM) throw lock_error();
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void mutex::do_lock(cv_state& state)
|
||||
{
|
||||
}
|
||||
|
||||
void mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
state.pmutex = &m_mutex;
|
||||
}
|
||||
|
||||
try_mutex::try_mutex()
|
||||
{
|
||||
int res = pthread_mutex_init(&m_mutex, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::try_mutex : failure to construct");
|
||||
}
|
||||
|
||||
try_mutex::~try_mutex()
|
||||
{
|
||||
int res = pthread_mutex_destroy(&m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
if (res == EDEADLK) throw lock_error();
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool try_mutex::do_trylock()
|
||||
{
|
||||
int res = pthread_mutex_trylock(&m_mutex);
|
||||
if (res == EDEADLK) throw lock_error();
|
||||
assert(res == 0 || res == EBUSY);
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock()
|
||||
{
|
||||
int res = pthread_mutex_unlock(&m_mutex);
|
||||
if (res == EPERM) throw lock_error();
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
state.pmutex = &m_mutex;
|
||||
}
|
||||
|
||||
timed_mutex::timed_mutex()
|
||||
: m_locked(false)
|
||||
{
|
||||
int res = pthread_mutex_init(&m_mutex, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::timed_mutex : failure to construct");
|
||||
|
||||
res = pthread_cond_init(&m_condition, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::timed_mutex : failure to construct");
|
||||
}
|
||||
|
||||
timed_mutex::~timed_mutex()
|
||||
{
|
||||
assert(!m_locked);
|
||||
int res = pthread_mutex_destroy(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_cond_destroy(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
while (m_locked)
|
||||
{
|
||||
res = pthread_cond_wait(&m_condition, &m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
assert(!m_locked);
|
||||
m_locked = true;
|
||||
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool timed_mutex::do_trylock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
bool ret = false;
|
||||
if (!m_locked)
|
||||
{
|
||||
m_locked = true;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
|
||||
while (m_locked)
|
||||
{
|
||||
res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts);
|
||||
assert(res == 0 || res == ETIMEDOUT);
|
||||
|
||||
if (res == ETIMEDOUT)
|
||||
break;
|
||||
}
|
||||
|
||||
mutex::~mutex()
|
||||
bool ret = false;
|
||||
if (!m_locked)
|
||||
{
|
||||
int res = pthread_mutex_destroy(&_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void mutex::do_lock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
if (res == EDEADLK) throw lock_error();
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void mutex::do_unlock()
|
||||
{
|
||||
int res = pthread_mutex_unlock(&_mutex);
|
||||
if (res == EPERM) throw lock_error();
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void mutex::do_lock(cv_state& state)
|
||||
{
|
||||
}
|
||||
|
||||
void mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
state.pmutex = &_mutex;
|
||||
m_locked = true;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
try_mutex::try_mutex()
|
||||
{
|
||||
int res = pthread_mutex_init(&_mutex, 0);
|
||||
assert(res == 0);
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::try_mutex : failure to construct");
|
||||
}
|
||||
|
||||
try_mutex::~try_mutex()
|
||||
void timed_mutex::do_unlock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
assert(m_locked);
|
||||
m_locked = false;
|
||||
|
||||
res = pthread_cond_signal(&m_condition);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
int res;
|
||||
while (m_locked)
|
||||
{
|
||||
int res = pthread_mutex_destroy(&_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
if (res == EDEADLK) throw lock_error();
|
||||
res = pthread_cond_wait(&m_condition, &m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool try_mutex::do_trylock()
|
||||
{
|
||||
int res = pthread_mutex_trylock(&_mutex);
|
||||
if (res == EDEADLK) throw lock_error();
|
||||
assert(res == 0 || res == EBUSY);
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock()
|
||||
{
|
||||
int res = pthread_mutex_unlock(&_mutex);
|
||||
if (res == EPERM) throw lock_error();
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void try_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
}
|
||||
|
||||
void try_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
state.pmutex = &_mutex;
|
||||
}
|
||||
assert(!m_locked);
|
||||
m_locked = true;
|
||||
|
||||
timed_mutex::timed_mutex()
|
||||
: _locked(false)
|
||||
{
|
||||
int res = pthread_mutex_init(&_mutex, 0);
|
||||
assert(res == 0);
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::timed_mutex : failure to construct");
|
||||
void timed_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_cond_init(&_cond, 0);
|
||||
assert(res == 0);
|
||||
assert(m_locked);
|
||||
m_locked = false;
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::timed_mutex : failure to construct");
|
||||
}
|
||||
res = pthread_cond_signal(&m_condition);
|
||||
assert(res == 0);
|
||||
|
||||
timed_mutex::~timed_mutex()
|
||||
{
|
||||
assert(!_locked);
|
||||
int res = pthread_mutex_destroy(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_cond_destroy(&_cond);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
while (_locked)
|
||||
{
|
||||
res = pthread_cond_wait(&_cond, &_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
assert(!_locked);
|
||||
_locked = true;
|
||||
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool timed_mutex::do_trylock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
bool ret = false;
|
||||
if (!_locked)
|
||||
{
|
||||
_locked = true;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool timed_mutex::do_timedlock(const xtime& xt)
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
|
||||
while (_locked)
|
||||
{
|
||||
res = pthread_cond_timedwait(&_cond, &_mutex, &ts);
|
||||
assert(res == 0 || res == ETIMEDOUT);
|
||||
|
||||
if (res == ETIMEDOUT)
|
||||
break;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
if (!_locked)
|
||||
{
|
||||
_locked = true;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void timed_mutex::do_unlock()
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
assert(_locked);
|
||||
_locked = false;
|
||||
|
||||
res = pthread_cond_signal(&_cond);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void timed_mutex::do_lock(cv_state& state)
|
||||
{
|
||||
int res;
|
||||
while (_locked)
|
||||
{
|
||||
res = pthread_cond_wait(&_cond, &_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
assert(!_locked);
|
||||
_locked = true;
|
||||
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void timed_mutex::do_unlock(cv_state& state)
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
assert(_locked);
|
||||
_locked = false;
|
||||
|
||||
res = pthread_cond_signal(&_cond);
|
||||
assert(res == 0);
|
||||
|
||||
state.pmutex = &_mutex;
|
||||
}
|
||||
state.pmutex = &m_mutex;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 22 May 01 Modified to use xtime for time outs.
|
||||
*/
|
||||
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/semaphore.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include "timeconv.inl"
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
@@ -30,154 +24,150 @@
|
||||
# include <boost/thread/condition.hpp>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hack around various namespace challenged compilers
|
||||
*/
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std {
|
||||
using ::clock_t;
|
||||
using ::clock;
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
semaphore::semaphore(unsigned count, unsigned max)
|
||||
{
|
||||
if (static_cast<long>(max) <= 0)
|
||||
max = std::numeric_limits<long>::max();
|
||||
semaphore::semaphore(unsigned count, unsigned max)
|
||||
{
|
||||
if (static_cast<long>(max) <= 0)
|
||||
max = std::numeric_limits<long>::max();
|
||||
|
||||
_sema = reinterpret_cast<unsigned long>(CreateSemaphore(0, count, max, 0));
|
||||
assert(_sema != 0);
|
||||
m_sema = reinterpret_cast<unsigned long>(CreateSemaphore(0, count, max, 0));
|
||||
assert(m_sema != 0);
|
||||
|
||||
if (!_sema)
|
||||
throw std::runtime_error("boost::semaphore : failure to construct");
|
||||
}
|
||||
|
||||
semaphore::~semaphore()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(_sema));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
bool semaphore::up(unsigned count, unsigned* prev)
|
||||
{
|
||||
long p;
|
||||
bool ret = !!ReleaseSemaphore(reinterpret_cast<HANDLE>(_sema), count, &p);
|
||||
assert(ret || GetLastError() == ERROR_TOO_MANY_POSTS);
|
||||
if (!m_sema)
|
||||
throw std::runtime_error("boost::semaphore : failure to construct");
|
||||
}
|
||||
|
||||
if (prev)
|
||||
*prev = p;
|
||||
semaphore::~semaphore()
|
||||
{
|
||||
int res = CloseHandle(reinterpret_cast<HANDLE>(m_sema));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void semaphore::down()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_sema), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
bool semaphore::up(unsigned count, unsigned* prev)
|
||||
{
|
||||
long p;
|
||||
bool ret = !!ReleaseSemaphore(reinterpret_cast<HANDLE>(m_sema), count, &p);
|
||||
assert(ret || GetLastError() == ERROR_TOO_MANY_POSTS);
|
||||
|
||||
bool semaphore::down(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(_sema), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
if (prev)
|
||||
*prev = p;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void semaphore::down()
|
||||
{
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_sema), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
bool semaphore::down(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_sema), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
return res == WAIT_OBJECT_0;
|
||||
}
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
semaphore::semaphore(unsigned count, unsigned max)
|
||||
: _available(count), _max(max ? max : std::numeric_limits<unsigned>::max())
|
||||
semaphore::semaphore(unsigned count, unsigned max)
|
||||
: m_available(count), m_max(max ? max : std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
int res = pthread_mutex_init(&m_mutex, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::semaphore : failure to construct");
|
||||
|
||||
res = pthread_cond_init(&m_condition, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::semaphore : failure to construct");
|
||||
}
|
||||
|
||||
semaphore::~semaphore()
|
||||
{
|
||||
int res = pthread_mutex_destroy(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_cond_destroy(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool semaphore::up(unsigned count, unsigned* prev)
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
if (prev)
|
||||
*prev = m_available;
|
||||
|
||||
if (m_available + count > m_max)
|
||||
{
|
||||
int res = pthread_mutex_init(&_mutex, 0);
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::semaphore : failure to construct");
|
||||
|
||||
res = pthread_cond_init(&_cond, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::semaphore : failure to construct");
|
||||
return false;
|
||||
}
|
||||
|
||||
semaphore::~semaphore()
|
||||
{
|
||||
int res = pthread_mutex_destroy(&_mutex);
|
||||
assert(res == 0);
|
||||
m_available += count;
|
||||
|
||||
res = pthread_cond_destroy(&_cond);
|
||||
res = pthread_cond_broadcast(&m_condition);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void semaphore::down()
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
while (m_available == 0)
|
||||
{
|
||||
res = pthread_cond_wait(&m_condition, &m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool semaphore::up(unsigned count, unsigned* prev)
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
if (prev)
|
||||
*prev = _available;
|
||||
|
||||
if (_available + count > _max)
|
||||
m_available--;
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool semaphore::down(const xtime& xt)
|
||||
{
|
||||
int res = pthread_mutex_lock(&m_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
|
||||
while (m_available == 0)
|
||||
{
|
||||
res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts);
|
||||
assert(res == 0 || res == ETIMEDOUT);
|
||||
|
||||
if (res == ETIMEDOUT)
|
||||
{
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
_available += count;
|
||||
|
||||
res = pthread_cond_broadcast(&_cond);
|
||||
assert(res == 0);
|
||||
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void semaphore::down()
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
while (_available == 0)
|
||||
{
|
||||
res = pthread_cond_wait(&_cond, &_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
_available--;
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool semaphore::down(const xtime& xt)
|
||||
{
|
||||
int res = pthread_mutex_lock(&_mutex);
|
||||
assert(res == 0);
|
||||
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
|
||||
while (_available == 0)
|
||||
{
|
||||
res = pthread_cond_timedwait(&_cond, &_mutex, &ts);
|
||||
assert(res == 0 || res == ETIMEDOUT);
|
||||
|
||||
if (res == ETIMEDOUT)
|
||||
{
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_available--;
|
||||
res = pthread_mutex_unlock(&_mutex);
|
||||
assert(res == 0);
|
||||
return true;
|
||||
}
|
||||
m_available--;
|
||||
res = pthread_mutex_unlock(&m_mutex);
|
||||
assert(res == 0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
|
||||
556
src/thread.cpp
556
src/thread.cpp
@@ -1,23 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
* 1 Jun 01 Added boost::thread initial implementation.
|
||||
* 3 Jul 01 Redesigned boost::thread to be noncopyable.
|
||||
*/
|
||||
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/semaphore.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
@@ -28,331 +22,339 @@
|
||||
#include "timeconv.inl"
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
// This class is used to signal thread objects when the thread dies.
|
||||
class thread::thread_list
|
||||
{
|
||||
// This class is used to signal thread objects when the thread dies.
|
||||
class thread::thread_list
|
||||
public:
|
||||
thread_list() { }
|
||||
~thread_list()
|
||||
{
|
||||
public:
|
||||
thread_list() { }
|
||||
~thread_list()
|
||||
mutex::lock lock(m_mutex);
|
||||
for (std::list<thread*>::iterator it = m_thread_objects.begin(); it != m_thread_objects.end(); ++it)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
for (std::list<thread*>::iterator it = m_list.begin(); it != m_list.end(); ++it)
|
||||
{
|
||||
mutex::lock lock((*it)->m_mutex);
|
||||
(*it)->m_list = 0;
|
||||
(*it)->m_cond.notify_all();
|
||||
}
|
||||
mutex::lock lock((*it)->m_mutex);
|
||||
(*it)->m_state_manager = 0;
|
||||
(*it)->m_condition.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
void add(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
m_list.push_back(thrd);
|
||||
}
|
||||
void add(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
m_thread_objects.push_back(thrd);
|
||||
}
|
||||
|
||||
void remove(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
std::list<thread*>::iterator it = std::find(m_list.begin(), m_list.end(), thrd);
|
||||
if (it != m_list.end())
|
||||
m_list.erase(it);
|
||||
}
|
||||
void remove(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
std::list<thread*>::iterator it = std::find(m_thread_objects.begin(), m_thread_objects.end(), thrd);
|
||||
if (it != m_thread_objects.end())
|
||||
m_thread_objects.erase(it);
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<thread*> m_list;
|
||||
mutex m_mutex;
|
||||
};
|
||||
private:
|
||||
std::list<thread*> m_thread_objects;
|
||||
mutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
pthread_key_t key;
|
||||
pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
|
||||
void destroy_list(void* p)
|
||||
{
|
||||
boost::thread::thread_list* list = static_cast<boost::thread::thread_list*>(p);
|
||||
delete list;
|
||||
}
|
||||
|
||||
void init_key()
|
||||
{
|
||||
int res = pthread_key_create(&key, &destroy_list);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
pthread_key_t get_key()
|
||||
{
|
||||
int res = pthread_once(&once, &init_key);
|
||||
assert(res == 0);
|
||||
return key;
|
||||
}
|
||||
|
||||
boost::thread::thread_list* get_list()
|
||||
{
|
||||
pthread_key_t key = get_key();
|
||||
boost::thread::thread_list* list = static_cast<boost::thread::thread_list*>(pthread_getspecific(key));
|
||||
if (!list)
|
||||
{
|
||||
list = new boost::thread::thread_list;
|
||||
pthread_setspecific(key, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace
|
||||
class thread_param
|
||||
{
|
||||
public:
|
||||
thread_param(const boost::function0<void>& threadfunc) : m_threadfunc(threadfunc), m_started(false) { }
|
||||
void wait()
|
||||
{
|
||||
boost::mutex::lock lock(m_mutex);
|
||||
while (!m_started)
|
||||
m_condition.wait(lock);
|
||||
}
|
||||
void started()
|
||||
{
|
||||
boost::mutex::lock lock(m_mutex);
|
||||
m_started = true;
|
||||
m_condition.notify_one();
|
||||
}
|
||||
|
||||
boost::mutex m_mutex;
|
||||
boost::condition m_condition;
|
||||
const boost::function0<void>& m_threadfunc;
|
||||
bool m_started;
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
pthread_key_t key;
|
||||
pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
|
||||
void destroy_list(void* p)
|
||||
{
|
||||
boost::thread::thread_list* list = static_cast<boost::thread::thread_list*>(p);
|
||||
delete list;
|
||||
}
|
||||
|
||||
void init_key()
|
||||
{
|
||||
int res = pthread_key_create(&key, &destroy_list);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
pthread_key_t get_key()
|
||||
{
|
||||
int res = pthread_once(&once, &init_key);
|
||||
assert(res == 0);
|
||||
return key;
|
||||
}
|
||||
|
||||
boost::thread::thread_list* get_list()
|
||||
{
|
||||
pthread_key_t key = get_key();
|
||||
boost::thread::thread_list* list = static_cast<boost::thread::thread_list*>(pthread_getspecific(key));
|
||||
if (!list)
|
||||
{
|
||||
list = new boost::thread::thread_list;
|
||||
pthread_setspecific(key, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
boost::thread::thread_list* m_state_manager;
|
||||
#endif
|
||||
|
||||
class thread_param
|
||||
{
|
||||
public:
|
||||
thread_param(const boost::function0<void>& threadfunc) : m_threadfunc(threadfunc), m_started(false) { }
|
||||
void wait()
|
||||
{
|
||||
boost::mutex::lock lock(m_mutex);
|
||||
while (!m_started)
|
||||
m_cond.wait(lock);
|
||||
}
|
||||
void started()
|
||||
{
|
||||
boost::mutex::lock lock(m_mutex);
|
||||
m_started = true;
|
||||
m_cond.notify_one();
|
||||
}
|
||||
|
||||
boost::mutex m_mutex;
|
||||
boost::condition m_cond;
|
||||
const boost::function0<void>& m_threadfunc;
|
||||
bool m_started;
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
boost::thread::thread_list* m_list;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned __stdcall thread_proxy(void* param)
|
||||
unsigned __stdcall thread_proxy(void* param)
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
void* thread_proxy(void* param)
|
||||
void* thread_proxy(void* param)
|
||||
#endif
|
||||
{
|
||||
thread_param* p = static_cast<thread_param*>(param);
|
||||
boost::function0<void> threadfunc = p->m_threadfunc;
|
||||
{
|
||||
thread_param* p = static_cast<thread_param*>(param);
|
||||
boost::function0<void> threadfunc = p->m_threadfunc;
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
p->m_list = get_list(); // create the list
|
||||
p->m_state_manager = get_list(); // create the list
|
||||
#endif
|
||||
p->started();
|
||||
threadfunc();
|
||||
return 0;
|
||||
}
|
||||
p->started();
|
||||
threadfunc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace boost
|
||||
} // unnamed namespace
|
||||
|
||||
namespace boost {
|
||||
|
||||
lock_error::lock_error() : std::runtime_error("thread lock error")
|
||||
{
|
||||
lock_error::lock_error() : std::runtime_error("thread lock error")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
thread::thread()
|
||||
{
|
||||
thread::thread()
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
HANDLE cur = GetCurrentThread();
|
||||
HANDLE real;
|
||||
DuplicateHandle(GetCurrentProcess(), cur, GetCurrentProcess(), &real, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
m_thread = reinterpret_cast<unsigned long>(real);
|
||||
m_id = GetCurrentThreadId();
|
||||
HANDLE cur = GetCurrentThread();
|
||||
HANDLE real;
|
||||
DuplicateHandle(GetCurrentProcess(), cur, GetCurrentProcess(), &real, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
m_thread = reinterpret_cast<unsigned long>(real);
|
||||
m_id = GetCurrentThreadId();
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
m_thread = pthread_self();
|
||||
m_list = get_list();
|
||||
m_list->add(this);
|
||||
m_thread = pthread_self();
|
||||
m_state_manager = get_list();
|
||||
m_state_manager->add(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
thread::thread(const boost::function0<void>& threadfunc)
|
||||
{
|
||||
thread_param param(threadfunc);
|
||||
}
|
||||
|
||||
thread::thread(const function0<void>& threadfunc)
|
||||
{
|
||||
thread_param param(threadfunc);
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
m_thread = _beginthreadex(0, 0, &thread_proxy, ¶m, 0, &m_id);
|
||||
assert(m_thread);
|
||||
m_thread = _beginthreadex(0, 0, &thread_proxy, ¶m, 0, &m_id);
|
||||
assert(m_thread);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
int res = pthread_create(&m_thread, 0, &thread_proxy, ¶m);
|
||||
assert(res == 0);
|
||||
int res = pthread_create(&m_thread, 0, &thread_proxy, ¶m);
|
||||
assert(res == 0);
|
||||
#endif
|
||||
param.wait();
|
||||
param.wait();
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
m_list = param.m_list;
|
||||
assert(m_list);
|
||||
m_list->add(this);
|
||||
m_state_manager = param.m_state_manager;
|
||||
assert(m_state_manager);
|
||||
m_state_manager->add(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
thread::~thread()
|
||||
{
|
||||
int res = 0;
|
||||
thread::~thread()
|
||||
{
|
||||
int res = 0;
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
|
||||
assert(res);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
if (m_list)
|
||||
m_list->remove(this);
|
||||
}
|
||||
|
||||
res = pthread_detach(m_thread);
|
||||
assert(res == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool thread::operator==(const thread& other)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
return other.m_id == m_id;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
return pthread_equal(m_thread, other.m_thread) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool thread::operator!=(const thread& other)
|
||||
{
|
||||
return operator!=(other);
|
||||
}
|
||||
|
||||
void thread::join()
|
||||
{
|
||||
int res;
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
mutex::lock lock(m_mutex);
|
||||
while (m_list)
|
||||
m_cond.wait(lock);
|
||||
#endif
|
||||
if (m_state_manager)
|
||||
m_state_manager->remove(this);
|
||||
}
|
||||
|
||||
bool thread::try_join()
|
||||
{
|
||||
res = pthread_detach(m_thread);
|
||||
assert(res == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool thread::operator==(const thread& other) const
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
return WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), 0) == WAIT_OBJECT_0;
|
||||
return other.m_id == m_id;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
mutex::lock lock(m_mutex);
|
||||
bool ret = (m_list == 0);
|
||||
return ret;
|
||||
return pthread_equal(m_thread, other.m_thread) != 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool thread::timed_join(const xtime& xt)
|
||||
{
|
||||
bool thread::operator!=(const thread& other) const
|
||||
{
|
||||
return operator!=(other);
|
||||
}
|
||||
|
||||
void thread::join()
|
||||
{
|
||||
int res;
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
return WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), 0) == WAIT_OBJECT_0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
mutex::lock lock(m_mutex);
|
||||
while (m_list)
|
||||
{
|
||||
if (!m_cond.timed_wait(lock, xt))
|
||||
break;
|
||||
}
|
||||
bool ret = (m_list == 0);
|
||||
return ret;
|
||||
mutex::lock lock(m_mutex);
|
||||
while (m_state_manager)
|
||||
m_condition.wait(lock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void thread::sleep(const xtime& xt)
|
||||
{
|
||||
bool thread::try_join()
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
Sleep(milliseconds);
|
||||
return WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), 0) == WAIT_OBJECT_0;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
mutex::lock lock(m_mutex);
|
||||
bool ret = (m_state_manager == 0);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool thread::timed_join(const xtime& xt)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
return WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), 0) == WAIT_OBJECT_0;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
mutex::lock lock(m_mutex);
|
||||
while (m_state_manager)
|
||||
{
|
||||
if (!m_condition.timed_wait(lock, xt))
|
||||
break;
|
||||
}
|
||||
bool ret = (m_state_manager == 0);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread::sleep(const xtime& xt)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned 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);
|
||||
int res = pthread_delay_np(&ts);
|
||||
assert(res == 0);
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
int res = pthread_delay_np(&ts);
|
||||
assert(res == 0);
|
||||
# elif defined(BOOST_HAS_NANOSLEEP)
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
nanosleep(&ts, 0);
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
nanosleep(&ts, 0);
|
||||
# else
|
||||
boost::semaphore sema;
|
||||
sema.down(xt);
|
||||
semaphore sema;
|
||||
sema.down(xt);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void thread::yield()
|
||||
{
|
||||
void thread::yield()
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
Sleep(0);
|
||||
Sleep(0);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
# if defined(BOOST_HAS_SCHED_YIELD)
|
||||
int res = sched_yield();
|
||||
assert(res == 0);
|
||||
int res = sched_yield();
|
||||
assert(res == 0);
|
||||
# elif defined(BOOST_HAS_PTHREAD_YIELD)
|
||||
int res = pthread_yield();
|
||||
assert(res == 0);
|
||||
int res = pthread_yield();
|
||||
assert(res == 0);
|
||||
# else
|
||||
xtime xt;
|
||||
xtime_get(&xt, boost::TIME_UTC);
|
||||
sleep(xt);
|
||||
xtime xt;
|
||||
xtime_get(&xt, TIME_UTC);
|
||||
sleep(xt);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
thread_group::thread_group()
|
||||
{
|
||||
}
|
||||
thread_group::thread_group()
|
||||
{
|
||||
}
|
||||
|
||||
thread_group::~thread_group()
|
||||
{
|
||||
// We shouldn't have to lock here, since referencing this object from another thread
|
||||
// while we're deleting it in the current thread is going to lead to undefined behavior
|
||||
// any way.
|
||||
for (std::list<thread*>::iterator it = m_threads.begin(); it != m_threads.end(); ++it)
|
||||
delete (*it);
|
||||
}
|
||||
thread_group::~thread_group()
|
||||
{
|
||||
// We shouldn't have to lock here, since referencing this object from another thread
|
||||
// while we're deleting it in the current thread is going to lead to undefined behavior
|
||||
// any way.
|
||||
for (std::list<thread*>::iterator it = m_threads.begin(); it != m_threads.end(); ++it)
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
thread* thread_group::create_thread(const function0<void>& threadfunc)
|
||||
{
|
||||
// No lock required here since the only "shared data" that's modified here occurs
|
||||
// inside add_thread which does lock.
|
||||
std::auto_ptr<thread> thrd(new thread(threadfunc));
|
||||
add_thread(thrd.get());
|
||||
return thrd.release();
|
||||
}
|
||||
thread* thread_group::create_thread(const function0<void>& threadfunc)
|
||||
{
|
||||
// No lock required here since the only "shared data" that's modified here occurs
|
||||
// inside add_thread which does lock.
|
||||
std::auto_ptr<thread> thrd(new thread(threadfunc));
|
||||
add_thread(thrd.get());
|
||||
return thrd.release();
|
||||
}
|
||||
|
||||
void thread_group::add_thread(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
void thread_group::add_thread(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
|
||||
// For now we'll simply ignore requests to add a thread object multiple times.
|
||||
// Should we consider this an error and either throw or return an error value?
|
||||
std::list<thread*>::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd);
|
||||
assert(it == m_threads.end());
|
||||
if (it == m_threads.end())
|
||||
m_threads.push_back(thrd);
|
||||
}
|
||||
// For now we'll simply ignore requests to add a thread object multiple times.
|
||||
// Should we consider this an error and either throw or return an error value?
|
||||
std::list<thread*>::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd);
|
||||
assert(it == m_threads.end());
|
||||
if (it == m_threads.end())
|
||||
m_threads.push_back(thrd);
|
||||
}
|
||||
|
||||
void thread_group::remove_thread(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
void thread_group::remove_thread(thread* thrd)
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
|
||||
// For now we'll simply ignore requests to remove a thread object that's not in the group.
|
||||
// Should we consider this an error and either throw or return an error value?
|
||||
std::list<thread*>::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd);
|
||||
assert(it != m_threads.end());
|
||||
if (it != m_threads.end())
|
||||
m_threads.erase(it);
|
||||
}
|
||||
// For now we'll simply ignore requests to remove a thread object that's not in the group.
|
||||
// Should we consider this an error and either throw or return an error value?
|
||||
std::list<thread*>::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd);
|
||||
assert(it != m_threads.end());
|
||||
if (it != m_threads.end())
|
||||
m_threads.erase(it);
|
||||
}
|
||||
|
||||
void thread_group::join_all()
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
for (std::list<thread*>::iterator it = m_threads.begin(); it != m_threads.end(); ++it)
|
||||
(*it)->join();
|
||||
}
|
||||
}
|
||||
void thread_group::join_all()
|
||||
{
|
||||
mutex::lock lock(m_mutex);
|
||||
for (std::list<thread*>::iterator it = m_threads.begin(); it != m_threads.end(); ++it)
|
||||
(*it)->join();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Added boost::thread initial implementation.
|
||||
// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable.
|
||||
|
||||
118
src/tss.cpp
118
src/tss.cpp
@@ -1,79 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 6 Jun 01 Initial version.
|
||||
*/
|
||||
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
namespace boost {
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
tss::tss()
|
||||
{
|
||||
_key = TlsAlloc();
|
||||
assert(_key != 0xFFFFFFFF);
|
||||
tss::tss()
|
||||
{
|
||||
m_key = TlsAlloc();
|
||||
assert(m_key != 0xFFFFFFFF);
|
||||
|
||||
if (_key == 0xFFFFFFFF)
|
||||
throw std::runtime_error("boost::tss : failure to construct");
|
||||
}
|
||||
if (m_key == 0xFFFFFFFF)
|
||||
throw std::runtime_error("boost::tss : failure to construct");
|
||||
}
|
||||
|
||||
tss::~tss()
|
||||
{
|
||||
int res = TlsFree(_key);
|
||||
assert(res);
|
||||
}
|
||||
tss::~tss()
|
||||
{
|
||||
int res = TlsFree(m_key);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void* tss::get() const
|
||||
{
|
||||
return TlsGetValue(_key);
|
||||
}
|
||||
void* tss::get() const
|
||||
{
|
||||
return TlsGetValue(m_key);
|
||||
}
|
||||
|
||||
bool tss::set(void* value)
|
||||
{
|
||||
return TlsSetValue(_key, value);
|
||||
}
|
||||
bool tss::set(void* value)
|
||||
{
|
||||
return TlsSetValue(m_key, value);
|
||||
}
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
tss::tss()
|
||||
{
|
||||
int res = pthread_key_create(&_key, 0);
|
||||
assert(res == 0);
|
||||
tss::tss()
|
||||
{
|
||||
int res = pthread_key_create(&m_key, 0);
|
||||
assert(res == 0);
|
||||
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::tss : failure to construct");
|
||||
}
|
||||
if (res != 0)
|
||||
throw std::runtime_error("boost::tss : failure to construct");
|
||||
}
|
||||
|
||||
tss::~tss()
|
||||
{
|
||||
int res = pthread_key_delete(_key);
|
||||
assert(res == 0);
|
||||
}
|
||||
tss::~tss()
|
||||
{
|
||||
int res = pthread_key_delete(m_key);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void* tss::get() const
|
||||
{
|
||||
return pthread_getspecific(_key);
|
||||
}
|
||||
void* tss::get() const
|
||||
{
|
||||
return pthread_getspecific(m_key);
|
||||
}
|
||||
|
||||
bool tss::set(void* value)
|
||||
{
|
||||
return pthread_setspecific(_key, value) == 0;
|
||||
}
|
||||
bool tss::set(void* value)
|
||||
{
|
||||
return pthread_setspecific(m_key, value) == 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 6 Jun 01 WEKEMPF Initial version.
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2001
|
||||
* William E. Kempf
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. William E. Kempf makes no representations
|
||||
* about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
*/
|
||||
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/config.hpp>
|
||||
|
||||
@@ -22,34 +17,39 @@
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
int xtime_get(struct xtime* xtp, int clock_type)
|
||||
|
||||
int xtime_get(struct xtime* xtp, int clock_type)
|
||||
{
|
||||
if (clock_type == TIME_UTC)
|
||||
{
|
||||
if (clock_type == TIME_UTC)
|
||||
{
|
||||
#if defined(BOOST_HAS_FTIME)
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
const __int64 TIMESPEC_TO_FILETIME_OFFSET = ((__int64)27111902 << 32) + (__int64)3577643008;
|
||||
xtp->sec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
|
||||
xtp->nsec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET -
|
||||
((__int64)xtp->sec * (__int64)10000000)) * 100);
|
||||
return clock_type;
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
const __int64 TIMESPEC_TO_FILETIME_OFFSET = ((__int64)27111902 << 32) + (__int64)3577643008;
|
||||
xtp->sec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
|
||||
xtp->nsec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET -
|
||||
((__int64)xtp->sec * (__int64)10000000)) * 100);
|
||||
return clock_type;
|
||||
#elif defined(BOOST_HAS_GETTIMEOFDAY)
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
xtp->sec = tv.tv_sec;
|
||||
xtp->nsec = tv.tv_usec * 1000;
|
||||
return clock_type;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
xtp->sec = tv.tv_sec;
|
||||
xtp->nsec = tv.tv_usec * 1000;
|
||||
return clock_type;
|
||||
#elif defined(BOOST_HAS_CLOCK_GETTIME)
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
xtp->sec = ts.tv_sec;
|
||||
xtp->nsec = ts.tv_nsec;
|
||||
return clock_type;
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
xtp->sec = ts.tv_sec;
|
||||
xtp->nsec = ts.tv_nsec;
|
||||
return clock_type;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//#include <boost/thread/atomic.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
Reference in New Issue
Block a user