OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
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.