1 ///////////////////////////////////////////////////////////////////////////////
2 // $Source: x:/prj/tech/libsrc/lg/RCS/thrdtool.h $
4 // $Date: 1997/01/07 13:05:41 $
7 // Tools for thread synchronization and management.
16 #if defined(DEBUG) || defined(ONEOPT)
17 #define THRDTOOL_DEBUG
20 ///////////////////////////////////////////////////////////////////////////////
24 // Wrapper for critical sections management
34 // Get/wait for ownership of the critical section
39 // Release ownership of the critical section
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
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.
58 // make copy constructor and assignment operator inaccessible
59 cThreadLock(const cThreadLock
&refCritSec
);
60 cThreadLock
&operator=(const cThreadLock
&refCritSec
);
62 CRITICAL_SECTION m_CritSec
;
65 DWORD m_currentOwnerID
;
67 BOOL m_fTrace
; // Trace this one
72 ///////////////////////////////////////////////////////////////////////////////
76 // Locks a critical section, and unlocks it automatically
77 // when the lock goes out of scope
83 cAutoLock(cThreadLock
& 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
107 ~cThreadSyncObject();
110 // Query if object is useful
112 BOOL
operator!() const;
120 // Wait for a signal from the object
122 BOOL
Wait(DWORD dwTimeout
= INFINITE
);
126 #ifdef THRDTOOL_DEBUG
127 void AssertUseable();
130 HANDLE m_hSyncObject
;
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
149 cThreadEvent(BOOL fManualReset
= FALSE
);
152 // Set the state to signaled
158 // Set the state to nonsignaled
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.
170 // Check if the event is signaled
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
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
);
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
212 cThreadMutex(BOOL fEstablishInitialOwnership
= FALSE
);
215 // Release ownership of the mutex
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.
239 virtual ~cWorkerThread();
241 ///////////////////////////////////
243 // Functions for the master thread
247 // Start thread running - error if already running
252 // Accessor thread calls this when done with thread (having told thread
255 void WaitForClose(DWORD dwErrorTimeout
= 10000);
258 // Returns TRUE if thread has been created and hasn't yet exited
263 ///////////////////////////////////
265 // Functions for both master and worker
271 int GetPriority() const;
276 BOOL
SetPriority(int);
284 // Resume a suspended thread
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
318 // Is there a request?
320 BOOL
PeekCall(DWORD
* pParam
= NULL
);
323 // Reply to the request
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;
342 kInvalidCallParam
= 0xffffffff
346 // Thread will run this function on startup
347 // must be supplied by derived class
349 virtual DWORD
ThreadProc() = 0;
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
&);
369 cThreadEvent m_EventSend
;
370 cThreadEvent m_EventComplete
;
378 ///////////////////////////////////////////////////////////////////////////////
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()
423 ///////////////////////////////////////
425 inline void cThreadLock::SetTrace(BOOL
)
429 #endif /* !THRDTOOL_DEBUG */
431 ///////////////////////////////////////
437 cAutoLock::cAutoLock(cThreadLock
& lock
)
443 ///////////////////////////////////////
446 cAutoLock::~cAutoLock()
451 ///////////////////////////////////////
453 // CLASS: cThreadSyncObject
456 inline cThreadSyncObject::cThreadSyncObject()
457 : m_hSyncObject(NULL
)
461 ///////////////////////////////////////
463 inline cThreadSyncObject::~cThreadSyncObject()
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");
485 ///////////////////////////////////////
487 inline cThreadSyncObject::operator HANDLE ()
489 return m_hSyncObject
;
492 ///////////////////////////////////////
494 inline BOOL
cThreadSyncObject::Wait(DWORD dwTimeout
)
496 #ifdef THRDTOOL_DEBUG
499 return (WaitForSingleObject(m_hSyncObject
, dwTimeout
) == WAIT_OBJECT_0
);
502 ///////////////////////////////////////
504 // CLASS: cThreadEvent
507 inline BOOL
cThreadEvent::Set()
509 #ifdef THRDTOOL_DEBUG
512 return SetEvent(m_hSyncObject
);
515 ///////////////////////////////////////
517 inline BOOL
cThreadEvent::Reset()
519 #ifdef THRDTOOL_DEBUG
522 return ResetEvent(m_hSyncObject
);
525 ///////////////////////////////////////
527 inline BOOL
cThreadEvent::Pulse()
529 #ifdef THRDTOOL_DEBUG
532 return PulseEvent(m_hSyncObject
);
535 ///////////////////////////////////////
537 inline BOOL
cThreadEvent::Check()
539 #ifdef THRDTOOL_DEBUG
545 ///////////////////////////////////////
547 // CLASS: cWorkerThread
550 inline cWorkerThread::cWorkerThread()
551 : m_EventSend(TRUE
), // must be manual-reset for PeekCall()
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()
612 ///////////////////////////////////////
614 inline DWORD
cWorkerThread::GetCallParam() const
619 ///////////////////////////////////////
630 BOOL
AssertOwnedByCurrentThread() { return TRUE
;}
631 void SetTrace(BOOL
) {};
637 cAutoLock(cThreadLock
& lock
) {};
643 ///////////////////////////////////////////////////////////////////////////////
645 #endif /* !__THRDTOOL_H */