#ifndef THRDSWITHPROC_H #define THRDSWITHPROC_H ///////////////////////////////////////////////////////////////////// // thrdsWithProc.h - class supporting creation of threads // // ver 2.0 // // Language: Visual C++, ver 6.0, SP 5 // // Platform: Dell Dimension 8100, Win 2000 Pro, SP 2 // // Application: CSE691/791 - SWM&A Demonstration // // 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. 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 // This module also provides an interface class for processing with a built in queue. The interface defines functions which provide synchronized access to the queue for both parent and child thread processing. You will find an example of how to use that in the test stub for this module. This class is an abstract class, inheriting from the abstract base class processing, so you will have to create a derived class, as described above, and as illustrated in the test stub. Public Interface for procWithQ ============================== class myProc : public procWithQ { public: void run() { // your processing using an mtqueue, e.g.: // string temp = deQ(); // : } }; myProc proc; // declare processing using threads thread t(proc); // create thread t.start(); // start it : proc.enQ("a message"); // main thread sends thread a message : t.wait(); // wait til thread finishes */ /////////////////////////////////////////////////////////////////////// // Build Process // /////////////////////////////////////////////////////////////////////// // Required Files: // // threads.h, threads.cpp, lockingPtr.h, lockingPtr.cpp, // // sysUtils.h, sysUtils.cpp // // // // Compiler Command: // // cl /GX /DTEST_THREADS threads.cpp lockingPtr.cpp sysUtils.cpp // // // /////////////////////////////////////////////////////////////////////// /* Maintenance History =================== 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 "lockingPtr.h" #include "sysUtils.h" #include "mtQueue.h" ///////////////////////////////////////////////////////////////////// // thread processing interface declaration class processing { public: virtual ~processing() {} virtual void run()=0; }; ///////////////////////////////////////////////////////////////////// // thread class declaration class thread { public: enum priority { low, normal, high }; thread(processing &proc) : _proc(proc) { } virtual ~thread(); void start(); void wait(); 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(); HANDLE handle(); protected: processing &_proc; HANDLE th; unsigned int threadID; static unsigned int __stdcall threadProc(void *pSelf); bool _canSuspend; bool _alive; }; // //----< return thread handle >--------------------------------------- inline HANDLE thread::handle() { return th; } //----< increment suspend count >------------------------------------ // // puts thread to sleep if not already asleep // inline bool thread::suspend() { if(_canSuspend) { ::SuspendThread(th); } return _canSuspend; } //----< 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; } // ///////////////////////////////////////////////////////////////////// // procWithQ interface declaration template class procWithQ : public processing { public: virtual ~procWithQ() { } void enQ(const T &t); T deQ(); protected: Mutex _mtx; mtqueue _queue; }; //----< synchronized enqueue >--------------------------------------- template inline void procWithQ::enQ(const T &t) { lockingPtr,Mutex>(_queue,_mtx)->enQ(t); } //----< synchronized dequeue >--------------------------------------- template inline T procWithQ::deQ() { return lockingPtr,Mutex>(_queue,_mtx)->deQ(); } #endif