#ifndef THREADS_H #define THREADS_H ///////////////////////////////////////////////////////////////////// // threads.h - class supporting creation of threads // // ver 3.9 // // Language: Visual C++, ver 7.1, SP 2 // // Platform: Dell Dimension 8300, Win XP, SP2 // // Application: CSE687 - Object Oriented Design // // Author: Jim Fawcett, CST 2-187, Syracuse Univ // // (315) 443-3948, jfawcett@twcny.rr.com // // // ///////////////////////////////////////////////////////////////////// /* Module Operations ================= The class thread encapsulates creation of Win32 threads. To construct a thread object, you will first need to create a class derived from the processing class, declared in this header file, and pass it to the thread constructor. Each derived processing class must provide a public run() function that defines the operations that the thread is expected to carry out. The test stub in the accompanying implementation file shows how to define classes derived from processing. Note: You need to compile with this project property setting: C/C++\Code Generation\Runtime Library = Multithreaded Debug (/MTd). Public Interface ================ class myProc : public processing { ... } myProc proc; // create a processing object thread t(proc); // create a thread object t.start(); // create running Win32 thread t.wait(); // wait for thread to complete t.sleep(50); // number of milliseconds to sleep t.canSuspend(false); // set false just before thread acquires lock t.canSuspend(true); // set true just after thread releases lock t.suspend(); // suspend thread operation t.resume(); // resume thread operation HANDLE th = t.handle(); // return Win32 thread handle unsigned int id = thread::currentThread(); // return current thread's ID */ // /////////////////////////////////////////////////////////////////////// // Build Process // /////////////////////////////////////////////////////////////////////// // Files required to build test stub: // // threads.h, threads.cpp, locks.h, blockingQueue.h // // // // Compiler Command: // // cl /GX /DTEST_THREADS threads.cpp // // // /////////////////////////////////////////////////////////////////////// /* Maintenance History =================== ver 3.9 : 09 Apr 2005 - separated threads into three modules, this module, locks, and blockingQueues. Version history notes with fixes for locks or blockingQueues were moved to those modules. ver 3.8 : 31 Mar 2005 - added note about project settings to manual page. ver 3.5 : 27 Apr 2004 - added a static function currentThread() to return thread id ver 3.3 : 10 Apr 2004 - a pure virtual clone() function has been added to the processing interface so that each thread can make its own copy of the proc. That avoids a problem when the derived proc object is declared inside a loop, causing each prior proc to get blown away. That could be avoided in ver 3.2 by declaring the proc instance above the loop. Now that is not necessary. ver 3.2 : 08 Apr 2004 - a few cosmetic changes, but no functional changes ver 3.0 : 08 Apr 2004 - added willSelfDestruct() function which you call if, and only if, you created a thread on the heap. The thread then deletes itself when it returns from its processing::run() function. You will find a demonstration in the test stub for this module. - changed the way handles are closed in the start() function to avoid an irritating exception thrown only during debugging. ver 2.1 : 18 Nov 2001 - added setPriority() and alive() member functions ver 2.0 : 10 Nov 2001 - added procWithQ class, providing queuing services for its thread ver 1,2 : 05 Nov 2001 - made processing class abstract - provided fixes to the manual page ver 1.1 : 28 Oct 2001 - added missing file names to Build Process comments ver 1.0 : 26 Oct 2001 - first release */ // #include #include #include #include ///////////////////////////////////////////////////////////////////// // thread processing interface declaration class processing { public: virtual ~processing() {} virtual processing* clone()=0; // used by thread to make its own copy of derived proc instance // which provides the thread's application specific processing virtual void run()=0; }; ///////////////////////////////////////////////////////////////////// // thread class declaration class thread { public: enum priority { low, normal, high }; thread(processing &proc); virtual ~thread(); void start(); void wait(); static unsigned int currentThread(); HANDLE handle(); void canSuspend(bool b=true); // set false if thread holds a lock bool suspend(); // otherwise thread may deadlock void resume(); void sleep(int MilliSec); void setPriority(priority pr); bool alive(); void willSelfDestruct(bool b=true); // call this only if thread created // on heap protected: processing* _pProc; HANDLE th; unsigned int threadID; static unsigned int __stdcall threadProc(void *pSelf); bool _canSuspend; bool _alive; bool _suicidal; }; // //----< constructor >------------------------------------------------ inline thread::thread(processing &proc) : _pProc(proc.clone()), _suicidal(false), _canSuspend(true), th(0) { } //----< enable suicide - call this only if created on heap >--------- inline void thread::willSelfDestruct(bool b) { _suicidal = b; } //----< return thread handle >--------------------------------------- inline HANDLE thread::handle() { return th; } //----< get current thread id >-------------------------------------- inline unsigned int thread::currentThread() { return ::GetCurrentThreadId(); } //----< decrement suspend count >------------------------------------ // // if count is zero, make thread schedualable // inline void thread::resume() { ::ResumeThread(th); } //----< put thread to sleep for t milliseconds >--------------------- inline void thread::sleep(int t) { ::Sleep(t); } //----< is thread locked? >------------------------------------------ inline void thread::canSuspend(bool b) { _canSuspend = b; } #endif