📄 thread.h
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.// // This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by// the GNU General Public License. //// This exception applies only to the code released under the name GNU// Common C++. If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.///** * @file thread.h * @short Synchronization and threading services. **/#ifndef CCXX_THREAD_H_#define CCXX_THREAD_H_#include <cc++/config.h>#ifndef WIN32#define CCXX_POSIX#endif // !WIN32#include <ctime>#ifndef WIN32#include <pthread.h>#endif // !WIN32#undef CCXX_USE_WIN32_ATOMIC#ifndef WIN32#include <time.h>#include <signal.h>#include <unistd.h>#ifdef _THR_UNIXWARE#undef PTHREAD_MUTEXTYPE_RECURSIVE#endiftypedef pthread_t cctid_t;typedef unsigned long timeout_t;/*#if defined(__CYGWIN32__)__declspec(dllimport) long __stdcall InterlockedIncrement(long *);__declspec(dllimport) long __stdcall InterlockedDecrement(long *);__declspec(dllimport) long __stdcall InterlockedExchange(long *, long);#define CCXX_USE_WIN32_ATOMIC 1#endif*/#else // WIN32typedef DWORD cctid_t;typedef DWORD timeout_t;#define MAX_SEM_VALUE 1000000#define CCXX_USE_WIN32_ATOMIC 1#endif // !WIN32#ifdef HAVE_GCC_CXX_BITS_ATOMIC#include <ios>#endif#ifdef CCXX_NAMESPACESnamespace ost {#ifdef __BORLANDC__# if __BORLANDC__ >= 0x0560using std::time_t;using std::tm;# endif#endif#endif#ifdef HAVE_GCC_CXX_BITS_ATOMICusing namespace __gnu_cxx;#endifclass __EXPORT Thread;class __EXPORT ThreadKey;#define TIMEOUT_INF ~((timeout_t) 0)#define ENTER_CRITICAL enterMutex();#define LEAVE_CRITICAL leaveMutex();#define ENTER_DEFERRED setCancel(cancelDeferred);#define LEAVE_DEFERRED setCancel(cancelImmediate);#ifndef WIN32// These macros override common functions with thread-safe versions. In// particular the common "libc" sleep() has problems since it normally// uses SIGARLM (as actually defined by "posix"). The pthread_delay and// usleep found in libpthread are gaurenteed not to use SIGALRM and offer// higher resolution. psleep() is defined to call the old process sleep.#undef sleep#define psleep(x) (sleep)(x)#ifdef signal#undef signal#endif#endif // !WIN32#undef Yieldclass __EXPORT Conditional;class __EXPORT Event;/** * The Mutex class is used to protect a section of code so that at any * given time only a single thread can perform the protected operation. * * The Mutex can be used as a base class to protect access in a derived * class. When used in this manner, the ENTER_CRITICAL and LEAVE_CRITICAL * macros can be used to specify when code written for the derived class * needs to be protected by the default Mutex of the derived class, and * hence is presumed to be 'thread safe' from multiple instance execution. * One of the most basic Common C++ synchronization object is the Mutex * class. A Mutex only allows one thread to continue execution at a given * time over a specific section of code. Mutex's have a enter and leave * method; only one thread can continue from the Enter until the Leave is * called. The next thread waiting can then get through. Mutex's are also * known as "CRITICAL SECTIONS" in win32-speak. * * The Mutex is always recursive in that if the same thread invokes * the same mutex lock multiple times, it must release it multiple times. * This allows a function to call another function which also happens to * use the same mutex lock when called directly. This was * deemed essential because a mutex might be used to block individual file * requests in say, a database, but the same mutex might be needed to block a * whole series of database updates that compose a "transaction" for one * thread to complete together without having to write alternate non-locking * member functions to invoke for each part of a transaction. * * Strangely enough, the original pthread draft standard does not directly * support recursive mutexes. In fact this is the most common "NP" extension * for most pthread implementations. Common C++ emulates recursive mutex * behavior when the target platform does not directly support it. * * In addition to the Mutex, Common C++ supports a rwlock class. This * implements the X/Open recommended "rwlock". On systems which do not * support rwlock's, the behavior is emulated with a Mutex; however, the * advantage of a rwlock over a mutex is then entirely lost. There has been * some suggested clever hacks for "emulating" the behavior of a rwlock with * a pair of mutexes and a semaphore, and one of these will be adapted for * Common C++ in the future for platforms that do not support rwlock's * directly. * * @author David Sugar <dyfet@ostel.com> * @short Mutex lock for protected access. */class __EXPORT Mutex{private: static bool _debug; const char *_name;#ifndef WIN32#ifndef PTHREAD_MUTEXTYPE_RECURSIVE int volatile _level; Thread *volatile _tid;#endif /* * Pthread mutex object. This is protected rather than private * because some mixed mode pthread operations require a mutex as * well as their primary pthread object. A good example of this * is the Event class, as waiting on a conditional object must be * associated with an accessable mutex. An alternative would be * to make such classes "friend" classes of the Mutex. */ pthread_mutex_t _mutex;#else // WIN32# if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)# error "Can't determine underground for Mutex"# endif#ifdef MUTEX_UNDERGROUND_WIN32_MUTEX HANDLE _mutex;#endif#ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION CRITICAL_SECTION _criticalSection;#endif#endif // WIN32public: /** * The mutex is always initialized as a recursive entity. * * @param name of mutex for optional deadlock detection */ Mutex(const char *name = NULL); /** * Destroying the mutex removes any system resources associated * with it. If a mutex lock is currently in place, it is presumed * to terminate when the Mutex is destroyed. */ virtual ~Mutex(); /** * Enable or disable deadlock debugging. * * @param mode debug mode. */ static void setDebug(bool mode) {_debug = mode;}; /** * Enable setting of mutex name for deadlock debug. * * @param name for mutex. */ inline void nameMutex(const char *name) {_name = name;}; /** * Entering a Mutex locks the mutex for the current thread. This * also can be done using the ENTER_CRITICAL macro or by using the * ++ operator on a mutex. * * @see #leaveMutex */ void enterMutex(void); /** * Future abi will use enter/leave/test members. */ inline void enter(void) {enterMutex();}; /** * Future abi will use enter/leave/test members. */ inline void leave(void) {leaveMutex();}; /** * Future abi will use enter/leave/test members. * * @return true if entered. */ inline bool test(void) {return tryEnterMutex();}; /** * Tries to lock the mutex for the current thread. Behaves like * #enterMutex , except that it doesn't block the calling thread * if the mutex is already locked by another thread. * * @return true if locking the mutex was succesful otherwise false * * @see enterMutex * @see leaveMutex */ bool tryEnterMutex(void); /** * Leaving a mutex frees that mutex for use by another thread. If * the mutex has been entered (invoked) multiple times (recursivily) * by the same thread, then it will need to be exited the same number * of instances before it is free for re-use. This operation can * also be done using the LEAVE_CRITICAL macro or by the -- operator * on a mutex. * * @see #enterMutex */ void leaveMutex(void);};/** * The MutexLock class is used to protect a section of code so that at any * given time only a single thread can perform the protected operation. * * It use Mutex to protect operation. Using this class is usefull and * exception safe. The mutex that has been locked is automatically * released when the function call stack falls out of scope, so one doesnt * have to remember to unlock the mutex at each function return. * * A common use is * * void func_to_protect() * { * MutexLock lock(mutex); * ... operation ... * } * * NOTE: do not declare variable as "MutexLock (mutex)", the mutex will be * released at statement end. * * @author Frediano Ziglio <freddy77@angelfire.com> * @short Mutex automatic locker for protected access. */class __EXPORT MutexLock{private: Mutex& mutex;public: /** * Acquire the mutex * * @param _mutex reference to mutex to aquire. */ MutexLock( Mutex& _mutex ) : mutex( _mutex ) { mutex.enterMutex(); } /** * Release the mutex automatically */ // this should be not-virtual ~MutexLock() { mutex.leaveMutex(); }};/** * The ThreadLock class impliments a thread rwlock for optimal reader performance * on systems which have rwlock support, and reverts to a simple mutex for those * that do not. * * @author David Sugar <dyfet@ostel.com> * @short Posix rwlock extension for protected access. */class __EXPORT ThreadLock{private:#ifdef HAVE_PTHREAD_RWLOCK pthread_rwlock_t _lock;#else Mutex mutex;#endifpublic: /** * Create a process shared thread lock object. */ ThreadLock(); /** * Destroy a process shared thread lock object. */ virtual ~ThreadLock(); /** * Aquire a read lock for the current object. */ void readLock(void); /** * Aquire a write lock for the current object. */ void writeLock(void); /** * Attempt read lock for current object. * * @return true on success. */ bool tryReadLock(void); /** * Attempt write lock for current object. * * @return true on success. */ bool tryWriteLock(void); /** * Release any held locks. */ void unlock(void);};/** * The ReadLock class is used to protect a section of code through * a ThreadLock for "read" access to the member function. The * ThreadLock is automatically released when the object falls out of * scope. * * A common use is * * void func_to_protect() * { * ReadLock lock(threadlock); * ... operation ... * } * * NOTE: do not declare variable as "ReadLock (threadlock)", the * mutex will be released at statement end. * * @author David Sugar <dyfet@gnu.org> * @short Read mode automatic locker for protected access. */class __EXPORT ReadLock{private: ThreadLock& tl;public: /** * Wait for read access * * @param _tl reference to lock to aquire. */ ReadLock( ThreadLock& _tl ) : tl( _tl ) { tl.readLock(); } /** * Post the semaphore automatically */ // this should be not-virtual ~ReadLock() { tl.unlock(); }};/** * The WriteLock class is used to protect a section of code through * a ThreadLock for "write" access to the member function. The * ThreadLock is automatically released when the object falls out of * scope. * * A common use is * * void func_to_protect() * { * WriteLock lock(threadlock); * ... operation ... * } * * NOTE: do not declare variable as "WriteLock (threadlock)", the * mutex will be released at statement end. * * @author David Sugar <dyfet@gnu.org> * @short Read mode automatic locker for protected access. */class __EXPORT WriteLock{private: ThreadLock& tl;public: /** * Wait for write access * * @param _tl reference to threadlock to aquire. */ WriteLock( ThreadLock& _tl ) : tl( _tl ) { tl.writeLock(); } /** * Post the semaphore automatically */ // this should be not-virtual ~WriteLock() { tl.unlock(); }};/** * The Mutex Counter is a counter variable which can safely be incremented * or decremented by multiple threads. A Mutex is used to protect access * to the counter variable (an integer). An initial value can be specified * for the counter, and it can be manipulated with the ++ and -- operators.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -