Skip to content

Low (and high)-level TMonitor improvements.

Rika requested to merge runewalsh/source:tmonitor into main
  1. Change SetMonitorData to InterlockedTrySetMonitorData (can be named less Java EE style...) InterlockedCompareExchangeMonitorData (this style is probably required over TrySet... : boolean to be able to free TMonitorData early, should the urge ever arise) and remove global _MemLock.

  2. LockCount does not require atomic operations, they are already performed under the lock, and the check GetCurrentThreadId = LockOwnerThreadID passes if and only if current thread holds the lock. If current thread does not hold the lock, LockOwnerThreadID can only visibly change from one value not equal to GetCurrentThreadId to another value not equal to GetCurrentThreadId. (While we at it: TryEnter is incorrect, it does not increment LockCount on succesful recursive acquisitions.)

  3. Since TPulseData-related structures are “transient” in their nature (TPulseData exists only during corresponding Wait call), they can be assembled into a linked list of structures allocated in Wait stack frames of waiting threads. This may sound exotic and dangerous, but is in practice simpler and more reliable (does not require any kind of search and TPulseData.Match, and cannot throw OOM in the middle of Wait) than current implementation.

  4. TMonitor.Wait must temporarily unlock through any amount of recursive acquisitions!

Two Three more notes:

  1. I just hope this entire thing is not going to be compiled into every application at any point in the future, right? (Right now it is not, but eg threading is, because of TThreadManager; cf TMonitorManager).

  2. Starting from Windows Vista, there are SRW locks and condition variables (and starting from Windows 8, there are WaitOnAddress, WakeByAddressSingle, and WakeByAddressAll, but not sure about their usage here). They implement most of TMonitor (with no guarantees about fairness or FIFO, but, ugh...) and are well worth a separate far simpler and far more efficient TMonitor implementation chosen at runtime.

  3. Timeouted Enter must be implemented with an event, but I don’t want to think how exactly. For now, spin-wait a while, ThreadSwitch a while, and then progressively Sleep.

Merge request reports