Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type LockPile ¶
type LockPile []lockHandle
LockPile is a list to keep track of locks held by a thread. For every lock, it keeps track of a recursion count, allowing locks that don't support recursion to be acquired multiple times. The underlying lock will only be unlocked if the recursion count reaches zero.
LockPile implements a deadlock avoidance algorithm, ensuring that blocking on a lock is only performed when no other locks are held. What LockPile implements is equivalent to the "Smart" algorithm described on Howard Hinnant's page titled "Dining Philosophers Rebooted":
https://howardhinnant.github.io/dining_philosophers.html
As the set of locks held can be extended over time, there may be a possibility LockPile has to backtrack and temporarily unlock one or more locks it held prior to acquiring more. The caller is signalled when this happens, so that it may revalidate its state. Depending on the state's validity, the caller may either continue or retry.
func (*LockPile) Lock ¶
Lock one or more TryLocker objects, adding them to the LockPile. This function returns true iff it was capable of acquiring all locks without temporarily unlocking one of the existingly owned locks. Regardless of whether this function returns true or false, the same set of locks is held by the calling threads afterwards.
Example usage, of a function that computes the sum of two value nodes in a tree atomically:
func (node *Node) GetSumOfParentAndChild(name string) (int, bool) { lockPile := util.LockPile{} defer lockPile.UnlockAll() lockPile.Lock(&node.lock) // Always returns 'true' for { if child, ok := node.children[name]; !ok { return 0, false } else if lockPile.Lock(&child.lock) { // Successfully acquired child lock without unlocking // the parent. break } else if node.children[name] == child { // Even though the parent was temporarily unlocked, // the parent-child relationship did not change. break } // Race condition during unlock. Retry. lockPile.Unlock(&child.Lock) } return node.value + child.value, true }