home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
deans.zip
/
PROCESS.HPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-14
|
20KB
|
503 lines
//
// NAME: CIDLib_Process.Hpp
//
// DESCRIPTION:
//
// This module provides task and thread control classes. Threads are named
// for easy identification in log file messages and such. The
// CIDLib_Process.Cpp module maintains a linked list of threads that a
// process starts so that it can insure that thread names are not
// duplicated.
//
// The relevant portion of the hierarchy is:
//
// CIDOBJECT
// │
// THREAD
//
//
//
// AUTHOR: Dean Roddey
//
// CREATE DATE: 04/16/93
//
// COPYRIGHT: 1992..1994, 'CIDCorp
//
// CAVEATS/GOTCHAS:
//
// 1) When a thread object is created, a function address is passed to it
// that will become the thread entry point. That function must be a
// pfnTHREADFUNC function.
//
// 2) The destructor for a thread object can be called while the thread is
// still running. It will kill the thread if so.
//
// 3) A simple synchonization method is provided via the WaitSync()/Sync()
// methods, which allow two threads to sync up with each other. If the
// controlling application needs more complex synchronization, it must
// communicate with the thread via some IPC mechanism.
//
// 4) Other subsystems can register to have an object created for every
// thread that is constructed. This gives them the ability to have
// per-thread data with no effort.
//
// 5) Each thread object has a CIDERROR object into which the last error
// that occured on that thread can be stored. The client can query this
// last error, which will clear it.
//
// 6) An exception handler is installed for every thread. If will clear the
// thread's state flags when it is killed and will log exception info
// when the thread has an access violation that is not handled by a
// higher level exception handler.
//
//
// MODIFICATION LOG:
//
// Avoid multiple inclusion
#if !defined(CIDLIB_PROCESS_HPP)
#define CIDLIB_PROCESS_HPP
// -----------------------------------------------------------------------------
// Forward reference some structures needed for a friend declaration below
// -----------------------------------------------------------------------------
struct _EXCEPTIONREPORTRECORD;
struct _EXCEPTIONREGISTRATIONRECORD;
struct _CONTEXT;
// -----------------------------------------------------------------------------
// Process related constants
// -----------------------------------------------------------------------------
const tCIDLib::CARD4 c4MaxPTObjs = 64;
// -----------------------------------------------------------------------------
// CLASS: THREAD
// PREFIX: thr
//
// This class provides thread support.
// -----------------------------------------------------------------------------
class THREAD : public CIDOBJECT
{
public :
// ---------------------------------------------------------------------
// Contructors and Destructors
//
// THREAD
// This is the only contructor for threads. The default
// constructor is protected so that it can't be called by
// accident, it is also not exported. The bAutoStart flag
// indicates whether the thread should be started during the
// constructor or just instantiated in a dormant state, to be
// stated by a call to c4Start() call. It defaults to FALSE,
// which means no autostart. The bSelfPrio parm indicates
// whether this thread should not allow any other thread to
// set his priority.
//
// ~THREAD
// This is the destructor for threads. It will remove the
// thread object from the list of thread objects maintained by
// CIDLib_Process.Cpp. This guy will destroy the __perrLast
// object and the thread data buffer that was passed to the
// thread.
// ---------------------------------------------------------------------
THREAD
(
const STRG32& strName
, tCIDLib::pfnTHREADFUNC pbFunc
, tCIDLib::CARD4 c4StackSz = 0x7FFF
, tCIDLib::VOID* pData = 0
, tCIDLib::eBOOL bAutoStart = tCIDLib::eFALSE
, tCIDLib::eBOOL bSelfPrio = tCIDLib::eFALSE
);
~THREAD();
// ---------------------------------------------------------------------
// Static methods
//
// c4RegisterPerThreadObj
// This method can be called by subsystems to register per-thread
// object storage. For every thread created, each subsystem's
// callout function (the pfnPerThread parm) is called to allow
// them to create an object for that thread. The return is a handle
// that the subsystem can use to access the object later. The
// passed object name string is just a descriptive string used for
// logging messages regarding this object.
// This is not exported directly to the user, they have an API via
// the facCIDLib facility to register per-thread objects.
// ---------------------------------------------------------------------
static tCIDLib::CARD4 c4RegisterPerThreadObj
(
const STRG64& strObjName
, tCIDLib::pfnPTHRFUNC pfnPerThread
);
// ---------------------------------------------------------------------
// Public, inherited methods
//
// FormatToStr
// Formats some debug info into the string.
// ---------------------------------------------------------------------
STDVPUBMETHODS(THREAD,CIDOBJECT,tCIDLib::eFALSE);
virtual tCIDLib::VOID FormatToStr
(
STRGBUF& strbDest
) const;
// ---------------------------------------------------------------------
// Public virtual methods
//
// Init
// Terminate
// These methods are used to give derived classes a chance to get
// control after the thread is created but before the client's
// thread function is called and after the client's thread
// returns, but before the thread is terminated. But, if the
// autostart is used to start the thread from the THREAD
// constructor, the derived class's constructor will not have
// been entered at the time of the Init call.
// ---------------------------------------------------------------------
virtual tCIDLib::VOID Init() {}
virtual tCIDLib::VOID Terminate() {}
// ---------------------------------------------------------------------
// Public, non-virtual methods
//
// bIsRunning
// The method will return the running flag
//
// bProbeBuffer
// This method will install an exception handler and then probe
// the bounds of the passed buffer. If the probe generates an
// exception, the return is eFALSE. It just reads the first and
// last byte of the buffer, not the whole thing.
//
// bRelease
// When another thread has synced with this thread, this thread
// will be blocked until the other thread calls this thread's
// bRelease() to let this thread go again.
//
// bStart
// This method will start the thread running if not already.
//
// bWaitSync
// This method is called by another thread to sync up with this
// thread. The other thread will be blocked until this thread
// calls bSync(), at which time the other thead will unblock.
//
// ClrLastErr
// This guy will clear the error info for the thread. It is
// inline for speed.
//
// c4LastErrCode
// Returns the error code of the last error stored away by this
// thread. This will clear the error.
//
// pfnSetOnExit
// This will set a new On-Exit function for this thread and
// return the current one. It can only be called by this thread.
//
// perrLast
// Returns a pointer to the last error object. This will clear
// the last error and the caller is responsible for deleting
// the object.
//
// SetPriority
// This method will set the priority of this thread. If the
// thread is in 'self prio' mode, no other thread can call this
// method. One verion allows a set of the class and absolute
// level with that class (which must be less than the value
// tCIDLib::c4MaxPrioLev.) The other version just sets the
// relative level with the existing class, so it takes a signed
// offset from the current value.
//
// StoreNewError
// Stores a new last error for this thread. It deletes the last
// stored error and saves away the address of the new one. Only
// this thread can call it.
//
// strName
// Returns a cosnstant reference to the name of the thread
//
// Sync
// This method can be called by the thread function to sync up
// with another thread. If another thread has called bWaitSync()
// and is waiting for this thread to sync, then this thread will
// block and the other will be awakened. The other thread can do
// whatever is needed. The other thead can then call bRelease()
// to let this thread go again. Only this thread can call this
// method.
//
// tidThread
// Returns the thread id. Should not be needed by public but just
// in case.
// ---------------------------------------------------------------------
tCIDLib::eBOOL bIsRunning
(
) const {return __bRunning;}
tCIDLib::eBOOL bProbeBuffer
(
tCIDLib::VOID* pBuffer
, tCIDLib::CARD4 c4Len
);
tCIDLib::eBOOL bRelease();
tCIDLib::eBOOL bStart();
tCIDLib::eBOOL bWaitSync();
tCIDLib::VOID ClrLastErr();
tCIDLib::CARD4 c4LastErrCode();
tCIDLib::VOID GetPriority
(
tCIDLib::ePRTYCLASS& ePrtyClass
, tCIDLib::CARD4& c4PrioLev
);
tCIDLib::pfnEXITFUNC pfnSetOnExit
(
tCIDLib::pfnEXITFUNC pfnNew
);
CIDERROR* perrLast();
tCIDLib::VOID SetPriority
(
tCIDLib::ePRTYCLASS ePrtyClass
, tCIDLib::CARD4 c4PrioLev
);
tCIDLib::VOID SetPriority
(
tCIDLib::INT4 i4PrioLev
);
tCIDLib::VOID StoreNewError
(
CIDERROR* perrNew
);
const STRG32& strName() const;
tCIDLib::VOID Sync();
TID tidThread
(
) const {return __tidThread;}
protected :
// ---------------------------------------------------------------------
// Hidden constructors/operators
//
// THREAD
// Hide the default constructor so that empty threads can't be
// created. Hide the copy constructor and assignment operator
// so they can't be assigned.
// ---------------------------------------------------------------------
THREAD();
THREAD
(
const THREAD& thrSrc
);
THREAD& operator=
(
const THREAD& thrSrc
);
// ---------------------------------------------------------------------
// Protected, inherited methods
//
// _bIsEqual
// This method is called from the public bIsEqual, which has
// determined that the objects are of comparable classes and are
// not the same object. It does the comparison down the class
// hierarchy.
// ---------------------------------------------------------------------
virtual tCIDLib::eBOOL _bIsEqual
(
const CIDOBJECT& objTarget
) const;
// ---------------------------------------------------------------------
// Protected, non-virtual methods
//
// _CheckIsCallerSelf
// This method will make sure that the calling thread is this
// thread. If not, it will issue a fatal error message using the
// passed method name. An optional text message can be passed
// that will be placed into the aux text of the logged error.
//
// _Exiting
// This is provided so that the thread exception handler
// installed for every thread can clear the running flag.
// ---------------------------------------------------------------------
tCIDLib::VOID _CheckCallerIsSelf
(
const tCIDLib::CH* pszMethod
, const tCIDLib::CH* pszAuxText = 0
) const;
tCIDLib::VOID _Exiting();
// ---------------------------------------------------------------------
// Declare friends
// ---------------------------------------------------------------------
friend tCIDLib::eBOOL _bInitProcess();
friend APIRET APIENTRY __ThreadException
(
_EXCEPTIONREPORTRECORD* pRep
, _EXCEPTIONREGISTRATIONRECORD* pReg
, _CONTEXT* pContext
, tCIDLib::VOID* pDummy
);
friend tCIDLib::VOID THREADFUNC __ThreadStart
(
tCIDLib::VOID* pData
);
friend tCIDLib::VOID _LogExceptInfo
(
_EXCEPTIONREPORTRECORD* pRep
, _EXCEPTIONREGISTRATIONRECORD* pReg
, _CONTEXT* pContext
);
private :
// ---------------------------------------------------------------------
// Private, non-virtual methods
//
// __CreatePerThreadObjs
// This method will create any registered per-thread objects for
// this thread.
//
// __DestroyPerThreadObjs
// This method will destroy the object's per thead objects.
// ---------------------------------------------------------------------
tCIDLib::VOID __CreatePerThreadObjs();
tCIDLib::VOID __DestroyPerThreadObjs();
// ---------------------------------------------------------------------
// Private data members
//
// __apobjList
// This is the array of per-thread objects. It is filled in by the
// constructor and cleaned up by the destructor. It holds the
// per-thread objects. The current number of valid entries is
// known inside the .Cpp module.
//
// __bRunning
// Set if the thread is currently running. It is cleared when the
// thread function returns.
//
// __bSelfPrio
// This flag (when set) prevents any other thread from setting
// this thread's priority.
//
// __bSyncRequest
// This is set to indicate that another thread has called
// bWaitSync(). It is also used to make sure that two threads
// don't try to sync at the same time. We store the tid of the
// syncing thread to be able to insure that only he releases
// the sync (in __tidSyncRequester.)
//
// __c4StackSz
// The size of the stack to give to the thread. Passed in by the
// creator.
//
// __perrLast
// Storage for the last error that occured. Each time a new error
// is stored (via StoreNewError()), the old one is deleted and the
// new one is stored here. Only copies are returned to callers so
// there is no problem with this. It is also deleted when the
// client calls to get the error info. This leaves the error info
// cleared until the next error.
//
// __hevSync
// This semaphore is used by the Sync()/WaitSync() methods to
// allow the thread to sync with another thread. It is also used
// during thread startup to sync.
//
// __hevResponse
// This semaphore is used by the Sync()/WaitSync() methods to
// allow the thread to sync with another thread.
//
// __pfnFunc
// This is the address of the function that will be the entry
// point of the thread. It is called from the .bStart() method.
// When it returns, the destructor is called.
//
// __pfnOnExit
// This is the address of an optional on-exit function that
// may be provided by the client code. It will be called when
// the thread is shutting down. If the client does not set the
// function, it is 0.
//
// __pData
// A pointer to the data buffer that was passed to the thread.
//
// __tidSyncReq
// When a sync request is made, we store the id of the thread
// that is syncing. This allows us to make sure that only that
// thread releases the sync.
//
// __tidThread
// The thread id for this thread. This is used later to identify
// this thread and get its name for error reported.
//
// __szName
// The name of the thread. This was passed in by the caller in the
// constructor.
// ---------------------------------------------------------------------
CIDOBJECT* __apobjList[c4MaxPTObjs];
tCIDLib::eBOOL __bRunning;
tCIDLib::eBOOL __bSelfPrio;
tCIDLib::eBOOL __bSyncRequest;
tCIDLib::CARD4 __c4StackSz;
CIDERROR* __perrLast;
HEV __hevSync;
HEV __hevResponse;
tCIDLib::pfnTHREADFUNC __pfnFunc;
tCIDLib::pfnEXITFUNC __pfnOnExit;
tCIDLib::VOID* __pData;
TID __tidSyncReq;
TID __tidThread;
STRG32 __strName;
};
//
// Some global functions for formatting our enumerated values. The actual
// functions are in CIDLib_FmtType.Cpp.
//
STRGBUF& operator<<(STRGBUF& strDest, tCIDLib::ePRTYCLASS ePrtyClass);
OTXTFILE& operator<<(OTXTFILE& txflDest, tCIDLib::ePRTYCLASS ePrtyClass);
#endif