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-TYPEhzLockRWD(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-TYPEhzLockRWD(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_tGranted(void)
uint64_tInuse(void)
voidKill(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_tLevel(void)
hzEcodeLockRead(int32_t nTries)Obtain a read lock on a resource. This is only spin if there is a write lock in place.
hzEcodeLockWrite(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)
hzEcodeSetname(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_tSpinThis(void)
uint64_tSpinTotal(void)
uint32_tThread(void)
uint32_tTriesThis(void)
uint32_tTriesTotal(void)
uint32_tUID(void)
voidUnlock(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_tWaitThis(void)
uint64_tWaitTotal(void)

Overloaded operators:

hzLockRWD&operator=(hzLockRWD& op)

Member Variables:

uint64_tm_GrantedTime mutex was last granted. Used to calculate both in-use and wait time
uint16_tm_IdUnique id
uint64_tm_InuseTotal time lock was in-use (a thread had write access)
uint32_tm_LockOpsRTotal lock operations (read)
uint32_tm_LockOpsWTotal lock operations (write)
uint32_tm_SpinsThisSpins before current lock granted
uint64_tm_SpinsTotalRuntime total spins on the lock by all waiting threads
uint32_tm_TriesThisNumber of compare and swap calls before lock granted
uint64_tm_TriesTotalRuntime total number of compare and swap calls
uint32_tm_UnlocksUnlocks operations (should equal the total of read and write lock operations)
uint64_tm_WaitThisTime mutex was last granted. Used to calculate both in-use and wait time
uint64_tm_WaitTotalTotal time thread waited for access (either for read or write)
uint32_tm_counterThe read lock counter
uint32_tm_lockvalThe lock itself - set to 0 or thread id that has the lock
char*m_nameName for diagnostics. Note limited to a fixed buffer to allow mutex initialization within the hzHeap regime
uint16_tm_recurseRecursion count
hzLockRWD*nextFor accomodation in an explicit linked list and mutex internal instances
hzLockRWD*prevFor accomodation in an explicit linked list and mutex internal instances