convert line ends
[canaan.git] / prj / tech / libsrc / lg / thrdtool.h
blob3dc4e022b5e4e229278d83d07b94a0b32db38467
1 ///////////////////////////////////////////////////////////////////////////////
2 // $Source: x:/prj/tech/libsrc/lg/RCS/thrdtool.h $
3 // $Author: TOML $
4 // $Date: 1997/01/07 13:05:41 $
5 // $Revision: 1.11 $
6 //
7 // Tools for thread synchronization and management.
8 //
9 //
11 #ifndef __THRDTOOL_H
12 #define __THRDTOOL_H
14 #ifdef _WIN32
16 #if defined(DEBUG) || defined(ONEOPT)
17 #define THRDTOOL_DEBUG
18 #endif
20 ///////////////////////////////////////////////////////////////////////////////
22 // CLASS: cThreadLock
24 // Wrapper for critical sections management
27 class cThreadLock
29 public:
30 cThreadLock();
31 ~cThreadLock();
34 // Get/wait for ownership of the critical section
36 void Lock();
39 // Release ownership of the critical section
41 void Unlock();
44 // To make deadlocks easier to track it is useful to insert in
45 // the code an assertion that says whether we own a critical
46 // section or not.
48 BOOL AssertOwnedByCurrentThread();
51 // In addition we provide a routine that allows usage of specific
52 // critical sections to be traced. This is NOT on by default.
54 void SetTrace(BOOL);
57 private:
58 // make copy constructor and assignment operator inaccessible
59 cThreadLock(const cThreadLock &refCritSec);
60 cThreadLock &operator=(const cThreadLock &refCritSec);
62 CRITICAL_SECTION m_CritSec;
64 #ifdef THRDTOOL_DEBUG
65 DWORD m_currentOwnerID;
66 DWORD m_lockCount;
67 BOOL m_fTrace; // Trace this one
68 #endif
72 ///////////////////////////////////////////////////////////////////////////////
74 // CLASS: cAutoLock
76 // Locks a critical section, and unlocks it automatically
77 // when the lock goes out of scope
80 class cAutoLock
82 public:
83 cAutoLock(cThreadLock & lock);
84 ~cAutoLock();
86 private:
87 cThreadLock & m_lock;
89 // make copy constructor and assignment operator inaccessible
90 cAutoLock(const cAutoLock &);
91 cAutoLock &operator=(const cAutoLock &);
95 ///////////////////////////////////////////////////////////////////////////////
97 // CLASS: cThreadSyncObject
99 // Base class for event, semaphore and mutex objects.
101 // @TBD (toml 08-19-96): named objects? ability to "attach" an existing object?
104 class cThreadSyncObject
106 public:
107 ~cThreadSyncObject();
110 // Query if object is useful
112 BOOL operator!() const;
115 // Access handle
117 operator HANDLE ();
120 // Wait for a signal from the object
122 BOOL Wait(DWORD dwTimeout = INFINITE);
124 protected:
125 cThreadSyncObject();
126 #ifdef THRDTOOL_DEBUG
127 void AssertUseable();
128 #endif
130 HANDLE m_hSyncObject;
132 private:
133 // make copy constructor and assignment operator inaccessible
134 cThreadSyncObject(const cThreadSyncObject &);
135 cThreadSyncObject &operator=(const cThreadSyncObject &);
139 ///////////////////////////////////////////////////////////////////////////////
141 // CLASS: cThreadEvent
143 // Wrapper for unnamed event objects
146 class cThreadEvent : public cThreadSyncObject
148 public:
149 cThreadEvent(BOOL fManualReset = FALSE);
152 // Set the state to signaled
154 BOOL Set();
158 // Set the state to nonsignaled
160 BOOL Reset();
163 // A single operation that sets (to signaled) the state of
164 // the object and then resets it (to nonsignaled) after
165 // releasing the appropriate number of waiting threads.
167 BOOL Pulse();
170 // Check if the event is signaled
172 BOOL Check();
174 private:
175 // make copy constructor and assignment operator inaccessible
176 cThreadEvent(const cThreadEvent &);
177 cThreadEvent &operator=(const cThreadEvent &);
181 ///////////////////////////////////////////////////////////////////////////////
183 // CLASS: cThreadSemaphore
186 class cThreadSemaphore : public cThreadSyncObject
188 public:
189 cThreadSemaphore(long initialValue, long maxValue);
192 // Increases the count of the semaphore object by a specified
193 // amount. Wait() decreases the count by one on return.
195 BOOL Release(long releaseCount = 1, long * pPreviousCount = NULL);
197 private:
198 // make copy constructor and assignment operator inaccessible
199 cThreadSemaphore(const cThreadSemaphore &);
200 cThreadSemaphore &operator=(const cThreadSemaphore &);
204 ///////////////////////////////////////////////////////////////////////////////
206 // CLASS: cThreadMutex
209 class cThreadMutex : public cThreadSyncObject
211 public:
212 cThreadMutex(BOOL fEstablishInitialOwnership = FALSE);
215 // Release ownership of the mutex
217 BOOL Release();
219 private:
220 // make copy constructor and assignment operator inaccessible
221 cThreadMutex(const cThreadMutex &);
222 cThreadMutex &operator=(const cThreadMutex &);
225 ///////////////////////////////////////////////////////////////////////////////
227 // CLASS: cWorkerThread
229 // Support for a worker thread
231 // Simple thread class supports creation of worker thread, synchronization
232 // and simpler communication. Must derived to use.
235 class cWorkerThread
237 public:
238 cWorkerThread();
239 virtual ~cWorkerThread();
241 ///////////////////////////////////
243 // Functions for the master thread
247 // Start thread running - error if already running
249 BOOL Create();
252 // Accessor thread calls this when done with thread (having told thread
253 // to exit)
255 void WaitForClose(DWORD dwErrorTimeout = 10000);
258 // Returns TRUE if thread has been created and hasn't yet exited
260 BOOL ThreadExists();
263 ///////////////////////////////////
265 // Functions for both master and worker
269 // Get the priority
271 int GetPriority() const;
274 // Set the priority
276 BOOL SetPriority(int);
279 // Suspend a thread
281 DWORD Suspend();
284 // Resume a suspended thread
286 DWORD Resume();
289 // Force hard-termination of thread. Used for critical failures.
291 BOOL Terminate(DWORD dwExitCode);
294 ///////////////////////////////////
296 // Inter-thread communication
298 // Calls in either direction take place on the same "channel."
299 // Seperate functions are specified to make indents obvious
303 // Master: Signal the thread, and block for a response
305 DWORD CallWorker(DWORD, BOOL fBoostWorkerPriorityToMaster = TRUE);
308 // Master: Signal the thread, and block for a response
310 DWORD CallMaster(DWORD);
313 // Wait for the next request
315 DWORD WaitForCall();
318 // Is there a request?
320 BOOL PeekCall(DWORD * pParam = NULL);
323 // Reply to the request
325 void Reply(DWORD);
328 // If you want to do WaitForMultipleObjects you'll need to include
329 // this handle in your wait list or you won't be responsive
331 HANDLE GetCallHandle();
334 // Find out what the request was
336 DWORD GetCallParam() const;
338 protected:
340 enum
342 kInvalidCallParam = 0xffffffff
346 // Thread will run this function on startup
347 // must be supplied by derived class
349 virtual DWORD ThreadProc() = 0;
351 cThreadLock m_Lock;
353 private:
355 DWORD Call(DWORD, BOOL fBoost);
358 // Thread initially runs this. param is actually 'this'. function
359 // just gets this and calls ThreadProc
361 static unsigned __stdcall InitialThreadProc(LPVOID pv);
363 // make copy constructor and assignment operator inaccessible
364 cWorkerThread(const cWorkerThread &);
365 cWorkerThread &operator=(const cWorkerThread &);
367 HANDLE m_hThread;
369 cThreadEvent m_EventSend;
370 cThreadEvent m_EventComplete;
372 DWORD m_dwParam;
373 DWORD m_dwReturnVal;
378 ///////////////////////////////////////////////////////////////////////////////
380 // Inline functions
383 #ifndef THRDTOOL_DEBUG
385 ///////////////////////////////////////
387 // CLASS: cThreadLock
390 inline cThreadLock::cThreadLock()
392 InitializeCriticalSection(&m_CritSec);
395 ///////////////////////////////////////
397 inline cThreadLock::~cThreadLock()
399 DeleteCriticalSection(&m_CritSec);
402 ///////////////////////////////////////
404 inline void cThreadLock::Lock()
406 EnterCriticalSection(&m_CritSec);
409 ///////////////////////////////////////
411 inline void cThreadLock::Unlock()
413 LeaveCriticalSection(&m_CritSec);
416 ///////////////////////////////////////
418 inline BOOL cThreadLock::AssertOwnedByCurrentThread()
420 return TRUE;
423 ///////////////////////////////////////
425 inline void cThreadLock::SetTrace(BOOL)
429 #endif /* !THRDTOOL_DEBUG */
431 ///////////////////////////////////////
433 // CLASS: cAutoLock
436 inline
437 cAutoLock::cAutoLock(cThreadLock & lock)
438 : m_lock(lock)
440 m_lock.Lock();
443 ///////////////////////////////////////
445 inline
446 cAutoLock::~cAutoLock()
448 m_lock.Unlock();
451 ///////////////////////////////////////
453 // CLASS: cThreadSyncObject
456 inline cThreadSyncObject::cThreadSyncObject()
457 : m_hSyncObject(NULL)
461 ///////////////////////////////////////
463 inline cThreadSyncObject::~cThreadSyncObject()
465 if (m_hSyncObject)
466 Verify(CloseHandle(m_hSyncObject));
469 ///////////////////////////////////////
471 inline BOOL cThreadSyncObject::operator!() const
473 return !m_hSyncObject;
476 ///////////////////////////////////////
478 #ifdef THRDTOOL_DEBUG
479 inline void cThreadSyncObject::AssertUseable()
481 AssertMsg(m_hSyncObject, "Thread synchronization object is unuseable");
483 #endif
485 ///////////////////////////////////////
487 inline cThreadSyncObject::operator HANDLE ()
489 return m_hSyncObject;
492 ///////////////////////////////////////
494 inline BOOL cThreadSyncObject::Wait(DWORD dwTimeout)
496 #ifdef THRDTOOL_DEBUG
497 AssertUseable();
498 #endif
499 return (WaitForSingleObject(m_hSyncObject, dwTimeout) == WAIT_OBJECT_0);
502 ///////////////////////////////////////
504 // CLASS: cThreadEvent
507 inline BOOL cThreadEvent::Set()
509 #ifdef THRDTOOL_DEBUG
510 AssertUseable();
511 #endif
512 return SetEvent(m_hSyncObject);
515 ///////////////////////////////////////
517 inline BOOL cThreadEvent::Reset()
519 #ifdef THRDTOOL_DEBUG
520 AssertUseable();
521 #endif
522 return ResetEvent(m_hSyncObject);
525 ///////////////////////////////////////
527 inline BOOL cThreadEvent::Pulse()
529 #ifdef THRDTOOL_DEBUG
530 AssertUseable();
531 #endif
532 return PulseEvent(m_hSyncObject);
535 ///////////////////////////////////////
537 inline BOOL cThreadEvent::Check()
539 #ifdef THRDTOOL_DEBUG
540 AssertUseable();
541 #endif
542 return Wait(0);
545 ///////////////////////////////////////
547 // CLASS: cWorkerThread
550 inline cWorkerThread::cWorkerThread()
551 : m_EventSend(TRUE), // must be manual-reset for PeekCall()
552 m_hThread(NULL)
556 ///////////////////////////////////////
558 inline int cWorkerThread::GetPriority() const
560 return GetThreadPriority(m_hThread);
563 ///////////////////////////////////////
565 inline BOOL cWorkerThread::SetPriority(int priority)
567 return SetThreadPriority(m_hThread, priority);
570 ///////////////////////////////////////
572 inline DWORD cWorkerThread::Suspend()
574 return SuspendThread(m_hThread);
577 ///////////////////////////////////////
579 inline DWORD cWorkerThread::Resume()
581 return ResumeThread(m_hThread);
584 ///////////////////////////////////////
586 inline BOOL cWorkerThread::Terminate(DWORD dwExitCode)
588 return TerminateThread(m_hThread, dwExitCode);
591 ///////////////////////////////////////
593 inline DWORD cWorkerThread::CallWorker(DWORD dw, BOOL fBoostWorkerPriorityToMaster)
595 return Call(dw, fBoostWorkerPriorityToMaster);
598 ///////////////////////////////////////
600 inline DWORD cWorkerThread::CallMaster(DWORD dw)
602 return Call(dw, FALSE);
605 ///////////////////////////////////////
607 inline HANDLE cWorkerThread::GetCallHandle()
609 return m_EventSend;
612 ///////////////////////////////////////
614 inline DWORD cWorkerThread::GetCallParam() const
616 return m_dwParam;
619 ///////////////////////////////////////
621 #else
623 class cThreadLock
625 public:
626 cThreadLock() {};
627 ~cThreadLock() {};
628 void Lock() {};
629 void Unlock() {};
630 BOOL AssertOwnedByCurrentThread() { return TRUE;}
631 void SetTrace(BOOL) {};
634 class cAutoLock
636 public:
637 cAutoLock(cThreadLock & lock) {};
638 ~cAutoLock() {};
641 #endif
643 ///////////////////////////////////////////////////////////////////////////////
645 #endif /* !__THRDTOOL_H */