syncutils

package
v0.1.11 Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2023 License: Apache-2.0, BSD-2-Clause Imports: 11 Imported by: 3

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Counter

type Counter struct {
	// contains filtered or unexported fields
}

func NewCounter

func NewCounter() (newCounter *Counter)

func (*Counter) Decrease

func (c *Counter) Decrease() (newValue int)

func (*Counter) Get

func (c *Counter) Get() (value int)

func (*Counter) Increase

func (c *Counter) Increase() (newValue int)

func (*Counter) Set

func (c *Counter) Set(newValue int) (oldValue int)

func (*Counter) Subscribe

func (c *Counter) Subscribe(subscribers ...func(oldValue, newValue int)) (unsubscribe func())

func (*Counter) Update

func (c *Counter) Update(delta int) (newValue int)

func (*Counter) WaitIsAbove

func (c *Counter) WaitIsAbove(threshold int)

func (*Counter) WaitIsBelow

func (c *Counter) WaitIsBelow(threshold int)

func (*Counter) WaitIsZero

func (c *Counter) WaitIsZero()

type DAGMutex

type DAGMutex[T comparable] struct {
	sync.Mutex
	// contains filtered or unexported fields
}

DAGMutex is a multi-entity reader/writer mutual exclusion lock that allows for starvation. Entities can be registered dynamically by providing a comparable identifier. The structure and relation of these entities MUST NOT contain any cycles as this may lead to deadlocks while waiting to acquire locks cyclically.

Entities can be Lock-ed one at a time. The call blocks until the lock for this entity can be acquired. Entities can be RLock-ed multiple in arbitrary order. The call blocks until all read locks can be acquired.

Consider the following example of a DAG with 3 entities A,B,C. ┌───┬─┐ │ │B◄─┐ ┌▼┐ └─┘ │ │A│ │ └▲┘ ┌┴┐ │ │C│ └──────┴─┘

Let's assume the following 3 goroutines are competing for access. Time is advancing with every row. Goroutine 1 Goroutine 2 Goroutine 3

  Lock(A)           		-         RLock(A,B) <- blocking, not able to acquire locks
     work            Lock(B)   	        wait
Unlock(A)               work   	        wait
        -          Unlock(B)   	        wait <- (internally) now RLock(A) is successful, but still waiting for B
        -                  -   	 RLock(A, B) <- successful acquired, holding the locks now

func NewDAGMutex

func NewDAGMutex[T comparable]() *DAGMutex[T]

NewDAGMutex creates a new DAGMutex.

func (*DAGMutex[T]) Lock

func (d *DAGMutex[T]) Lock(id T)

Lock locks the given entity for writing. If the lock is already locked for reading or writing, Lock blocks until the lock is available.

func (*DAGMutex[T]) RLock

func (d *DAGMutex[T]) RLock(ids ...T)

RLock locks all given entities for reading. It blocks until all read locks can be acquired.

It should not be used for recursive read locking. A blocked Lock call DOES NOT exclude new readers from acquiring the lock. Hence, it is starving.

func (*DAGMutex[T]) RUnlock

func (d *DAGMutex[T]) RUnlock(ids ...T)

RUnlock unlocks reading for all given entities. It does not affect other simultaneous readers.

func (*DAGMutex[T]) Unlock

func (d *DAGMutex[T]) Unlock(id T)

Unlock unlocks the given entity for writing.

As with Mutexes, a locked DAGMutex is not associated with a particular goroutine. One goroutine may RLock (Lock) an entity within DAGMutex and then arrange for another goroutine to RUnlock (Unlock) it.

type KRWMutex

type KRWMutex struct {
	// contains filtered or unexported fields
}

func NewKRWMutex

func NewKRWMutex() *KRWMutex

func (*KRWMutex) Free

func (k *KRWMutex) Free(key interface{})

func (*KRWMutex) Register

func (k *KRWMutex) Register(key interface{}) (result *RWMutex)

type LockableEntity

type LockableEntity interface {
	// Locks returns the locks that the entity needs to lock.
	Locks() (locks []interface{})
}

LockableEntity is an interface that allows to lock (and unlock) entities that are generating complex locks.

type MultiMutex

type MultiMutex struct {
	// contains filtered or unexported fields
}

MultiMutex is a mutex that allows to lock multiple entities exclusively. Entities are represented by interface{} identifiers and can be presented in arbitrary order. Goroutine 1 Goroutine 2 Goroutine 3

Lock(a,c)           		-          Lock(c,b) <- blocking
     work            Lock(b)   	        wait

Unlock(a,c) work wait

  • Unlock(b) wait
  • - Lock(c,b) <- successful

func NewMultiMutex

func NewMultiMutex() *MultiMutex

NewMultiMutex creates a new MultiMutex.

func (*MultiMutex) Lock

func (m *MultiMutex) Lock(ids ...interface{})

Lock blocks until all locks given by ids can be acquired atomically.

func (*MultiMutex) LockEntity

func (m *MultiMutex) LockEntity(entity LockableEntity)

LockEntity locks all locks that are required for the given LockableEntity.

func (*MultiMutex) Unlock

func (m *MultiMutex) Unlock(ids ...interface{})

Unlock releases the locks of ids.

func (*MultiMutex) UnlockEntity

func (m *MultiMutex) UnlockEntity(entity LockableEntity)

UnlockEntity unlocks all locks that are required for the given LockableEntity.

type MultiMutexLockBuilder

type MultiMutexLockBuilder struct {
	// contains filtered or unexported fields
}

func (*MultiMutexLockBuilder) AddLock

func (lockBuilder *MultiMutexLockBuilder) AddLock(identifier interface{}) *MultiMutexLockBuilder

func (*MultiMutexLockBuilder) Build

func (lockBuilder *MultiMutexLockBuilder) Build() []interface{}

type Mutex

type Mutex = sync.Mutex

type RWMultiMutex

type RWMultiMutex struct {
	// contains filtered or unexported fields
}

func (*RWMultiMutex) Lock

func (mutex *RWMultiMutex) Lock(identifiers ...interface{})

func (*RWMultiMutex) RLock

func (mutex *RWMultiMutex) RLock(identifiers ...interface{})

func (*RWMultiMutex) RUnlock

func (mutex *RWMultiMutex) RUnlock(identifiers ...interface{})

func (*RWMultiMutex) Unlock

func (mutex *RWMultiMutex) Unlock(identifiers ...interface{})

type RWMutex

type RWMutex = sync.RWMutex

type Stack

type Stack[T any] struct {
	// contains filtered or unexported fields
}

func NewStack

func NewStack[T any]() (newStack *Stack[T])

func (*Stack[T]) Pop

func (b *Stack[T]) Pop() (element T, success bool)

func (*Stack[T]) PopOrWait

func (b *Stack[T]) PopOrWait(waitCondition func() bool) (element T, success bool)

func (*Stack[T]) Push

func (b *Stack[T]) Push(task T)

func (*Stack[T]) SignalShutdown

func (b *Stack[T]) SignalShutdown()

func (*Stack[T]) Size

func (b *Stack[T]) Size() int

func (*Stack[T]) WaitIsEmpty

func (b *Stack[T]) WaitIsEmpty()

func (*Stack[T]) WaitSizeIsAbove

func (b *Stack[T]) WaitSizeIsAbove(threshold int)

func (*Stack[T]) WaitSizeIsBelow

func (b *Stack[T]) WaitSizeIsBelow(threshold int)

type StarvingMutex

type StarvingMutex struct {
	// contains filtered or unexported fields
}

A StarvingMutex is a reader/writer mutual exclusion lock that allows for starvation of readers or writers by first prioritizing any outstanding reader or writer depending on the current mode (continue reading or continue writing). The lock can be held by an arbitrary number of readers or a single writer. The zero value for a StarvingMutex is an unlocked mutex.

A StarvingMutex must not be copied after first use.

If a goroutine holds a StarvingMutex for reading and another goroutine might call Lock, other goroutines can acquire a read lock. This allows recursive read locking. However, this can result in starvation of goroutines that tried to acquire write lock on the mutex. A blocked Lock call does not exclude new readers from acquiring the lock.

func NewStarvingMutex

func NewStarvingMutex() *StarvingMutex

NewStarvingMutex creates a new StarvingMutex.

func (*StarvingMutex) Lock

func (f *StarvingMutex) Lock()

Lock locks starving mutex for writing. If the lock is already locked for reading or writing, Lock blocks until the lock is available.

If there are waiting writers these will be served first before ANY reader can read again. Hence, it is starving.

func (*StarvingMutex) RLock

func (f *StarvingMutex) RLock()

RLock locks starving mutex for reading.

It should not be used for recursive read locking. A blocked Lock call DOES NOT exclude new readers from acquiring the lock. Hence, it is starving.

func (*StarvingMutex) RUnlock

func (f *StarvingMutex) RUnlock()

RUnlock undoes a single RLock call; it does not affect other simultaneous readers. It is a run-time error if mutex is not locked for reading on entry to RUnlock.

func (*StarvingMutex) String

func (f *StarvingMutex) String() (humanReadable string)

String returns a string representation of the StarvingMutex.

func (*StarvingMutex) Unlock

func (f *StarvingMutex) Unlock()

Unlock unlocks starving mutex for writing. It is a run-time error if mutex is not locked for writing on entry to Unlock.

As with Mutexes, a locked StarvingMutex is not associated with a particular goroutine. One goroutine may RLock (Lock) a StarvingMutex and then arrange for another goroutine to RUnlock (Unlock) it.

Jump to

Keyboard shortcuts

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