Anzeigen: Delphi
C++
Anzeigeeinstellungen
System.TMonitor
Aus XE2 API Documentation
Delphi
TMonitor = record strict private type PWaitingThread = ^TWaitingThread; TWaitingThread = record Next: PWaitingThread; Thread: TThreadID; WaitEvent: Pointer; end; { TSpinWait implements an exponential backoff algorithm for TSpinLock. The algorithm is as follows: If the CPUCount > 1, then the first 10 (YieldThreshold) spin cycles (calls to SpinCycle) will use a base 2 exponentially increasing spin count starting at 4. After 10 cycles, then the behavior reverts to the same behavior as when CPUCount = 1. If the CPUCount = 1, then it will sleep 1ms every modulus 20 cycles and sleep 0ms every modulus 5 cycles. All other cycles simply yield (SwitchToThread - Windows, sched_yield - POSIX). } TSpinWait = record private const YieldThreshold = 10; Sleep1Threshold = 20; Sleep0Threshold = 5; private FCount: Integer; public procedure Reset; inline; procedure SpinCycle; end; { TSpinLock implements a very simple non-reentrant lock. This lock does not block the calling thread using a synchronization object. Instead it opts to burn a few extra CPU cycles using the above TSpinWait type. This is typically far faster than fully blocking since the length of time the lock is held is relatively few cycles and the thread switching overhead will usually far outpace the few cycles burned by simply spin waiting. } TSpinLock = record private FLock: Integer; public procedure Enter; procedure Exit; end; var FLockCount: Integer; FRecursionCount: Integer; FOwningThread: TThreadID; FLockEvent: Pointer; FSpinCount: Integer; FWaitQueue: PWaitingThread; FQueueLock: TSpinLock; class var CacheLineSize: Integer; class procedure Spin(Iterations: Integer); static; class function GetCacheLineSize: Integer; static; procedure QueueWaiter(var WaitingThread: TWaitingThread); procedure RemoveWaiter(var WaitingThread: TWaitingThread); function DequeueWaiter: PWaitingThread; function GetEvent: Pointer; function CheckOwningThread: TThreadID; class procedure CheckMonitorSupport; static; inline; class function Create: PMonitor; static; private class procedure Destroy(AObject: TObject); overload; static; strict private class function GetFieldAddress(AObject: TObject): PPMonitor; inline; static; class function GetMonitor(AObject: TObject): PMonitor; static; procedure Destroy; overload; function Enter(Timeout: Cardinal): Boolean; overload; procedure Exit; overload; function TryEnter: Boolean; overload; function Wait(ALock: PMonitor; Timeout: Cardinal): Boolean; overload; procedure Pulse; overload; procedure PulseAll; overload; public { In multi-core/multi-processor systems, it is sometimes desirable to spin for a few cycles instead of blocking the current thread when attempting to Enter the monitor. Use SetSpinCount to set a reasonable number of times to spin before fully blocking the thread. This value usually obtained through empirical study of the particular situation. } class procedure SetSpinCount(AObject: TObject; ASpinCount: Integer); static; { Enter locks the monitor object with an optional timeout (in ms) value. Enter without a timeout will wait until the lock is obtained. If the procedure returns it can be assumed that the lock was acquired. Enter with a timeout will return a boolean status indicating whether or not the lock was obtained (True) or the attempt timed out prior to acquire the lock (False). Calling Enter with an INFINITE timeout is the same as calling Enter without a timeout. TryEnter will simply attempt to obtain the lock and return immediately whether or not the lock was acuired. Enter with a 0ms timeout is functionally equivalent to TryEnter. Exit will potentially release the lock acquired by a call to Enter or TryEnter. Since Enter/TryEnter are rentrant, you must balance each of those calls with a corresponding call to Exit. Only the last call to Exit will release the lock and allow other threads to obtain it. Runtime error, reMonitorNoLocked, is generated if Exit is called and the calling thread does not own the lock. } class procedure Enter(AObject: TObject); overload; static; inline; class function Enter(AObject: TObject; Timeout: Cardinal): Boolean; overload; static; class procedure Exit(AObject: TObject); overload; static; class function TryEnter(AObject: TObject): Boolean; overload; static; { Wait will atomically fully release the lock (regardless of the recursion count) and block the calling thread until another thread calls Pulse or PulseAll. The first overloaded Wait function will assume the locked object and wait object are the same and thus the calling thread must own the lock. The second Wait allows the given
C++
struct DECLSPEC_DRECORD TMonitor{ private: struct TWaitingThread; typedef TWaitingThread *PWaitingThread; struct DECLSPEC_DRECORD TWaitingThread { public: TMonitor::TWaitingThread *Next; unsigned Thread; void *WaitEvent; }; struct DECLSPEC_DRECORD TSpinWait { private: static const System::Int8 YieldThreshold = System::Int8(0xa); static const System::Int8 Sleep1Threshold = System::Int8(0x14); static const System::Int8 Sleep0Threshold = System::Int8(0x5); int FCount; public: void __fastcall Reset(void); void __fastcall SpinCycle(void); }; struct DECLSPEC_DRECORD TSpinLock { private: int FLock; public: void __fastcall Enter(void); void __fastcall Exit(void); }; private: int FLockCount; int FRecursionCount; unsigned FOwningThread; void *FLockEvent; int FSpinCount; TWaitingThread *FWaitQueue; TSpinLock FQueueLock; static int CacheLineSize; static void __fastcall Spin(int Iterations); static int __fastcall GetCacheLineSize(); void __fastcall QueueWaiter(TWaitingThread &WaitingThread); void __fastcall RemoveWaiter(TWaitingThread &WaitingThread); PWaitingThread __fastcall DequeueWaiter(void); void * __fastcall GetEvent(void); unsigned __fastcall CheckOwningThread(void); static void __fastcall CheckMonitorSupport(); static PMonitor __fastcall Create(); private: static void __fastcall Destroy(TObject* AObject)/* overload */; private: static PPMonitor __fastcall GetFieldAddress(TObject* AObject); static PMonitor __fastcall GetMonitor(TObject* AObject); void __fastcall Destroy(void)/* overload */; bool __fastcall Enter(unsigned Timeout)/* overload */; void __fastcall Exit(void)/* overload */; bool __fastcall TryEnter(void)/* overload */; bool __fastcall Wait(PMonitor ALock, unsigned Timeout)/* overload */; void __fastcall Pulse(void)/* overload */; void __fastcall PulseAll(void)/* overload */; public: static void __fastcall SetSpinCount(TObject* AObject, int ASpinCount); static void __fastcall Enter(TObject* AObject)/* overload */; static bool __fastcall Enter(TObject* AObject, unsigned Timeout)/* overload */; static void __fastcall Exit(TObject* AObject)/* overload */; static bool __fastcall TryEnter(TObject* AObject)/* overload */; static bool __fastcall Wait(TObject* AObject, unsigned Timeout)/* overload */; static bool __fastcall Wait(TObject* AObject, TObject* ALock, unsigned Timeout)/* overload */; static void __fastcall Pulse(TObject* AObject)/* overload */; static void __fastcall PulseAll(TObject* AObject)/* overload */; };
Eigenschaften
| Typ | Sichtbarkeit | Quelle | Unit | Übergeordnet |
|---|---|---|---|---|
struct class |
public | System.pas System.hpp |
System | System |
Beschreibung
TMonitor stellt Methoden für die Synchronisierung des Zugriffs von mehreren Threads auf ein einzelnes Objekt bereit.
Mit den Klassenmethoden von TMonitor synchronisieren Sie den Zugriff von Threads auf Ressourcen in einer Multithread-Anwendung.