21#if defined(__BORLANDC__)
39 ::ReleaseMutex(*
this);
47 ::ReleaseSemaphore(*
this, 1,
nullptr);
66 Handle = CreateWaitableTimer(sa, manualReset, name);
75 Handle = CreateWaitableTimer(sa, manualReset, name.c_str());
82 Handle = OpenWaitableTimer(access, inherit, name);
91 Handle = OpenWaitableTimer(access, inherit, name.c_str());
99 return CancelWaitableTimer(
Handle) ? true :
false;
106 return SetWaitableTimer(
Handle, (
const LARGE_INTEGER*)&duetime,period,compFunc,param, resume);
126 Size = size >= 0 ? size : count;
131 for (; i < Count; i++)
133 for (; i < Size; i++)
148 Sems[Count++] = &sem;
154 CHECK(Count <= Size);
155 for (
int i = 0; i < Count; i++)
156 if (Sems[i] == &sem) {
157 for (
int j = i; j < Count-1; j++)
159 Sems[Count-1] =
nullptr;
165void TSemaphoreSet::Release(
int index)
170 for (
int i = 0; i <
Count; i++)
175static HANDLE* newHandles(
const TSemaphoreSet& set)
177 HANDLE* handles =
new HANDLE[set.GetCount()];
178 for (
int i = 0; i < set.GetCount(); i++) {
180 handles[i] = *set[i];
187 ulong timeOut,
bool alertable)
194 ::WaitForMultipleObjectsEx(set.Count, handles, wait, timeOut, alertable)))
205 ::MsgWaitForMultipleObjects(set.Count, handles, wait, timeOut, msgMask)))
214 if ((index >=
static_cast<int>(WAIT_OBJECT_0) && index <
static_cast<int>(WAIT_OBJECT_0 + count)) ||
215 (index >=
static_cast<int>(WAIT_ABANDONED_0) && index <
static_cast<int>(WAIT_ABANDONED_0 + count)))
218 if (index >=
static_cast<int>(WAIT_ABANDONED_0))
219 index -= WAIT_ABANDONED_0;
226 else if (index ==
int(WAIT_OBJECT_0+count))
228 else if (index == WAIT_TIMEOUT)
230 else if (index ==
static_cast<int>(WAIT_IO_COMPLETION))
274 static TNtDll_& GetInstance()
289 static TNtDll_ instance;
298 CRITICAL_SECTION CSection;
299 HANDLE hSharedSemaphore;
300 ULONG sharedExclusive;
301 HANDLE hExclusiveSemaphore;
302 ULONG exclusiveWaiters;
303 ULONG numberOfWaiters;
306 PRTL_RESOURCE_DEBUG DebugInfo;
309 typedef RTL_RESOURCE* PRTL_RESOURCE;
311 TModuleProcV1<PRTL_RESOURCE> RtlInitializeResource;
312 TModuleProcV1<PRTL_RESOURCE> RtlDeleteResource;
313 TModuleProc2<BOOLEAN, PRTL_RESOURCE, BOOLEAN> RtlAcquireResourceExclusive;
314 TModuleProc2<BOOLEAN, PRTL_RESOURCE, BOOLEAN> RtlAcquireResourceShared;
315 TModuleProcV1<PRTL_RESOURCE> RtlReleaseResource;
316 TModuleProcV1<PRTL_RESOURCE> RtlDumpResource;
321 : TModule(
_T(
"ntdll.dll"), true, true, false),
322 RtlInitializeResource(*this,
"RtlInitializeResource"),
323 RtlDeleteResource(*this,
"RtlDeleteResource"),
324 RtlAcquireResourceExclusive(*this,
"RtlAcquireResourceExclusive"),
325 RtlAcquireResourceShared(*this,
"RtlAcquireResourceShared"),
326 RtlReleaseResource(*this,
"RtlReleaseResource"),
327 RtlDumpResource(*this,
"RtlDumpResource")
329 TRACEX(OwlThread, 1,
"Initializing " << TraceId(
this));
332 TNtDll_(
const TNtDll_&);
333 TNtDll_& operator =(
const TNtDll_&);
339 TNtDll_& InitNtDllInstance = TNtDll_::GetInstance();
343struct TMRSWSection::TPimpl
346 TNtDll_::RTL_RESOURCE RtlResource;
348 TPimpl(TNtDll_& dll) : Dll(dll) {}
352 : Pimpl(new TPimpl(TNtDll_::GetInstance()))
354 Pimpl->Dll.RtlInitializeResource(&Pimpl->RtlResource);
359 Pimpl->Dll.RtlDeleteResource(&Pimpl->RtlResource);
365 Pimpl->Dll.RtlDumpResource(&Pimpl->RtlResource);
371 TNtDll_& dll = Section.Pimpl->Dll;
372 TNtDll_::PRTL_RESOURCE r = &Section.Pimpl->RtlResource;
374 dll.RtlAcquireResourceShared(r, wait) :
375 dll.RtlAcquireResourceExclusive(r, wait);
382 TNtDll_& dll = Section.Pimpl->Dll;
383 TNtDll_::PRTL_RESOURCE r = &Section.Pimpl->RtlResource;
384 dll.RtlReleaseResource(r);
403 TerminationRequested(0),
413 ThreadId(::GetCurrentThreadId()),
416 TerminationRequested(0),
419 ::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentThread(),
420 ::GetCurrentProcess(), &Handle,
421 0,
false, DUPLICATE_SAME_ACCESS);
434 TerminationRequested(0),
460 if (
this != &thread) {
464 TerminationRequested =
false;
472#if defined(BI_COMP_MSC)
485 WARN(!ok,
_T(
"TThread::~TThread: Terminating due to failed precondition. Error: ")
487 if (!ok) std::terminate();
492# if !defined(BI_MULTI_THREAD_RTL) || !defined(BI_COMP_BORLANDC)
493 ::CloseHandle(Handle);
508 ::CloseHandle(Handle);
511# if defined(BI_MULTI_THREAD_RTL)
512 Handle = (HANDLE)(UINT_PTR)::_beginthreadex(
nullptr, 4096, &TThread::Execute,
this, 0, (
uint*)&ThreadId);
514 Handle = ::CreateThread(0, 0, &TThread::Execute,
this, 0, &ThreadId);
518 TRACEX(OwlThread, 1,
_T(
"Thread started [id:") << Handle <<
_T(
']'));
522 TRACEX(OwlThread, 2,
_T(
"Thread failed to start"));
539 TRACEX(OwlThread, 2,
_T(
"Illegal Created thread suspension [id:") << Handle <<
_T(
']'));
542 TRACEX(OwlThread, 2,
_T(
"Illegal Finished thread suspension [id:") << Handle <<
_T(
']'));
545 ulong res = ::SuspendThread(Handle);
546 if (res < MAXIMUM_SUSPEND_COUNT)
549 TRACEX(OwlThread, 0,
_T(
"Thread suspended [id:") << Handle <<
_T(
", Count:") << res <<
_T(
']'));
562 TRACEX(OwlThread, 2,
_T(
"Illegal Created thread resumption [id:") << Handle <<
_T(
']'));
565 TRACEX(OwlThread, 2,
_T(
"Illegal Running thread resumption [id:") << Handle <<
_T(
']'));
568 TRACEX(OwlThread, 2,
_T(
"Illegal Finished thread resumption [id:") << Handle <<
_T(
']'));
571 ulong res = ::ResumeThread(Handle);
572 TRACEX(OwlThread, 0,
_T(
"Thread resumed [id:") << Handle <<
_T(
", Count:") << res <<
_T(
']'));
588 TRACEX(OwlThread, 1,
_T(
"Thread termination requested [handle:") << Handle <<
_T(
']'));
589 TerminationRequested =
true;
600 TRACEX(OwlThread, 1,
_T(
"Waiting for thread exit [id:") << Handle <<
_T(
']'));
602 return ::WaitForSingleObject(Handle, timeout);
604 return static_cast<ulong>(-1);
627 TRACEX(OwlThread, 1,
_T(
"Thread priority changed to ") << pri <<
628 _T(
" [id:") << Handle <<
_T(
']'));
629 return ::SetThreadPriority(Handle, pri);
641 TRACEX(OwlThread, 1,
_T(
"Illegal Run() on base TThread [id:") << Handle <<
_T(
']'));
651#if defined(BI_MULTI_THREAD_RTL)
653uint __stdcall TThread::Execute(
void* thread)
662DWORD WINAPI TThread::Execute(
void* thread)
680# if (defined(BI_COMP_MSC)||defined(BI_COMP_GNUC)) && defined(BI_MULTI_THREAD_RTL)
691TThread::CheckStatus()
const
694 ::GetExitCodeThread(Handle, &code);
695 if (code == STILL_ACTIVE)
706TThread::TThreadError::TThreadError(TErrorType type)
708 TXBase(MakeString(type)),
718tstring TThread::TThreadError::MakeString(TErrorType type)
720 static const tchar*
const Names[] = {
721 _T(
"Suspend() before Run()"),
722 _T(
"Resume() before Run()"),
723 _T(
"Resume() during Run()"),
724 _T(
"Suspend() after Exit()"),
725 _T(
"Resume() after Exit()"),
726 _T(
"creation failure"),
727 _T(
"destroyed before Exit()"),
728 _T(
"illegal assignment"),
729 _T(
"Multithreaded Runtime not selected"),
733 Msg =
_T(
"Error[thread]: ");
740#if defined(BI_MULTI_THREAD_RTL) && defined(OWL5_COMPAT)
744void TLocalData::SetData(
int index, TLocalObject* obj)
746 while(index >= (
int)Data.Size())
759static long _owlTlsRef = 0;
#define WARN(condition, message)
#define TRACEX(group, level, message)
Pointer to an array of type T.
TFileTime is a class derived from the structure FILETIME.
TLock(TMRSWSection &, bool shared, bool wait=true)
shared == true; allows multiple (read) access to the section.
TXLockFailure(const tstring &msg)
void Dump()
Dumps the current state of the section to the debugger output.
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Base class for handle-based thread synchronization classes, TMutex, TCountedSemaphore and TEventSemap...
THandle Handle
Derived class must initialize.
virtual void Release()=0
Derived class must provide release.
void Release(bool relinquish=false)
TLock(const TSemaphoreSet &set, TWaitWhat wait, ulong timeOut=NoLimit, bool alertable=false)
Assumes that set is not modified while locked.
bool InitLock(int count, TWaitWhat wait, int index)
@ IoComplete
IO complate alert.
@ AllAquired
All semaphores were aquired.
@ TimedOut
None aquired: timed out.
void Remove(const TSemaphore &sem)
TSemaphoreSet(const TSemaphore *sems[], int size=-1)
sems is initial array of sem ptrs, may be 0 to add sems later, size is maximum sems to hold,...
void Add(const TSemaphore &sem)
The error class that defines the objects that are thrown when an error occurs.
@ SuspendBeforeRun
The user called Suspend() on an object before calling Start().
@ AssignError
An attempt was made to assign to an object that was not in either the Created or the Finished state.
@ ResumeBeforeRun
The user called Resume() on an object before calling Start().
@ DestroyBeforeExit
The object's destructor was invoked its thread had exited.
@ ResumeDuringRun
The user called Resume() on a thread that was not Suspended.
@ SuspendAfterExit
The user called Suspend() on an object whose thread had already exited.
@ CreationFailure
The operating system was unable to create the thread.
@ ResumeAfterExit
The user called Resume() on an object whose thread had already exited.
TThread()
Create a thread. Derived class overrides Run().
ulong TerminateAndWait(ulong timeout=NoLimit)
Combines the behavior of Terminate() and WaitForExit().
ulong WaitForExit(ulong timeout=NoLimit)
Blocks the calling thread until the internal thread exits or until the time specified by timeout,...
THandle Start()
Starts the thread executing.
int SetPriority(int)
Can pass a TPriority for simplicity.
TStatus GetStatus() const
Gets the current status of the thread.
virtual ~TThread()
TThread destructor.
const TThread & operator=(const TThread &)
TThread assignment operator.
ulong Suspend()
Suspends execution of the thread.
ulong Resume()
Resumes execution of a suspended thread.
void Exit(ulong code)
Alternative to returning from Run().
TThread(TCurrent)
Attach to a running thread.
virtual void Terminate()
Mark the thread for termination.
TStatus
Identifies the states that the class can be in.
@ Created
The class has been created but the thread has not been started.
@ Finished
The thread has finished execution.
@ Suspended
The thread has been suspended.
@ Invalid
The object is invalid. Currently this happens only when the operating system is unable to start the t...
@ Running
The thread is running.
bool Set(const TFileTime &duetime, int32 period=0, PTIMERAPCROUTINE compFunc=nullptr, void *param=nullptr, bool resume=false)
TWaitableTimer(bool manualReset=false, LPCTSTR name=nullptr, LPSECURITY_ATTRIBUTES sa=nullptr)
TXBase(const tstring &msg)
Calls the xmsg class's constructor that takes a string parameter and initializes xmsg with the value ...
TXOwl(const tstring &msg, uint resId=0)
An OWL exception with a given message for displaying and an unsigned Id that can be used for identifi...
VOID(APIENTRY *) PTIMERAPCROUTINE(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
Encapsulation of Waitable Timer over Borland Classlib TSemaphore hierarchy.
Definition of class TModule.
Object Windows Library (OWLNext Core).
OWL_DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlThread, 1, 0)
ulong TStaticSync< T >::Count
ObjectWindows exception class & function definitions.
#define CONST_CAST(targetType, object)
#define STATIC_CAST(targetType, object)
Various types of smart pointer templatized classes.