OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
thread.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1993, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// TThread class implementation
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9
10#include <owl/thread.h>
11#include <owl/pointer.h>
12#include <owl/except.h>
13#include <owl/module.h>
14
15#if !defined(WINELIB)
16#include <process.h>
17#endif // !WINELIB
18
19#include <stdlib.h>
20
21#if defined(__BORLANDC__)
22# pragma option -w-ccc // Disable "Condition is always true/false"
23# pragma option -w-inl // Disable "Functions containing 'statement' is not expanded inline".
24#endif
25
26namespace owl {
27
29
30//----------------------------------------------------------------------------
31// Semaphores Win32
32//
33
34//----------------------------------------
35// TMutex WIN32
36
37void TMutex::Release()
38{
39 ::ReleaseMutex(*this);
40}
41
42//----------------------------------------
43// TCountedSemaphore WIN32
44
45void TCountedSemaphore::Release()
46{
47 ::ReleaseSemaphore(*this, 1, nullptr);
48}
49
50//----------------------------------------
51// TEventSemaphore WIN32
52
53void TEventSemaphore::Release()
54{
55 // Events don't need to be released
56}
57
58//----------------------------------------
59// TWaitableTimer
60
61//
62//
63//
69
70//
71// String-aware overload
72//
74{
76 if (!Handle) throw TXOwl(_T("CreateWaitableTimer failed."));
77}
78
79//
81{
83 if (!Handle) throw TXOwl(_T("OpenWaitableTimer failed."));
84}
85
86//
87// String-aware overload
88//
90{
92 if (!Handle) throw TXOwl(_T("OpenWaitableTimer failed."));
93}
94
95//
96bool
98{
99 return CancelWaitableTimer(Handle) ? true : false; // handle to a timer object
100}
101
102//
103bool
108//
110{
111}
112
113//----------------------------------------
114// TSemaphoreSet & its TLock for Win32
115
116//
118:
119 Sems(nullptr)
120{
121 int count = 0;
122 if (sems)
123 while (sems[count])
124 count++;
125 Count = count;
126 Size = size >= 0 ? size : count;
127 if (Size) {
128 Sems = CONST_CAST(const TSemaphore**, new TSemaphorePtr[Size]);
129 int i = 0;
130 if (sems)
131 for (; i < Count; i++)
132 Sems[i] = sems[i];
133 for (; i < Size; i++)
134 Sems[i] = nullptr;
135 }
136}
137
138//
140{
141 delete[] Sems;
142}
143
144//
146{
147 if (Count < Size)
148 Sems[Count++] = &sem;
149}
150
151//
153{
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++) // Shift rest down to keep packed
158 Sems[j] = Sems[j+1];
159 Sems[Count-1] = nullptr;
160 return;
161 }
162}
163
164//
165void TSemaphoreSet::Release(int index)
166{
167 if (index >= 0)
168 CONST_CAST(TSemaphore*,Sems[index])->Release();
169 else
170 for (int i = 0; i < Count; i++)
171 CONST_CAST(TSemaphore*,Sems[i])->Release();
172}
173
174//
175static HANDLE* newHandles(const TSemaphoreSet& set)
176{
177 HANDLE* handles = new HANDLE[set.GetCount()];
178 for (int i = 0; i < set.GetCount(); i++) {
179 CHECK(set[i]);
180 handles[i] = *set[i]; // Assumes non-0 since i is in set range
181 }
182 return handles;
183}
184
185//
187 ulong timeOut, bool alertable)
188:
189 Set(nullptr)
190{
191 TAPointer<THandle> handles(newHandles(set));
192
193 if (InitLock(set.Count, wait,
195 Set = &set;
196}
197
198//
201{
202 TAPointer<THandle> handles(newHandles(set));
203
204 if (InitLock(set.Count, wait,
206 Set = &set;
207}
208
209//
210// Init the Set and Locked members after a system wait call
211//
213{
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)))
216 {
217 if (wait == WaitAny) {
218 if (index >= static_cast<int>(WAIT_ABANDONED_0))
219 index -= WAIT_ABANDONED_0;
220 Locked = index; // Just this one is locked
221 }
222 else
223 Locked = AllAquired; // They are all locked
224 return true;
225 }
226 else if (index == int(WAIT_OBJECT_0+count))
227 Locked = MsgWaiting;
228 else if (index == WAIT_TIMEOUT)
229 Locked = TimedOut;
230 else if (index == static_cast<int>(WAIT_IO_COMPLETION))
231 Locked = IoComplete;
232 return false;
233}
234
235//
237{
238 Release();
239}
240
241//
243{
244 if (Set) {
245 CONST_CAST(TSemaphoreSet*,Set)->Release(Locked);
246 if (relinquish)
247 Set = nullptr;
248 }
249}
250
251//----------------------------------------------------------------------------
252// class TMRSWSection
253//
254
255namespace
256{
257
258 //
259 // This class encapsulates the undocumented fat read/write lock functions in "ntdll.dll".
260 // See http://undoc.airesoft.co.uk/ntdll.dll/RtlInitializeResource.php
261 // These functions are used to implement TMRSWSection.
262 //
263 // TODO: Investigate alternatives that do not rely on this undocumented feature, such as the
264 // documented slim read/write (SRW) functions in the Windows API since Vista.
265 //
266 class TNtDll_ : public TModule
267 {
268 public:
269
270 //
271 // Returns the module instance.
272 // Exceptions are thrown if the module cannot be loaded.
273 //
274 static TNtDll_& GetInstance()
275 {
276 //
277 // Note that while this lazy initialization avoids problems with global initialization order,
278 // the initial call of this function is not thread-safe (pre C++11). As a work-around, we
279 // ensure this function is called during program start-up (single-thread, safe).
280 // See InitNtDllInstance below.
281 //
282 // The work-around can be removed when C++11 compliant compilers are mandated.
283 //
284 // Also note that the singleton construction may throw an exception. Since there is no way to
285 // continue without this singleton, we make no attempt to handle it here. We assume that
286 // the exception will terminate the program, or if it is handled, that subsequent calls will
287 // be retried still within a single thread.
288 //
289 static TNtDll_ instance; // initial call (construction) not thread-safe pre-C++11
290 return instance;
291 }
292
293 //
294 // Undocumented structure representing the critical section.
295 //
296 struct RTL_RESOURCE
297 {
298 CRITICAL_SECTION CSection;
299 HANDLE hSharedSemaphore;
300 ULONG sharedExclusive;
301 HANDLE hExclusiveSemaphore;
302 ULONG exclusiveWaiters;
303 ULONG numberOfWaiters;
304 HANDLE hOwnerThread;
305 ULONG flags;
306 PRTL_RESOURCE_DEBUG DebugInfo;
307 };
308
309 typedef RTL_RESOURCE* PRTL_RESOURCE;
310
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;
317
318 private:
319
320 TNtDll_()
321 : TModule(_T("ntdll.dll"), true, true, false), // shouldLoad, mustLoad and !addToList
322 RtlInitializeResource(*this, "RtlInitializeResource"),
323 RtlDeleteResource(*this, "RtlDeleteResource"),
324 RtlAcquireResourceExclusive(*this, "RtlAcquireResourceExclusive"),
325 RtlAcquireResourceShared(*this, "RtlAcquireResourceShared"),
326 RtlReleaseResource(*this, "RtlReleaseResource"),
327 RtlDumpResource(*this, "RtlDumpResource")
328 {
329 TRACEX(OwlThread, 1, "Initializing " << TraceId(this));
330 }
331
332 TNtDll_(const TNtDll_&); // prohibited
333 TNtDll_& operator =(const TNtDll_&); // prohibited
334 };
335
336 //
337 // Ensure singleton initialization at start-up (single-threaded, safe).
338 //
339 TNtDll_& InitNtDllInstance = TNtDll_::GetInstance();
340
341} // namespace
342
343struct TMRSWSection::TPimpl
344{
345 TNtDll_& Dll;
346 TNtDll_::RTL_RESOURCE RtlResource;
347
348 TPimpl(TNtDll_& dll) : Dll(dll) {}
349};
350
352 : Pimpl(new TPimpl(TNtDll_::GetInstance()))
353{
354 Pimpl->Dll.RtlInitializeResource(&Pimpl->RtlResource);
355}
356
358{
359 Pimpl->Dll.RtlDeleteResource(&Pimpl->RtlResource);
360 delete Pimpl;
361}
362
364{
365 Pimpl->Dll.RtlDumpResource(&Pimpl->RtlResource);
366}
367
369 : Section(s)
370{
371 TNtDll_& dll = Section.Pimpl->Dll;
372 TNtDll_::PRTL_RESOURCE r = &Section.Pimpl->RtlResource;
373 bool ok = shared ?
374 dll.RtlAcquireResourceShared(r, wait) :
375 dll.RtlAcquireResourceExclusive(r, wait);
376 if (!ok)
377 throw TXLockFailure(_T("TMRSWSection::TLock failed to acquire lock"));
378}
379
381{
382 TNtDll_& dll = Section.Pimpl->Dll;
383 TNtDll_::PRTL_RESOURCE r = &Section.Pimpl->RtlResource;
384 dll.RtlReleaseResource(r);
385}
386
390
391//----------------------------------------------------------------------------
392// TThread Win32
393
394//
395// TThread constructors
396//
397/// Creates an object of type TThread.
399:
400 ThreadId(0),
401 Handle(nullptr),
402 Stat(Created),
403 TerminationRequested(0),
404 Attached(false)
405{
406}
407
408//
409/// Attach to a running thread
410//
412:
413 ThreadId(::GetCurrentThreadId()),
414 Handle(nullptr),
415 Stat(Running),
416 TerminationRequested(0),
417 Attached(true)
418{
420 ::GetCurrentProcess(), &Handle,
421 0, false, DUPLICATE_SAME_ACCESS);
422}
423
424//
425/// Puts the object into the Created
426/// state, just like the default constructor.
427/// Does not copy any of the internal details of the thread being copied.
428//
430:
431 ThreadId(0),
432 Handle(nullptr),
433 Stat(Created),
434 TerminationRequested(0),
435 Attached(false)
436{
437}
438
439//
440/// TThread assignment operator
441//
442/// Used when assigning derived objects. Attempting to assign from a running
443/// object is an error, since the data fields in the running object can be
444/// changing asynchronously.
445///
446/// The target object must be in either the
447/// Created state or the Finished state. If
448/// so, puts the object into the Created
449/// state. If the object is not in either the
450/// Created state or the Finished state it
451/// is an error and an exception will be
452/// thrown.
453
455{
456 switch (GetStatus()) {
457 case Created:
458 case Suspended:
459 case Finished: {
460 if (this != &thread) {
461 Handle = nullptr;
462 ThreadId = 0;
463 Stat = Created;
464 TerminationRequested = false;
465 Attached = false;
466 }
467 return *this;
468 }
469 default:
471 }
472#if defined(BI_COMP_MSC)
473 return *this; // Bogus return to make MSVC happy
474#endif
475}
476
477//
478/// TThread destructor
479//
480/// If the thread hasn't finished, destroying its control object is an error.
481//
483{
484 const auto ok = Attached || !(GetStatus() == Running || GetStatus() == Suspended);
485 WARN(!ok, _T("TThread::~TThread: Terminating due to failed precondition. Error: ")
486 << TThreadError::MakeString(TThreadError::DestroyBeforeExit));
487 if (!ok) std::terminate();
488
489//
490// The RTL calls CloseHandle in _endthread, so we shouldn't if the thread
491// was started with _beginthreadNT(...).
492# if !defined(BI_MULTI_THREAD_RTL) || !defined(BI_COMP_BORLANDC)
493 ::CloseHandle(Handle);
494# endif
495}
496
497//
498/// Starts the thread executing. The actual call depends on the operating system.
499/// Returns the handle of the thread.
500/// After the system call we check status.
501//
503{
504 // If Start() has already been called for this thread, release the
505 // previously created system thread object before launching a new one.
506 //
507 if ((GetStatus() != Created) && Handle) {
508 ::CloseHandle(Handle);
509 }
510
511# if defined(BI_MULTI_THREAD_RTL)
512 Handle = (HANDLE)(UINT_PTR)::_beginthreadex(nullptr, 4096, &TThread::Execute, this, 0, (uint*)&ThreadId);
513# else
514 Handle = ::CreateThread(0, 0, &TThread::Execute, this, 0, &ThreadId);
515# endif
516
517 if (Handle) {
518 TRACEX(OwlThread, 1, _T("Thread started [id:") << Handle << _T(']'));
519 Stat = Running;
520 }
521 else {
522 TRACEX(OwlThread, 2, _T("Thread failed to start"));
523 Stat = Invalid;
525 }
526
527 return Handle;
528}
529
530/// Suspends execution of the thread.
531//
532/// It's an error to try to suspend a thread that hasn't been started or that
533/// has already terminated.
534//
536{
537 switch (GetStatus()) {
538 case Created:
539 TRACEX(OwlThread, 2, _T("Illegal Created thread suspension [id:") << Handle << _T(']'));
541 case Finished:
542 TRACEX(OwlThread, 2, _T("Illegal Finished thread suspension [id:") << Handle << _T(']'));
544 default:
545 ulong res = ::SuspendThread(Handle);
546 if (res < MAXIMUM_SUSPEND_COUNT) // Else a problem
547 Stat = Suspended;
548
549 TRACEX(OwlThread, 0, _T("Thread suspended [id:") << Handle << _T(", Count:") << res << _T(']'));
550 return res;
551 }
552}
553
554/// Resumes execution of a suspended thread.
555//
556/// It's an error to try to resume a thread that isn't suspended.
557//
559{
560 switch (GetStatus()) {
561 case Created:
562 TRACEX(OwlThread, 2, _T("Illegal Created thread resumption [id:") << Handle << _T(']'));
564 case Running:
565 TRACEX(OwlThread, 2, _T("Illegal Running thread resumption [id:") << Handle << _T(']'));
567 case Finished:
568 TRACEX(OwlThread, 2, _T("Illegal Finished thread resumption [id:") << Handle << _T(']'));
570 default:
571 ulong res = ::ResumeThread(Handle);
572 TRACEX(OwlThread, 0, _T("Thread resumed [id:") << Handle << _T(", Count:") << res << _T(']'));
573 if (res == 1) // Y.B. suggested by Richard.D.Crossley and Fendy Riyanto
574 Stat = Running;
575 return res;
576 }
577}
578
579//
580/// Mark the thread for termination.
581//
582/// Sets an internal flag that indicates that the
583/// thread should exit. The derived class can check
584/// the state of this flag by calling ShouldTerminate().
585//
587{
588 TRACEX(OwlThread, 1, _T("Thread termination requested [handle:") << Handle << _T(']'));
589 TerminationRequested = true;
590}
591
592//
593/// Blocks the calling thread until the internal
594/// thread exits or until the time specified by
595/// timeout, in milliseconds,expires. A timeout of
596/// NoLimit says to wait indefinitely.
597//
599{
600 TRACEX(OwlThread, 1, _T("Waiting for thread exit [id:") << Handle << _T(']'));
601 if (Stat == Running)
602 return ::WaitForSingleObject(Handle, timeout);
603 else
604 return static_cast<ulong>(-1);
605}
606
607//
608/// Combines the behavior of Terminate() and
609/// WaitForExit(). Sets an internal flag that
610/// indicates that the thread should exit and blocks
611/// the calling thread until the internal thread
612/// exits or until the time specified by timeout, in
613/// milliseconds, expires. A timeout of NoLimit says
614/// to wait indefinitely.
615//
621
622//
623/// Sets the priority of the thread.
624//
626{
627 TRACEX(OwlThread, 1, _T("Thread priority changed to ") << pri <<
628 _T(" [id:") << Handle << _T(']'));
629 return ::SetThreadPriority(Handle, pri);
630}
631
632//
633/// This function does the actual thread execution. Calling Start creates a thread
634/// that begins executing Run with the this pointer pointing to the TThread-based
635/// object. Every derived class should define its own version of Run. See the
636/// example provided.
637//
638int
639TThread::Run()
640{
641 TRACEX(OwlThread, 1, _T("Illegal Run() on base TThread [id:") << Handle << _T(']'));
642 return -1;
643}
644
645//
646// Run the thread. This static function is given as the thread start address,
647// with 'this' thread object passed as the param. Invoke the Run() method on
648// the thread
649//
650
651#if defined(BI_MULTI_THREAD_RTL)
652
653uint __stdcall TThread::Execute(void* thread)
654{
655 int code = STATIC_CAST(TThread*,thread)->Run();
656 STATIC_CAST(TThread*,thread)->Stat = Finished;
657 return code;
658}
659
660#else
661
662DWORD WINAPI TThread::Execute(void* thread)
663{
664 int code = STATIC_CAST(TThread*,thread)->Run();
665 STATIC_CAST(TThread*,thread)->Stat = Finished;
666 return code;
667}
668
669#endif
670
671//
672/// Exit provides an alternative to returning from Run.
673//
674/// Called from within the thread that wants to exit early.
675//
676void
678{
679 Stat = Finished;
680# if (defined(BI_COMP_MSC)||defined(BI_COMP_GNUC)) && defined(BI_MULTI_THREAD_RTL)
682# else
684# endif
685}
686
687//
688// Call only when Stat claims that the thread is Running.
689//
691TThread::CheckStatus() const
692{
693 DWORD code;
694 ::GetExitCodeThread(Handle, &code);
695 if (code == STILL_ACTIVE)
696 return Running;
697 else
698 return Finished;
699}
700
701//----------------------------------------------------------------------------
702
703//
704// TThread::TThreadError constructor
705//
706TThread::TThreadError::TThreadError(TErrorType type)
707:
708 TXBase(MakeString(type)),
709 Type(type)
710{
711}
712
713//
714// TThread::TThreadError::MakeString()
715//
716// Translates an error code into a string.
717//
718tstring TThread::TThreadError::MakeString(TErrorType type)
719{
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"),
730 };
731 tstring Msg;
732 Msg.reserve(80);
733 Msg = _T("Error[thread]: ");
734 Msg += Names[type];
735 return Msg;
736}
737} // OWL namespace
738//
739
740#if defined(BI_MULTI_THREAD_RTL) && defined(OWL5_COMPAT)
741
742namespace owl {
743
744void TLocalData::SetData(int index, TLocalObject* obj)
745{
746 while(index >= (int)Data.Size())
747 Data.Add(0);
748 Data[index] = obj;
749}
750
751} // OWL namespace
752
753#endif
754
755//
756// These are just dummies left over from the old implementation of thread-local storage.
757//
758
759static long _owlTlsRef = 0;
760
762{
763 return _owlTlsRef++;
764}
765
767{
768 return --_owlTlsRef;
769}
770
771/* ========================================================================== */
#define OWL_DIAG_DEFINE_GROUP_INIT(f, g, e, l)
Definition checks.h:426
#define CHECK(condition)
Definition checks.h:239
#define WARN(condition, message)
Definition checks.h:273
#define TRACEX(group, level, message)
Definition checks.h:263
TFileTime is a class derived from the structure FILETIME.
Definition wsyscls.h:362
TLock(TMRSWSection &, bool shared, bool wait=true)
shared == true; allows multiple (read) access to the section.
Definition thread.cpp:368
TXLockFailure(const tstring &msg)
Definition thread.cpp:387
Multiple Read, Single Write section.
Definition thread.h:348
void Dump()
Dumps the current state of the section to the debugger output.
Definition thread.cpp:363
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:75
Base class for handle-based thread synchronization classes, TMutex, TCountedSemaphore and TEventSemap...
Definition thread.h:65
THandle Handle
Derived class must initialize.
Definition thread.h:95
void Release(bool relinquish=false)
Definition thread.cpp:242
TLock(const TSemaphoreSet &set, TWaitWhat wait, ulong timeOut=NoLimit, bool alertable=false)
Assumes that set is not modified while locked.
Definition thread.cpp:186
bool InitLock(int count, TWaitWhat wait, int index)
Definition thread.cpp:212
Semaphore object aggregator.
Definition thread.h:238
void Remove(const TSemaphore &sem)
Definition thread.cpp:152
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,...
Definition thread.cpp:117
void Add(const TSemaphore &sem)
Definition thread.cpp:145
The error class that defines the objects that are thrown when an error occurs.
Definition thread.h:647
@ SuspendBeforeRun
The user called Suspend() on an object before calling Start().
Definition thread.h:651
@ AssignError
An attempt was made to assign to an object that was not in either the Created or the Finished state.
Definition thread.h:658
@ ResumeBeforeRun
The user called Resume() on an object before calling Start().
Definition thread.h:652
@ DestroyBeforeExit
The object's destructor was invoked its thread had exited.
Definition thread.h:657
@ ResumeDuringRun
The user called Resume() on a thread that was not Suspended.
Definition thread.h:653
@ SuspendAfterExit
The user called Suspend() on an object whose thread had already exited.
Definition thread.h:654
@ CreationFailure
The operating system was unable to create the thread.
Definition thread.h:656
@ ResumeAfterExit
The user called Resume() on an object whose thread had already exited.
Definition thread.h:655
TThread provides a system-independent interface to threads.
Definition thread.h:601
TThread()
Create a thread. Derived class overrides Run()
Definition thread.cpp:398
ulong TerminateAndWait(ulong timeout=NoLimit)
Combines the behavior of Terminate() and WaitForExit().
Definition thread.cpp:616
ulong WaitForExit(ulong timeout=NoLimit)
Blocks the calling thread until the internal thread exits or until the time specified by timeout,...
Definition thread.cpp:598
THandle Start()
Starts the thread executing.
Definition thread.cpp:502
int SetPriority(int)
Can pass a TPriority for simplicity.
Definition thread.cpp:625
TStatus GetStatus() const
Gets the current status of the thread.
Definition thread.h:1412
virtual ~TThread()
TThread destructor.
Definition thread.cpp:482
const TThread & operator=(const TThread &)
TThread assignment operator.
Definition thread.cpp:454
ulong Suspend()
Suspends execution of the thread.
Definition thread.cpp:535
ulong Resume()
Resumes execution of a suspended thread.
Definition thread.cpp:558
void Exit(ulong code)
Alternative to returning from Run()
Definition thread.cpp:677
virtual void Terminate()
Mark the thread for termination.
Definition thread.cpp:586
TStatus
Identifies the states that the class can be in.
Definition thread.h:613
@ Created
The class has been created but the thread has not been started.
Definition thread.h:614
@ Finished
The thread has finished execution.
Definition thread.h:617
@ Suspended
The thread has been suspended.
Definition thread.h:616
@ Invalid
The object is invalid. Currently this happens only when the operating system is unable to start the t...
Definition thread.h:618
@ Running
The thread is running.
Definition thread.h:615
bool Set(const TFileTime &duetime, int32 period=0, PTIMERAPCROUTINE compFunc=nullptr, void *param=nullptr, bool resume=false)
Definition thread.cpp:104
virtual void Release()
Definition thread.cpp:109
TWaitableTimer(bool manualReset=false, LPCTSTR name=nullptr, LPSECURITY_ATTRIBUTES sa=nullptr)
Definition thread.cpp:64
Derived from xmsg, TXBase is the base class for ObjectWindows and ObjectComponents exception-handling...
Definition exbase.h:41
TXOwl is root class of the ObjectWindows exception hierarchy.
Definition except.h:38
#define _T(x)
Definition cygwin.h:51
VOID(APIENTRY * PTIMERAPCROUTINE)(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
Encapsulation of Waitable Timer over Borland Classlib TSemaphore hierarchy.
Definition thread.h:205
long TlsAddRefs()
Definition thread.cpp:761
long TlsRelease()
Definition thread.cpp:766
Definition of class TModule.
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
signed long int32
Definition number.h:30
unsigned long ulong
Definition number.h:26
const tchar * Section
Definition rcntfile.cpp:45
unsigned long uint32
Definition number.h:34
char tchar
Definition defs.h:77
std::string tstring
Definition defs.h:79
unsigned int uint
Definition number.h:25
#define OWL_INI
Definition defs.h:170
ObjectWindows exception class & function definitions.
#define CONST_CAST(targetType, object)
Definition defs.h:273
#define STATIC_CAST(targetType, object)
Definition defs.h:271
Various types of smart pointer templatized classes.