// $Revision: 1.12 $ // Copyright (C) 1994 Taligent, Inc. All rights reserved. #ifndef TaligentSamples_LOCALUTILITIES #include "LocalUtilities.h" #endif #ifndef Taligent_TASK #include #endif #ifndef Taligent_COLLECTIONEXCEPTION #include #endif #ifndef TaligentSamples_CONCURRENTACTORS #include "ConcurrentActors.h" #endif //============================================================================== // TStubBoundThreadProgram class TStubBoundThreadProgram : public TThreadProgram { public: TStubBoundThreadProgram(TBoundThreadProgram* prog); virtual ~TStubBoundThreadProgram(); virtual void Run(); private: TBoundThreadProgram* fProgram; }; TStubBoundThreadProgram::TStubBoundThreadProgram(TBoundThreadProgram* prog) : TThreadProgram(), fProgram(prog) { } TStubBoundThreadProgram::~TStubBoundThreadProgram() { } void TStubBoundThreadProgram::Run() { fProgram->BoundRun(); } //============================================================================== // TBoundThreadProgram TBoundThreadProgram::TBoundThreadProgram() : fThread(NIL) { } TBoundThreadProgram::~TBoundThreadProgram() { } void TBoundThreadProgram::Start() { Terminate(); BoundPrepare(); fThread = new TThreadHandle(new TStubBoundThreadProgram(this)); } void TBoundThreadProgram::Terminate() { if (fThread != NIL) { BoundExit(); fThread->WaitForDeathOf(); delete fThread; fThread = NIL; } } void TBoundThreadProgram::BoundPrepare() { } //============================================================================== // TPeriodicThread TPeriodicThread::TPeriodicThread() : TBoundThreadProgram(), fClock(), fDelay(), fLock(), fDone(true) { } TPeriodicThread::~TPeriodicThread() { } void TPeriodicThread::Pause() { fLock.Acquire(); } void TPeriodicThread::Resume() { fLock.Release(); } void TPeriodicThread::CheckInterval() { fDelay.CancelDelay(); } void TPeriodicThread::BoundPrepare() { fDone = false; } void TPeriodicThread::BoundRun() { fLock.Acquire(); TSystemClock clock; TTime bedTime; clock.Now(bedTime); TTime delayInterval(TSeconds(0)); while (!fDone) { TTime now; clock.Now(now); if (now - bedTime >= delayInterval) { HandleIntervalPassed(now - bedTime); GetDelayInterval(delayInterval); bedTime = now; } fLock.Release(); clock.DelayUntil(bedTime + delayInterval); fLock.Acquire(); } fLock.Release(); } void TPeriodicThread::BoundExit() { TPeriodicThreadEntry entry(this); fDone = true; fDelay.CancelDelay(); } //============================================================================== // TPeriodicThreadEntry TPeriodicThreadEntry::TPeriodicThreadEntry(TPeriodicThread* thread) : fThread(thread) { fThread->Pause(); } TPeriodicThreadEntry::~TPeriodicThreadEntry() { fThread->Resume(); } //============================================================================== // TPrimPCQueue TPrimPCQueue::TPrimPCQueue(unsigned long maxSize) : fMaxSize(maxSize), fItems(), fLock(), fItemInserted(&fLock), fItemRemoved(&fLock), fIsOpen(true) { } TPrimPCQueue::~TPrimPCQueue() { Close(); RemoveAll(); } unsigned long TPrimPCQueue::Count() const { TMonitorEntry entry(&((TPrimPCQueue*)this)->fLock); //cast away const return fItems.Count(); } void TPrimPCQueue::Close() { TMonitorEntry entry(&fLock); if (fIsOpen) { fIsOpen = false; fItemRemoved.Broadcast(); fItemInserted.Broadcast(); } } void TPrimPCQueue::Reopen() { TMonitorEntry entry(&fLock); fIsOpen = true; } bool TPrimPCQueue::IsOpen() const { TMonitorEntry entry(&((TPrimPCQueue*)this)->fLock); //cast away const return fIsOpen; } void TPrimPCQueue::RemoveAll() { TMonitorEntry entry(&fLock); fItems.DeleteAll(); } void TPrimPCQueue::DeleteAll() { TMonitorEntry entry(&fLock); TDequeOfIterator iter(&fItems); long* item = iter.First(); while (item != NIL) { DoDelete((void*)item); item = iter.Next(); } fItems.DeleteAll(); } void TPrimPCQueue::PAdd(void* item) { TMonitorEntry entry(&fLock); while (fIsOpen == true && fItems.Count() == fMaxSize) { fItemRemoved.Wait(); } if (fIsOpen == false) { ThrowQueueClosedException(); } else { long* temp = new long; *temp = (long)item; fItems.Insert(temp); fItemInserted.Notify(); } } void* TPrimPCQueue::PRemoveNext() { void* result = NIL; TMonitorEntry entry(&fLock); while (fIsOpen == true && fItems.Count() == 0) { fItemInserted.Wait(); } if (fItems.Count() == 0) { ThrowQueueClosedException(); } else { long* temp = fItems.Remove(); result = (void*)*temp; delete temp; fItemRemoved.Notify(); } return result; } void TPrimPCQueue::ThrowQueueClosedException() const { throw TCollectionException(); }