windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/upssvc/apcsmart/thrdable.cxx
2020-09-26 16:20:57 +08:00

238 lines
5.4 KiB
C++

/*
*
* NOTES:
*
* REVISIONS:
* ane09DEC92 - added code for rundown of threads
* ane30Dec92 - increase stack size for threads
* jod02Feb93 - increase stack size for threads to 10240
* ane08Feb93 - added ExitWait
* pcy05Mar93 - split off from thread.cxx
* rct20Apr93 - changed ExitNow(), added appropriate header files
* pcy28Apr93 - Removed debug puts() left in code
* cad27May93 - fixed semaphore handling to let thread exit
* tje01Jun93 - Added use of NullSemaphore for single-threaded platforms
* cad09Jul93: using new semaphores
* cad15Jul93: releasing during exitwait to avoid deadlocks
* cad07Oct93: Moved timeout constant to .h file
* cad27Oct93: Fixed problem with global possibly being gone on exitwait()
* rct16Nov93: Added single thread implementation
* ajr24Nov93: Added SetLastPeriod. Took method out of header file.
* ajr24Nov93: Initialized theLastPeriod in constructor
* cad11Jan94: Changes for new process manager
* jps28aug94: added test of theExitSem in ExitNow()
* ajr02May95: Need to stop carrying time in milliseconds
* srt24Oct96: Fixed time_out value usage
*/
#include "cdefine.h"
extern "C" {
#if(C_OS & C_OS2)
#define INCL_BASE
#define INCL_NOPM
#define UINT UINT_os2
#define ULONG ULONG_os2
#define COLOR COLOR_os2
#include "os2.h"
#undef UINT
#undef ULONG
#undef COLOR
#endif
#ifdef SINGLETHREADED
#include <time.h>
#endif
}
#include "thrdable.h"
#if (C_OS & C_OS2)
#include "apcsem2x.h"
#elif (C_OS & C_NLM)
#include "nlmsem.h"
#elif (C_OS & C_NT)
#include "apcsemnt.h"
#include "mutexnt.h"
#endif
#ifdef SINGLETHREADED
#include "nullsem.h"
#include "procmgr.h"
#endif
//#include "timerman.h"
//-------------------------------------------------------------------
Threadable::Threadable ()
{
SetThreadName("Unknown");
#ifdef MULTITHREADED
theResumeFlag = new ApcSemaphore();
theExitSem = new ApcSemaphore();
theExitDoneSem = new ApcSemaphore();
#else
theResumeFlag = new NullSemaphore();
theExitSem = new NullSemaphore();
theExitDoneSem = new NullSemaphore();
theServicePeriod = DEFAULT_SERVICE_PERIOD;
theLastPeriod = 0;
theNextPeriod = 0;
#endif
}
//-------------------------------------------------------------------
Threadable::~Threadable ()
{
#if (C_OS & C_NT)
//
// Dont remove this wait. NT needs it for some reason??
Sleep(0);
#endif
delete theResumeFlag;
theResumeFlag = (PSemaphore)NULL;
delete theExitSem;
theExitSem = (PSemaphore)NULL;
delete theExitDoneSem;
theExitDoneSem = (PSemaphore)NULL;
}
//-------------------------------------------------------------------
// This function is used to tell a threadable object to exit - it will
// pause for THREAD_EXIT_TIMEOUT milliseconds for the thread to exit and
// then will continue
INT Threadable::Exit()
{
#ifdef SINGLETHREADED
return _theProcessManager->RemoveThread(this);
#else
theResumeFlag->Pulse(); // just in case
theExitSem->Post();
return theExitDoneSem->TimedWait((THREAD_EXIT_TIMEOUT*1000));
#endif
}
VOID Threadable::SetThreadName(PCHAR aName)
{
strncpy(theThreadName, aName, MAX_THREAD_NAME);
}
PCHAR Threadable::GetThreadName(VOID)
{
return theThreadName;
}
//-------------------------------------------------------------------
// This function is used to tell a threadable object to exit - it will
// wait indefinitely for the thread to exit
INT Threadable::ExitWait()
{
#ifdef SINGLETHREADED
return _theProcessManager->RemoveThread(this);
#else
theExitSem->Post(); // tell them to go away
theResumeFlag->Post(); // just in case
return theExitDoneSem->Wait(); // wait for them to do so
#endif
}
//-------------------------------------------------------------------
INT Threadable::Reset()
{
if (theExitSem->IsPosted())
{
theExitSem->Clear();
}
if (theResumeFlag->IsPosted())
{
theResumeFlag->Clear();
}
if (theExitDoneSem->IsPosted())
{
theExitDoneSem->Clear();
}
return ErrNO_ERROR;
}
//-------------------------------------------------------------------
// This function is called from within a thread to see if Exit or ExitWait
// has been called.
INT Threadable::ExitNow()
{
#ifdef MULTITHREADED
if (theExitSem)
return (theExitSem->IsPosted());
else
return TRUE;
#else
return ErrNO_ERROR;
#endif
}
//-------------------------------------------------------------------
// This function is called from within a thread to mark the fact that the
// thread has been exited.
INT Threadable::DoneExiting()
{
INT err = ErrNO_ERROR;
if (this != NULL && theExitDoneSem != NULL) {
theExitDoneSem->Post();
}
return err;
}
//-------------------------------------------------------------------
#ifdef SINGLETHREADED
ULONG Threadable::GetServicePeriod() const
{
return theServicePeriod;
}
VOID Threadable::SetServicePeriod(ULONG period)
{
theServicePeriod = period;
ULONG next_period = 0L;
if (theLastPeriod > 0) {
next_period = theLastPeriod + theServicePeriod;
}
_theProcessManager->SetNextServiceTime(this, next_period);
}
ULONG Threadable::GetLastPeriod(void)
{
return theLastPeriod;
}
VOID Threadable::SetLastPeriod(ULONG period)
{
theLastPeriod = period;
}
ULONG Threadable::GetNextPeriod(void)
{
return theNextPeriod;
}
VOID Threadable::SetNextPeriod(ULONG period)
{
theNextPeriod = period;
_theProcessManager->SetNextServiceTime(this, theNextPeriod);
}
#endif