sync

package
v0.0.0-...-88aba65 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2024 License: Apache-2.0 Imports: 1 Imported by: 0

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

func (lp *LockPile) Lock(newLocks ...TryLocker) bool

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
}

func (*LockPile) Unlock

func (lp *LockPile) Unlock(oldLock TryLocker)

Unlock a TryLocker object, removing it from the LockPile.

func (*LockPile) UnlockAll

func (lp *LockPile) UnlockAll()

UnlockAll unlocks all locks associated with a LockPile. Calling this function using 'defer' ensures that no locks remain acquired after the calling function returns.

type TryLocker

type TryLocker interface {
	sync.Locker
	TryLock() bool
}

TryLocker represents a lock type that can both be acquired in a blocking and non-blocking fashion.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL