25#if !defined(OWL_THREAD_H)
29#if defined(BI_HAS_PRAGMA_ONCE)
35#if !defined(BI_MULTI_THREAD)
36#error Thread classes require multi-threaded operating system.
43#if defined(BI_MULTI_THREAD_RTL)
84 void Release(
bool relinquish =
false);
123 TMutex(LPCTSTR name =
nullptr, LPSECURITY_ATTRIBUTES sa =
nullptr);
124 TMutex(
const tstring& name, LPSECURITY_ATTRIBUTES sa =
nullptr);
125 TMutex(LPCTSTR name,
bool inherit,
uint32 access = MUTEX_ALL_ACCESS);
141 virtual void Release();
155 LPSECURITY_ATTRIBUTES sa =
nullptr);
158 uint32 access = SEMAPHORE_ALL_ACCESS);
166 virtual void Release();
176 LPCTSTR name =
nullptr, LPSECURITY_ATTRIBUTES sa =
nullptr);
177 TEventSemaphore(
bool manualReset,
bool initialState,
const tstring& name, LPSECURITY_ATTRIBUTES sa =
nullptr);
179 uint32 access = SEMAPHORE_ALL_ACCESS);
192 virtual void Release();
204#if !defined(CreateWaitableTimer)
205typedef VOID (APIENTRY *
PTIMERAPCROUTINE)(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue );
211 TWaitableTimer(
bool manualReset=
false, LPCTSTR name =
nullptr, LPSECURITY_ATTRIBUTES sa =
nullptr);
219 void* param=
nullptr,
bool resume=
false);
250 const TSemaphore* operator [](
int index)
const;
272 int WhichAquired()
const;
274 void Release(
bool relinquish =
false);
277 bool InitLock(
int count,
TWaitWhat wait,
int index);
286 void Release(
int index = -1);
289 typedef HANDLE THandle;
337 CRITICAL_SECTION CritSec;
624 bool Sleep(
long timeMS,
bool alertable =
false);
626 virtual void Terminate();
628 ulong TerminateAndWait(
ulong timeout = NoLimit);
630 TStatus GetStatus()
const;
631 uint32 GetExitCode()
const;
643 int GetPriority()
const;
644 int SetPriority(
int);
695#if defined(BI_MULTI_THREAD_RTL)
696 static uint __stdcall Execute(
void* thread);
698 static DWORD WINAPI Execute(
void* thread);
704 bool TerminationRequested;
708#if defined(BI_MULTI_THREAD_RTL)
716 virtual ~TLocalObject(){}
722class TXTlsContainer :
public TXBase
726 TXTlsContainer(
const tstring& msg)
758 : Index(::TlsAlloc())
760 TRACEX(OwlThread, 1,
"Initializing " << TraceId(
this));
761 if (Index == TLS_OUT_OF_INDEXES)
762 throw TXTlsContainer(
_T(
"TLS_OUT_OF_INDEXES"));
770 TRACEX(OwlThread, 1,
"Destructing " << TraceId(
this));
772 TCriticalSection::TLock lock(GarbageSection);
773 std::for_each(Garbage.begin(), Garbage.end(), &Delete);
783 {
return static_cast<T*
>(::TlsGetValue(Index));}
792 return p ? *p : Create();
798 const T* Query()
const
799 {
return const_cast<TTlsContainer*
>(
this)->Query();}
805 {
return const_cast<TTlsContainer*
>(
this)->Get();}
809#if defined(OWL5_COMPAT)
831 TCriticalSection GarbageSection;
832 std::vector<T*> Garbage;
836 T* p =
new T();
CHECK(p);
837 bool r = ::TlsSetValue(Index, p);
CHECK(r);
InUse(r);
838 TRACEX(OwlThread, 1, TraceId(
this) <<
" created " << TraceId(p) <<
" for thread " << GetCurrentThreadId());
842 TCriticalSection::TLock lock(GarbageSection);
843 Garbage.push_back(p);
847 static void Delete(T* p)
850 TRACEX(OwlThread, 1, TraceType<TTlsContainer>() <<
" deleted " << TraceId(p));
855 TTlsContainer(
const TTlsContainer&);
856 TTlsContainer& operator =(
const TTlsContainer&);
864#if defined(OWL5_COMPAT)
871class TLocalData:
public TLocalObject {
872 typedef TMIPtrArray<TLocalObject*,TLocalObject*,TLocalObject> TLocalObjectArray;
875 virtual ~TLocalData(){}
877 TLocalObject* GetData(
int index)
879 return index < (int)Data.Size() ? Data[index] : 0;
882 void SetData(
int index, TLocalObject* obj);
884 int AddData(TLocalObject* data) {
return Data.Add(data); }
887 TLocalObjectArray Data;
892 TTlsAllocator() { index = ::TlsAlloc();}
893 ~TTlsAllocator() { ::TlsFree(index); }
895 bool IsOk() {
return index != 0xFFFFFFFF; }
896 bool SetValue(
void* value) { return ::TlsSetValue(index, value); }
897 void* GetValue() { return ::TlsGetValue(index); }
903class TTlsDataManager :
public TLocalObject {
904 typedef TMIPtrArray<TLocalData*,TLocalData*,TLocalObject> TLocalDataArray;
908 CHECK(Allocator.IsOk());
910 virtual ~TTlsDataManager()
912 TMRSWSection::TLock __lock(Lock,
false,
true);
916 TLocalObject* GetData(
int index)
918 TLocalData* data = (TLocalData*)Allocator.GetValue();
919 return (data ? data : CreateData())->GetData(index);
921 void SetData(
int index, TLocalObject* obj)
923 TLocalData* data = (TLocalData*)Allocator.GetValue();
924 (data ? data : CreateData())->SetData(index, obj);
926 int AddData(TLocalObject* obj)
928 TLocalData* data = (TLocalData*)Allocator.GetValue();
929 return (data ? data : CreateData())->AddData(obj);
932 TLocalData* CreateData()
934 TMRSWSection::TLock __lock(Lock,
false,
true);
935 TLocalData* data =
new TLocalData();
937 Allocator.SetValue(data);
942 TTlsAllocator Allocator;
943 TLocalDataArray Data;
947template <
class T>
class TProcessContainer:
public TLocalObject{
949 TProcessContainer():Object(0){}
950 virtual ~TProcessContainer(){
delete Object;}
957 CHECK(
dynamic_cast<TLocalObject*
>(Object));
960 inline T* QueryData() {
return Object; }
961 inline operator T*() {
return GetData(); }
962 inline operator T&() {
return *GetData();}
963 inline T* operator->(){
return GetData(); }
1002 if (::WaitForSingleObjectEx(sem, timeOut, alertable) == 0)
1015 return Sem !=
nullptr;
1043 Handle = ::CreateMutex(sa,
false, name);
1044 if (
Handle && (GetLastError() == ERROR_ALREADY_EXISTS))
1054 Handle = ::CreateMutex(sa,
false, name.c_str());
1055 if (
Handle && (GetLastError() == ERROR_ALREADY_EXISTS))
1068 Handle = ::OpenMutex(access, inherit, name);
1079 Handle = ::OpenMutex(access, inherit, name.c_str());
1093 if (::DuplicateHandle(::GetCurrentProcess(), handle,
1094 ::GetCurrentProcess(), &
Handle,
1095 0,
false, DUPLICATE_SAME_ACCESS))
1115 LPSECURITY_ATTRIBUTES sa)
1117 Handle = ::CreateSemaphore(sa, initialCount, maxCount, name);
1125 Handle = ::CreateSemaphore(sa, initialCount, maxCount, name.c_str());
1132 Handle = ::OpenSemaphore(access, inherit, name);
1140 Handle = ::OpenSemaphore(access, inherit, name.c_str());
1146 ::DuplicateHandle(::GetCurrentProcess(), handle,
1147 ::GetCurrentProcess(), &
Handle,
1148 0,
false, DUPLICATE_SAME_ACCESS);
1156 LPSECURITY_ATTRIBUTES sa)
1158 Handle = ::CreateEvent(sa, manualReset, initialState, name);
1166 Handle = ::CreateEvent(sa, manualReset, initialState, name.c_str());
1173 Handle = ::OpenEvent(access, inherit, name);
1181 Handle = ::OpenEvent(access, inherit, name.c_str());
1187 ::DuplicateHandle(::GetCurrentProcess(), handle,
1188 ::GetCurrentProcess(), &
Handle,
1189 0,
false, DUPLICATE_SAME_ACCESS);
1199 ::ResetEvent(*
this);
1204 ::PulseEvent(*
this);
1211 ::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(),
1212 &
Handle, 0,
false, DUPLICATE_SAME_ACCESS);
1229 return (index >= 0 && index < Count) ? Sems[index] :
nullptr;
1235 return Set !=
nullptr;
1256 ::InitializeCriticalSection(
CONST_CAST(CRITICAL_SECTION*,&CritSec));
1264 ::DeleteCriticalSection(
CONST_CAST(CRITICAL_SECTION*,&CritSec));
1279 ::EnterCriticalSection(
CONST_CAST(CRITICAL_SECTION*,&CritSecObj.CritSec));
1287 ::LeaveCriticalSection(
CONST_CAST(CRITICAL_SECTION*,&CritSecObj.CritSec));
1345 return sync->CritSec;
1354template <
class T>
ulong TStaticSync<T>::Count;
1403 return ::SleepEx(timeMS, alertable) == WAIT_IO_COMPLETION;
1415 Stat = CheckStatus();
1423 ::GetExitCodeThread(Handle,
static_cast<DWORD*
>(&code));
1433 return ::GetThreadPriority(Handle);
1444 return TerminationRequested;
#define TRACEX(group, level, message)
TCountedSemaphore(int initialCount, int maxCount, LPCTSTR name=nullptr, LPSECURITY_ATTRIBUTES sa=nullptr)
This nested class handles locking and unlocking critical sections.
TLock(const TCriticalSection &)
Use system call to lock the CRITICAL_SECTION object.
~TLock()
Use system call to unlock the CRITICAL_SECTION object.
Lightweight intra-process thread synchronization.
TCriticalSection()
Use system call to initialize the CRITICAL_SECTION object.
TLock Lock
For compatibility with old T-less typename.
~TCriticalSection()
Use system call to destroy the CRITICAL_SECTION object.
TEventSemaphore(bool manualReset=false, bool initialState=false, LPCTSTR name=nullptr, LPSECURITY_ATTRIBUTES sa=nullptr)
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.
Mutual-exclusive semaphore.
TMutex(LPCTSTR name=nullptr, LPSECURITY_ATTRIBUTES sa=nullptr)
Constructs a TMutex instance encapsulating a newly created named or unnamed mutex object.
TLock Lock
For compatibility with old T-less typename.
bool IsShared()
If another mutex with the same name existed when this mutex was created, then another handle to the o...
TLock(const TSemaphore &, ulong timeOut=NoLimit, bool alertable=false)
void Release(bool relinquish=false)
Release lock early & relinquish, i.e.
bool WasAquired() const
See if really aquired, or just timed-out.
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.
friend class TSemaphoreSet
int WhichAquired() const
See which was aquired >=0, or enum.
TLock(const TSemaphoreSet &set, TWaitWhat wait, ulong timeOut=NoLimit, bool alertable=false)
Assumes that set is not modified while locked.
bool WasAquired() const
See if one or more was aquired.
@ IoComplete
IO complate alert.
@ AllAquired
All semaphores were aquired.
@ TimedOut
None aquired: timed out.
void Remove(const TSemaphore &sem)
const TSemaphore * operator[](int index) const
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)
Provides class-specific operator new and operator delete that simply call the global operator new and...
const TStaticSync< T > & operator=(const TStaticSync< T > &)
TLock Lock
For compatibility with old T-less typename.
This nested class handles locking and unlocking critical sections.
TLock(const TSync *)
Locks the TCriticalSection object in the TSync object.
const TSync & operator=(const TSync &)
Does not copy the TCriticalSection object, since the new object is not being used in any of its own m...
TSync()
Default constructor.
TLock Lock
For compatibility with old T-less typename.
The error class that defines the objects that are thrown when an error occurs.
TErrorType
Identifies the type of error that occurred.
@ 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.
@ NoMTRuntime
This usually results when you attempt to execute a multithread application which includes a module th...
@ CreationFailure
The operating system was unable to create the thread.
@ ResumeAfterExit
The user called Resume() on an object whose thread had already exited.
TErrorType GetErrorType() const
Returns a code indicating the type of error that occurred.
TThread provides a system-independent interface to threads.
uint32 GetExitCode() const
TStatus GetStatus() const
Gets the current status of the thread.
int GetPriority() const
Gets the thread priority.
TStatus Status
For compatibility with old T-less typenames.
void Exit(ulong code)
Alternative to returning from Run().
TThread(TCurrent)
Attach to a running thread.
bool ShouldTerminate() const
Returns a bool value to indicate that Terminate() or TerminateAndWait() has been called.
bool Sleep(long timeMS, bool alertable=false)
Suspends execution of the current thread for the number of milliseconds specified by the timeMS param...
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)
virtual ~TWaitableTimer()
TWaitableTimer(bool manualReset=false, LPCTSTR name=nullptr, LPSECURITY_ATTRIBUTES sa=nullptr)
Derived from xmsg, TXBase is the base class for ObjectWindows and ObjectComponents exception-handling...
TXBase(const tstring &msg)
Calls the xmsg class's constructor that takes a string parameter and initializes xmsg with the value ...
Base exception support for framework exceptions.
VOID(APIENTRY *) PTIMERAPCROUTINE(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
Encapsulation of Waitable Timer over Borland Classlib TSemaphore hierarchy.
Object Windows Library (OWLNext Core).
void InUse(const T &arg)
Handy utility to avoid compiler warnings about unused parameters.
DIAG_DECLARE_GROUP(OwlThread)
General definitions used by all ObjectWindows programs.
#define CONST_CAST(targetType, object)
Definition of container classes used and made available by OWL.
Classes for window system structure and type encapsulation.