⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.h

📁 common c++提供socket
💻 H
📖 第 1 页 / 共 4 页
字号:
 *  * @author David Sugar <dyfet@ostel.com> * @short Thread protected integer counter. */class __EXPORT MutexCounter : public Mutex{private:	volatile int	counter;public:	/**	 * Create and optionally name a mutex protected counter.	 *	 * @param id name for mutex counter, optional for deadlock testing.	 */	MutexCounter(const char *id = NULL);	/**	 * Create and optionally name a mutex protected counter with	 * an initial value.	 *	 * @param initial value of counter.	 * @param id name of counter, optional for deadlock testing.	 */	MutexCounter(int initial, const char *id = NULL);	friend __EXPORT int operator++(MutexCounter &mc);	friend __EXPORT int operator--(MutexCounter &mc);};/** * The AtomicCounter class offers thread-safe manipulation of an integer * counter.  These are commonly used for building thread-safe "reference" * counters for C++ classes.  The AtomicCounter depends on the platforms * support for "atomic" integer operations, and can alternately substitute * a "mutex" if no atomic support exists. * * @author Sean Cavanaugh <sean@dimensionalrift.com> * @short atomic counter operation. */class __EXPORT AtomicCounter{#ifndef CCXX_USE_WIN32_ATOMICprivate:#if	defined(HAVE_ATOMIC_AIX)	volatile int counter;#elif   defined(HAVE_GCC_BITS_ATOMIC)	volatile _Atomic_word counter;#elif   defined(HAVE_GCC_CXX_BITS_ATOMIC)	volatile _Atomic_word counter;//	__gnu_cxx::_Atomic_word counter;#elif	defined(HAVE_ATOMIC)	atomic_t atomic;#else	volatile int counter;	pthread_mutex_t _mutex;#endifpublic:	/**	 * Initialize an atomic counter to 0.	 */	AtomicCounter();	/**	 * Initialize an atomic counter to a known value.	 *	 * @param value initial value.	 */	AtomicCounter(int value);	~AtomicCounter();	int operator++(void);	int operator--(void);	int operator+=(int change);	int operator-=(int change);	int operator+(int change);	int operator-(int change);	int operator=(int value);	bool operator!(void);	operator int();#elseprivate:	long atomic;public:	inline AtomicCounter()		{atomic = 0;};	inline AtomicCounter(int value)		{atomic = value;};	inline int operator++(void)		{return InterlockedIncrement(&atomic);};	inline int operator--(void)		{return InterlockedDecrement(&atomic);};	int operator+=(int change);	int operator-=(int change);	inline int operator+(int change)		{return atomic + change;};	inline int operator-(int change)		{return atomic - change;};		inline int operator=(int value)		{return InterlockedExchange(&atomic, value);};	inline bool operator!(void)		{return (atomic == 0) ? true : false;};	inline operator int()		{return atomic;};#endif};#ifndef WIN32/** * A conditional variable synchcronization object for one to one and * one to many signal and control events between processes. * Conditional variables may wait for and receive signals to notify * when to resume or perform operations.  Multiple waiting threads may * be woken with a broadcast signal. * * @warning While this class inherits from Mutex, the methods of the * class Conditional just handle the system conditional variable, so * the user is responsible for calling enterMutex and leaveMutex so as * to avoid race conditions. Another thing to note is that if you have * several threads waiting on one condition, not uncommon in thread * pools, each thread must take care to manually unlock the mutex if * cancellation occurs. Otherwise the first thread cancelled will * deadlock the rest of the thread. * * @author David Sugar * @short conditional. * @todo implement in win32 */class __EXPORT Conditional {private:	pthread_cond_t _cond;	pthread_mutex_t _mutex;public:	/**	 * Create an instance of a conditional.	 *	 * @param id name of conditional, optional for deadlock testing.	 */	Conditional(const char *id = NULL);	/**	 * Destroy the conditional.	 */	virtual ~Conditional();	/**	 * Signal a conditional object and a waiting threads.	 *	 * @param broadcast this signal to all waiting threads if true.	 */	void signal(bool broadcast);	/** 	 * Wait to be signaled from another thread.	 *	 * @param timer time period to wait.	 * @param locked flag if already locked the mutex.	 */	bool wait(timeout_t timer = 0, bool locked = false);        /**         * Locks the conditional's mutex for this thread.  Remember	 * that Conditional's mutex is NOT a recursive mutex!         *         * @see #leaveMutex         */        void enterMutex(void);	/**	 * In the future we will use lock in place of enterMutex since	 * the conditional composite is not a recursive mutex, and hence	 * using enterMutex may cause confusion in expectation with the	 * behavior of the Mutex class.	 *	 * @see #enterMutex	 */	inline void lock(void)		{enterMutex();};        /**         * Tries to lock the conditional for the current thread. 	 * Behaves like #enterMutex , except that it doesn't block the 	 * calling thread.         *         * @return true if locking the mutex was succesful otherwise false         *         * @see enterMutex         * @see leaveMutex         */        bool tryEnterMutex(void);	inline bool test(void)		{return tryEnterMutex();};        /**         * Leaving a mutex frees that mutex for use by another thread.  	 *         * @see #enterMutex         */        void leaveMutex(void);	inline void unlock(void)		{return leaveMutex();};};#endif/** * A semaphore is generally used as a synchronization object between multiple * threads or to protect a limited and finite resource such as a memory or * thread pool.  The semaphore has a counter which only permits access by * one or more threads when the value of the semaphore is non-zero.  Each * access reduces the current value of the semaphore by 1.  One or more * threads can wait on a semaphore until it is no longer 0, and hence the * semaphore can be used as a simple thread synchronization object to enable * one thread to pause others until the thread is ready or has provided data * for them.  Semaphores are typically used as a * counter for protecting or limiting concurrent access to a given * resource, such as to permitting at most "x" number of threads to use * resource "y", for example. * * @author David Sugar <dyfet@ostel.com> * @short Semaphore counter for thread synchronization. */class __EXPORT Semaphore{private:#ifndef WIN32	unsigned _count, _waiters;	pthread_mutex_t _mutex;	pthread_cond_t _cond;#else	HANDLE	semObject;#endif // !WIN32public:	/**	 * The initial value of the semaphore can be specified.  An initial	 * value is often used When used to lock a finite resource or to	 * specify the maximum number of thread instances that can access a	 * specified resource.	 *	 * @param resource specify initial resource count or 0 default.	 */	Semaphore(unsigned resource = 0);	/**	 * Destroying a semaphore also removes any system resources	 * associated with it.  If a semaphore has threads currently waiting	 * on it, those threads will all continue when a semaphore is	 * destroyed.	 */	virtual ~Semaphore();	/**	 * Wait is used to keep a thread held until the semaphore counter	 * is greater than 0.  If the current thread is held, then another	 * thread must increment the semaphore.  Once the thread is accepted, 	 * the semaphore is automatically decremented, and the thread 	 * continues execution.	 * 	 * The pthread semaphore object does not support a timed "wait", and	 * hence to maintain consistancy, neither the posix nor win32 source	 * trees support "timed" semaphore objects.	 * 	 * @return false if timed out	 * @param timeout period in milliseconds to wait	 * @see #post	 */	bool wait(timeout_t timeout = 0);	/**	 * Posting to a semaphore increments its current value and releases	 * the first thread waiting for the semaphore if it is currently at	 * 0.  Interestingly, there is no support to increment a semaphore by	 * any value greater than 1 to release multiple waiting threads in	 * either pthread or the win32 API.  Hence, if one wants to release	 * a semaphore to enable multiple threads to execute, one must perform	 * multiple post operations.	 * 	 * @see #wait	 */	void post(void);	// FIXME: how implement getValue for posix compatibility ?	// not portable...#if	0	/**	 * Get the current value of a semaphore.	 *	 * @return current value.	 */	int getValue(void);#endif};/** * The SemaphoreLock class is used to protect a section of code through * a semaphore so that only x instances of the member function may * execute concurrently. *  * A common use is *  * void func_to_protect() * { *   SemaphoreLock lock(semaphore); *   ... operation ... * } * * NOTE: do not declare variable as "SemaohoreLock (semaphore)", the  * mutex will be released at statement end. *  * @author David Sugar <dyfet@gnu.org> * @short Semaphore automatic locker for protected access. */class __EXPORT SemaphoreLock{private:	Semaphore& sem;public:	/**	 * Wait for the semaphore	 */	SemaphoreLock( Semaphore& _sem ) : sem( _sem ) 		{ sem.wait(); }	/**	 * Post the semaphore automatically	 */	// this should be not-virtual	~SemaphoreLock()		{ sem.post(); }};/** * The Event class implements a feature originally found in the WIN32 API; * event notification.  A target thread waits on a resetable Event, and one * or more other threads can then signal the waiting thread to resume  * execution.  A timeout can be used to specify a wait duration in  * milliseconds.  The Event class must be reset before it can be used again  * as a trigger.  These event objects * use a trigger/reset mechanism and are related to low level conditional * variables. *  * @author: David Sugar <dyfet@ostel.com> * @short Thread synchornization on event notification. */class __EXPORT Event{private:#ifndef WIN32	pthread_mutex_t _mutex;	pthread_cond_t _cond;	bool _signaled;	int _count;#else	HANDLE cond;#endifpublic:	Event();	virtual ~Event();	/**	 * Once signaled, the Event class must be "reset" before responding	 * to a new signal.	 * 	 * @see #signal	 */	void reset(void);	/**	 * Signal the event for the waiting thread.	 */	void signal(void);	/**	 * Wait either for the event to be signaled by another thread or	 * for the specified timeout duration.	 * 	 * @see #signal	 * @return true if signaled, false if timed out.	 * @param timer timeout in milliseconds to wait for a signal.	 */	bool wait(timeout_t timer);	bool wait(void);};/** * Every thread of execution in an application is created by * instantiating an object of a class derived from the Thread * class. Classes derived from Thread must implement the run() method, * which specifies the code of the thread. The base Thread class * supports encapsulation of the generic threading methods implemented * on various target operating systems.  This includes the ability to * start and stop threads in a synchronized and controllable manner, * the ability to specify thread execution priority, and thread * specific "system call" wrappers, such as for sleep and yield.  A * thread exception is thrown if the thread cannot be created. * Threading was the first part of Common C++ I wrote, back when it * was still the APE library.  My goal for Common C++ threading has * been to make threading as natural and easy to use in C++ * application development as threading is in Java.  With this said, * one does not need to use threading at all to take advantage of * Common C++.  However, all Common C++ classes are designed at least * to be thread-aware/thread-safe as appropriate and necessary. *  * Common C++ threading is currently built either from the Posix "pthread" * library or using the win32 SDK.  In that the Posix "pthread" draft * has gone through many revisions, and many system implementations are * only marginally compliant, and even then usually in different ways, I * wrote a large series of autoconf macros found in ost_pthread.m4 which * handle the task of identifying which pthread features and capabilities * your target platform supports.  In the process I learned much about what * autoconf can and cannot do for you.. *  * Currently the GNU Portable Thread library (GNU pth) is not directly * supported in Common C++.  While GNU "Pth" doesn't offer direct * native threading support or benefit from SMP hardware, many of the design * advantages of threading can be gained from it's use, and the  Pth pthread * "emulation" library should be usable with Common C++.  In the future, * Common C++ will directly support Pth, as well as OS/2 and BeOS native * threading API's. *  * Common C++ itself defines a fairly "neutral" threading model that is * not tied to any specific API such as pthread, win32, etc.  This neutral * thread model is contained in a series of classes which handle threading * and synchronization and which may be used together to build reliable * threaded applications. *  * Common C++ defines application specific threads as objects which are * derived from the Common C++ "Thread" base class.  At minimum the "Run" * method must be implemented, and this method essentially is the "thread", * for it is executed within the execution context of the thread, and when * the Run method terminates the thread is assumed to have terminated. *  * Common C++ allows one to specify the running priority of a newly created * thread relative to the "parent" thread which is the thread that is * executing when the constructor is called.  Since most newer C++ * implementations do not allow one to call virtual constructors or virtual * methods from constructors, the thread must be "started" after the * constructor returns.  This is done either by defining a "starting" * semaphore object that one or more newly created thread objects can wait * upon, or by invoking an explicit "start" member function. *  * Threads can be "suspended" and "resumed".  As this behavior is not defined * in the Posix "pthread" specification, it is often emulated through * signals.  Typically SIGUSR1 will be used for this purpose in Common C++ * applications, depending in the target platform.  On Linux, since threads * are indeed processes, SIGSTP and SIGCONT can be used.  On solaris, the * Solaris thread library supports suspend and resume directly. *  * Threads can be canceled.  Not all platforms support the concept of * externally cancelable threads.  On those platforms and API * implementations that do not, threads are typically canceled through the * action of a signal handler. *  * As noted earlier, threads are considered running until the "Run" method * returns, or until a cancellation request is made.  Common C++ threads can * control how they respond to cancellation, using setCancellation(). * Cancellation requests can be ignored, set to occur only when a * cancellation "point" has been reached in the code, or occur immediately. * Threads can also exit by returning from Run() or by invoking the Exit() * method. *  * Generally it is a good practice to initialize any resources the thread may * require within the constructor of your derived thread class, and to purge * or restore any allocated resources in the destructor.  In most cases, the * destructor will be executed after the thread has terminated, and hence * will execute within the context of the thread that requested a join rather * than in the context of the thread that is being terminated.  Most * destructors in derived thread classes should first call Terminate() to

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -