Defined in file: hzLock.h
Derivative of: hzLocker
hzLockRWD is a resource lock effected as a 'wrapper' based on a single mutex. The lock is granted to the first thread that requests it and until the winning thread releases the lock, all other threads seeking the lock have to wait. Mutex locks can be blocking or non-blocking. When blockng, all waiting threads are suspended. The CPU performs a context switch (swaps out the current thread and runs another in its place). When non-blocking the waiting threads loop or 'spin', constantly testing if the lock has become available and then seeking the look. This spinning only stops when the lock is granted. Both blocking and non-blocking locks can be subjected to a timeout but if they are, the calling thread must be able to contend with being denied access to the resource controlled by the lock. While spining round a loop is clearly a waste of time, it should be noted that thread suspension is also a waste of time - and in the general case, a much worse waste of time. Context switching is very expensive. For this reason the decision was taken that hzLockRWD should not support blocking. So hzLockRWD Lock() method never blocks and hzLockRWD is exclusively a spinlock. The Lock() method has a single optional argument of timeout (as an integer number of milliseconds), with a default of -1 (not applicable). A timeout of zero will try for a lock but imeadiately return with or without it. The return is E_OK for lock granted, but also E_OK if the lock is not initialized (not made active). If the timeout expires E_TIMEOUT is returned. Note that outside these circumstances, Lock() won't return! The purpose of the hzLockRWD class is essentially diagnostic - as otherwise a mutex is too simple to require a wrapper! hzLockRWD keeps track of contentions and of time wasted by those contentions. To this end, hzLockRWD instances must be named, either by passing a hzString or char* to the constructor or later with a call to the Init() method. Indeed without being named, a hzLockRWD is inactive and does not lock anything. The global function ContentionReport(hzChain& Z) reports on contentions of all mutexes and adds up time wasted in spinlocks by all threads.
Constructors/Detructors
| hzLockRWD* | hzLockRWD | (hzLockRWD& op) | |
| hzLockRWD* | hzLockRWD | (void) | |
| hzLockRWD* | hzLockRWD | (const char* name) | |
| NULL-TYPE | hzLockRWD | (void) | hzLockRWD default constructor. Note that this assigns the mutex internal structure using malloc in order to avoid using new which is overloaded and itself controlled by a mutex etc! Arguments: None |
| NULL-TYPE | hzLockRWD | (const char* name) | hzLockRWD default constructor but with name supplied for diagnostic purposes. |
| void | ~hzLockRWD | (void) | |
| NULL-TYPE | ~hzLockRWD | (void) | hzLockRWD destructor. Arguments: None |
Public Methods:
| void* | Address | (void) | |
| uint64_t | Granted | (void) | |
| uint64_t | Inuse | (void) | |
| void | Kill | (void) | Kill a lock (signal that the resouce controlled by the lock is to be deleted). The calling thread must hold the write lock. This function will terminate the program if this is not the case or if the lock has already been killed. Arguments: None Returns: None |
| uint32_t | Level | (void) | |
| hzEcode | LockRead | (int32_t nTries) | Obtain a read lock on a resource. This is only spin if there is a write lock in place. |
| hzEcode | LockWrite | (int32_t timeout) | Obtain a write lock on a resource. This will spin until either the lock is granted or the lock is deactivated (host entity destructed). And then spin until the read count falls to zero. This latter step ensures no thread can read the resource during a write. |
| const char* | Name | (void) | |
| hzEcode | Setname | (const char* name) | Set diagnostic name on lock as an explicit step. This can only be done once. Subsequent calls will have no effect |
| uint32_t | SpinThis | (void) | |
| uint64_t | SpinTotal | (void) | |
| uint32_t | Thread | (void) | |
| uint32_t | TriesThis | (void) | |
| uint32_t | TriesTotal | (void) | |
| uint32_t | UID | (void) | |
| void | Unlock | (void) | Release a lock on a resource Arguments: None Returns: None Note this operation terminates execution if the current thread is trying to unlock a resource that is locked by another thread or not locked at all |
| uint64_t | WaitThis | (void) | |
| uint64_t | WaitTotal | (void) |
Overloaded operators:
| hzLockRWD& | operator= | (hzLockRWD& op) |
Member Variables:
| uint64_t | m_Granted | Time mutex was last granted. Used to calculate both in-use and wait time | |
| uint16_t | m_Id | Unique id | |
| uint64_t | m_Inuse | Total time lock was in-use (a thread had write access) | |
| uint32_t | m_LockOpsR | Total lock operations (read) | |
| uint32_t | m_LockOpsW | Total lock operations (write) | |
| uint32_t | m_SpinsThis | Spins before current lock granted | |
| uint64_t | m_SpinsTotal | Runtime total spins on the lock by all waiting threads | |
| uint32_t | m_TriesThis | Number of compare and swap calls before lock granted | |
| uint64_t | m_TriesTotal | Runtime total number of compare and swap calls | |
| uint32_t | m_Unlocks | Unlocks operations (should equal the total of read and write lock operations) | |
| uint64_t | m_WaitThis | Time mutex was last granted. Used to calculate both in-use and wait time | |
| uint64_t | m_WaitTotal | Total time thread waited for access (either for read or write) | |
| uint32_t | m_counter | The read lock counter | |
| uint32_t | m_lockval | The lock itself - set to 0 or thread id that has the lock | |
| char* | m_name | Name for diagnostics. Note limited to a fixed buffer to allow mutex initialization within the hzHeap regime | |
| uint16_t | m_recurse | Recursion count | |
| hzLockRWD* | next | For accomodation in an explicit linked list and mutex internal instances | |
| hzLockRWD* | prev | For accomodation in an explicit linked list and mutex internal instances |