From: <sv...@ww...> - 2004-06-23 06:24:31
|
Author: mkrose Date: 2004-06-22 23:24:22 -0700 (Tue, 22 Jun 2004) New Revision: 1062 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Thread.h trunk/CSP/SimData/Include/SimData/ThreadBase.h Log: Added a ScopedUnlock (trivial reversal of ScopedLock) Cleaned doxygen comments for some thread classes. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1062 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-21 07:23:32 UTC (rev 1061) +++ trunk/CSP/SimData/CHANGES.current 2004-06-23 06:24:22 UTC (rev 1062) @@ -1,6 +1,11 @@ Version 0.4.0 (in progress) =========================== +2004-06-22: onsight + * Added a ScopedUnlock (trivial reversal of ScopedLock) + + * Cleaned doxygen comments for some thread classes. + 2004-06-20: onsight * Doxygen and copyright notice updates. Modified: trunk/CSP/SimData/Include/SimData/Thread.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Thread.h 2004-06-21 07:23:32 UTC (rev 1061) +++ trunk/CSP/SimData/Include/SimData/Thread.h 2004-06-23 06:24:22 UTC (rev 1062) @@ -40,6 +40,11 @@ NAMESPACE_SIMDATA +/** + * @namespace thread + * + * @brief Global functions for manipulating threads. + */ namespace thread { @@ -78,7 +83,7 @@ } /** Terminate the current thread if there are any pending cancellation - * requests. @see cancel(). + * requests. @see Thread::cancel(). */ static void testCancel() { pthread_testcancel(); @@ -92,7 +97,7 @@ ThreadException::check(result); } - /* Set the cancellation type to be deferred. Cancellation requests will be + /** Set the cancellation type to be deferred. Cancellation requests will be * deferred until a cancellation checkpoint is reached (e.g a blocking wait * or an explicit call to testCancel()). */ @@ -217,10 +222,10 @@ }; -/** Object oriented wrapper for a Posix thread. +/** Base class for wrapping a Posix thread. * - * To create a thread, subclass Thread and implement the run() method. - * Then instantiate the class and call start(). + * This class is not used directly. To create a thread, subclass Task and + * implement the run() method. @see Thread for details. */ class BaseThread: public NonCopyable { @@ -334,6 +339,39 @@ }; +/** Class for starting and manipulating a posix thread. + * + * To create a new thread, subclass Task and implement the run() method. + * Then instantiate Thread<YourTaskSubclass>, and call the start() method. + * + * For example: + * @code + * // implement a task to run in a separate thread; this is just a + * // silly example. + * class MyTask: public simdata::Task { + * protected: + * // the task action; the thread running this task will terminate when + * // when run() returns. + * virtual void run() { + * for (int i = 0; i < 1000; i++) std::cout << "hello " << i << "\n"; + * } + * }; + * + * void start_a_couple_tasks() { + * // construct a couple threads to execute MyTask + * simdata::Thread<MyTask> task1("hello writer 1"); + * simdata::Thread<MyTask> task2("hello writer 2"); + * + * // start both tasks + * task1.start(); + * task2.start(); + * + * // wait for both tasks to finish + * task1.join() + * task2.join() + * } + * @endcode + */ template <class TASK> class Thread: public BaseThread { Modified: trunk/CSP/SimData/Include/SimData/ThreadBase.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-21 07:23:32 UTC (rev 1061) +++ trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 06:24:22 UTC (rev 1062) @@ -109,15 +109,17 @@ friend class ThreadCondition; public: /** Mutex types: - * DEFAULT : same as NORMAL - * NORMAL : non-reentrant; attempts to relock by a single thread, - * or to lock a mutex held by another thread that terminated - * will cause a deadlock. - * RECURSIVE : reentrant; can be relocked by a thread without causing - * a deadlock. The mutex will be held until it has been - * unlocked as many times as it was locked. - * ERRORCHECK : like NORMAL; but returns an error in situations that would - * normally result in a deadlock. + * <dl> + * <dt>DEFAULT <dd>same as NORMAL + * <dt>NORMAL <dd>non-reentrant; attempts to relock by a single thread, + * or to lock a mutex held by another thread that terminated + * will cause a deadlock. + * <dt>RECURSIVE <dd>reentrant; can be relocked by a thread without causing + * a deadlock. The mutex will be held until it has been + * unlocked as many times as it was locked. + * <dt>ERRORCHECK <dd>like NORMAL; but returns an error in situations that would + * normally result in a deadlock. + * </dl> */ typedef enum { DEFAULT, NORMAL, RECURSIVE, ERRORCHECK } MutexType; @@ -158,8 +160,8 @@ * * This method will block if another thread holds the mutex lock. * If the current thread has already locked the mutex, the behavior - * depends on the type of mutex specified during construction (@see - * MutexType). + * depends on the type of mutex specified during construction (see + * ThreadMutex::MutexType). */ void lock() { const int result = pthread_mutex_lock(&m_mutex); @@ -445,6 +447,31 @@ }; +/** Similar to ScopedLock, but unlocks the mutex for the duration of + * its existence, then relocks the mutex on destruction. + */ +template <class LOCK> +class ScopedUnlock { +public: + /** Construct a new scoped lock for a existing lockable instance. If constructed + * an the stack, this will immediately lock the instance for the duration of the + * current scope. + */ + ScopedUnlock(LOCK &lock): m_lock(lock) { + m_lock.unlock(); + } + + /** Release the underlying lock. + */ + ~ScopedLock() { + m_lock.lock(); + } + +private: + LOCK &m_lock; +}; + + /** Wrapper for allocating a global resource such that each thread receives * a separate, private instance. Thread specific instances do not require * any locking, since each thread has its own copy. |