Skip to content

Latest commit

 

History

History
1067 lines (765 loc) · 39.3 KB

File metadata and controls

1067 lines (765 loc) · 39.3 KB

xsync

import "github.com/fufuok/utils/xsync"

Index

func ToPlainMap

func ToPlainMap(m *Map) map[string]interface{}

ToPlainMap returns a native map with a copy of xsync Map's contents. The copied xsync Map should not be modified while this call is made. If the copied Map is modified, the copying behavior is the same as in the Range method.

func ToPlainMapOf

func ToPlainMapOf[K comparable, V any](m *MapOf[K, V]) map[K]V

ToPlainMapOf returns a native map with a copy of xsync Map's contents. The copied xsync Map should not be modified while this call is made. If the copied Map is modified, the copying behavior is the same as in the Range method.

func WithGrowOnly

func WithGrowOnly() func(*MapConfig)

WithGrowOnly configures new Map/MapOf instance to be grow-only. This means that the underlying hash table grows in capacity when new keys are added, but does not shrink when keys are deleted. The only exception to this rule is the Clear method which shrinks the hash table back to the initial capacity.

func WithPresize

func WithPresize(sizeHint int) func(*MapConfig)

WithPresize configures new Map/MapOf instance with capacity enough to hold sizeHint entries. The capacity is treated as the minimal capacity meaning that the underlying hash table will never shrink to a smaller capacity. If sizeHint is zero or negative, the value is ignored.

type Counter

A Counter is a striped int64 counter.

Should be preferred over a single atomically updated int64 counter in high contention scenarios.

A Counter must not be copied after first use.

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

func NewCounter

func NewCounter() *Counter

NewCounter creates a new Counter instance.

func (*Counter) Add

func (c *Counter) Add(delta int64)

Add adds the delta to the counter.

func (*Counter) Dec

func (c *Counter) Dec()

Dec decrements the counter by 1.

func (*Counter) Inc

func (c *Counter) Inc()

Inc increments the counter by 1.

func (*Counter) Reset

func (c *Counter) Reset()

Reset resets the counter to zero. This method should only be used when it is known that there are no concurrent modifications of the counter.

func (*Counter) Value

func (c *Counter) Value() int64

Value returns the current counter value. The returned value may not include all of the latest operations in presence of concurrent modifications of the counter.

type HashMapOf

type HashMapOf[K comparable, V any] interface {
    // Load returns the value stored in the map for a key, or nil if no
    // value is present.
    // The ok result indicates whether value was found in the map.
    Load(key K) (value V, ok bool)

    // Store sets the value for a key.
    Store(key K, value V)

    // LoadOrStore returns the existing value for the key if present.
    // Otherwise, it stores and returns the given value.
    // The loaded result is true if the value was loaded, false if stored.
    LoadOrStore(key K, value V) (actual V, loaded bool)

    // LoadAndStore returns the existing value for the key if present,
    // while setting the new value for the key.
    // It stores the new value and returns the existing one, if present.
    // The loaded result is true if the existing value was loaded,
    // false otherwise.
    LoadAndStore(key K, value V) (actual V, loaded bool)

    // LoadOrCompute returns the existing value for the key if present.
    // Otherwise, it computes the value using the provided function and
    // returns the computed value. The loaded result is true if the value
    // was loaded, false if stored.
    LoadOrCompute(key K, valueFn func() V) (actual V, loaded bool)

    // Compute either sets the computed new value for the key or deletes
    // the value for the key. When the delete result of the valueFn function
    // is set to true, the value will be deleted, if it exists. When delete
    // is set to false, the value is updated to the newValue.
    // The ok result indicates whether value was computed and stored, thus, is
    // present in the map. The actual result contains the new value in cases where
    // the value was computed and stored. See the example for a few use cases.
    Compute(
        key K,
        valueFn func(oldValue V, loaded bool) (newValue V, delete bool),
    ) (actual V, ok bool)

    // LoadAndDelete deletes the value for a key, returning the previous
    // value if any. The loaded result reports whether the key was
    // present.
    LoadAndDelete(key K) (value V, loaded bool)

    // Delete deletes the value for a key.
    Delete(key K)

    // Range calls f sequentially for each key and value present in the
    // map. If f returns false, range stops the iteration.
    //
    // Range does not necessarily correspond to any consistent snapshot
    // of the Map's contents: no key will be visited more than once, but
    // if the value for any key is stored or deleted concurrently, Range
    // may reflect any mapping for that key from any point during the
    // Range call.
    //
    // It is safe to modify the map while iterating it. However, the
    // concurrent modification rule apply, i.e. the changes may be not
    // reflected in the subsequently iterated entries.
    Range(f func(key K, value V) bool)

    // Clear deletes all keys and values currently stored in the map.
    Clear()

    // Size returns current size of the map.
    Size() int
}

type MPMCQueue

A MPMCQueue is a bounded multi-producer multi-consumer concurrent queue.

MPMCQueue instances must be created with NewMPMCQueue function. A MPMCQueue must not be copied after first use.

Based on the data structure from the following C++ library: https://github.com/rigtorp/MPMCQueue

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

func NewMPMCQueue

func NewMPMCQueue(capacity int) *MPMCQueue

NewMPMCQueue creates a new MPMCQueue instance with the given capacity.

func (*MPMCQueue) Dequeue

func (q *MPMCQueue) Dequeue() interface{}

Dequeue retrieves and removes the item from the head of the queue. Blocks, if the queue is empty.

Deprecated: use TryDequeue in combination with runtime.Gosched().

func (*MPMCQueue) Enqueue

func (q *MPMCQueue) Enqueue(item interface{})

Enqueue inserts the given item into the queue. Blocks, if the queue is full.

Deprecated: use TryEnqueue in combination with runtime.Gosched().

func (*MPMCQueue) TryDequeue

func (q *MPMCQueue) TryDequeue() (item interface{}, ok bool)

TryDequeue retrieves and removes the item from the head of the queue. Does not block and returns immediately. The ok result indicates that the queue isn't empty and an item was retrieved.

func (*MPMCQueue) TryEnqueue

func (q *MPMCQueue) TryEnqueue(item interface{}) bool

TryEnqueue inserts the given item into the queue. Does not block and returns immediately. The result indicates that the queue isn't full and the item was inserted.

type MPMCQueueOf

A MPMCQueueOf is a bounded multi-producer multi-consumer concurrent queue. It's a generic version of MPMCQueue.

MPMCQueueOf instances must be created with NewMPMCQueueOf function. A MPMCQueueOf must not be copied after first use.

Based on the data structure from the following C++ library: https://github.com/rigtorp/MPMCQueue

type MPMCQueueOf[I any] struct {
    // contains filtered or unexported fields
}

func NewMPMCQueueOf

func NewMPMCQueueOf[I any](capacity int) *MPMCQueueOf[I]

NewMPMCQueueOf creates a new MPMCQueueOf instance with the given capacity.

func (*MPMCQueueOf[I]) Dequeue

func (q *MPMCQueueOf[I]) Dequeue() I

Dequeue retrieves and removes the item from the head of the queue. Blocks, if the queue is empty.

Deprecated: use TryDequeue in combination with runtime.Gosched().

func (*MPMCQueueOf[I]) Enqueue

func (q *MPMCQueueOf[I]) Enqueue(item I)

Enqueue inserts the given item into the queue. Blocks, if the queue is full.

Deprecated: use TryEnqueue in combination with runtime.Gosched().

func (*MPMCQueueOf[I]) TryDequeue

func (q *MPMCQueueOf[I]) TryDequeue() (item I, ok bool)

TryDequeue retrieves and removes the item from the head of the queue. Does not block and returns immediately. The ok result indicates that the queue isn't empty and an item was retrieved.

func (*MPMCQueueOf[I]) TryEnqueue

func (q *MPMCQueueOf[I]) TryEnqueue(item I) bool

TryEnqueue inserts the given item into the queue. Does not block and returns immediately. The result indicates that the queue isn't full and the item was inserted.

type Map

Map is like a Go map[string]interface{} but is safe for concurrent use by multiple goroutines without additional locking or coordination. It follows the interface of sync.Map with a number of valuable extensions like Compute or Size.

A Map must not be copied after first use.

Map uses a modified version of Cache-Line Hash Table (CLHT) data structure: https://github.com/LPD-EPFL/CLHT

CLHT is built around idea to organize the hash table in cache-line-sized buckets, so that on all modern CPUs update operations complete with at most one cache-line transfer. Also, Get operations involve no write to memory, as well as no mutexes or any other sort of locks. Due to this design, in all considered scenarios Map outperforms sync.Map.

One important difference with sync.Map is that only string keys are supported. That's because Golang standard library does not expose the built-in hash functions for interface{} values.

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

func NewMap

func NewMap(options ...func(*MapConfig)) *Map

NewMap creates a new Map instance configured with the given options.

func NewMapPresized

func NewMapPresized(sizeHint int) *Map

NewMapPresized creates a new Map instance with capacity enough to hold sizeHint entries. The capacity is treated as the minimal capacity meaning that the underlying hash table will never shrink to a smaller capacity. If sizeHint is zero or negative, the value is ignored.

Deprecated: use NewMap in combination with WithPresize.

func (*Map) Clear

func (m *Map) Clear()

Clear deletes all keys and values currently stored in the map.

func (*Map) Compute

func (m *Map) Compute(key string, valueFn func(oldValue interface{}, loaded bool) (newValue interface{}, delete bool)) (actual interface{}, ok bool)

Compute either sets the computed new value for the key or deletes the value for the key. When the delete result of the valueFn function is set to true, the value will be deleted, if it exists. When delete is set to false, the value is updated to the newValue. The ok result indicates whether value was computed and stored, thus, is present in the map. The actual result contains the new value in cases where the value was computed and stored. See the example for a few use cases.

This call locks a hash table bucket while the compute function is executed. It means that modifications on other entries in the bucket will be blocked until the valueFn executes. Consider this when the function includes long-running operations.

func (*Map) Delete

func (m *Map) Delete(key string)

Delete deletes the value for a key.

func (*Map) Load

func (m *Map) Load(key string) (value interface{}, ok bool)

Load returns the value stored in the map for a key, or nil if no value is present. The ok result indicates whether value was found in the map.

func (*Map) LoadAndDelete

func (m *Map) LoadAndDelete(key string) (value interface{}, loaded bool)

LoadAndDelete deletes the value for a key, returning the previous value if any. The loaded result reports whether the key was present.

func (*Map) LoadAndStore

func (m *Map) LoadAndStore(key string, value interface{}) (actual interface{}, loaded bool)

LoadAndStore returns the existing value for the key if present, while setting the new value for the key. It stores the new value and returns the existing one, if present. The loaded result is true if the existing value was loaded, false otherwise.

func (*Map) LoadOrCompute

func (m *Map) LoadOrCompute(key string, valueFn func() interface{}) (actual interface{}, loaded bool)

LoadOrCompute returns the existing value for the key if present. Otherwise, it computes the value using the provided function, and then stores and returns the computed value. The loaded result is true if the value was loaded, false if computed.

This call locks a hash table bucket while the compute function is executed. It means that modifications on other entries in the bucket will be blocked until the valueFn executes. Consider this when the function includes long-running operations.

func (*Map) LoadOrStore

func (m *Map) LoadOrStore(key string, value interface{}) (actual interface{}, loaded bool)

LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value. The loaded result is true if the value was loaded, false if stored.

func (*Map) LoadOrTryCompute

func (m *Map) LoadOrTryCompute(key string, valueFn func() (newValue interface{}, cancel bool)) (value interface{}, loaded bool)

LoadOrTryCompute returns the existing value for the key if present. Otherwise, it tries to compute the value using the provided function and, if successful, stores and returns the computed value. The loaded result is true if the value was loaded, or false if computed (whether successfully or not). If the compute attempt was cancelled (due to an error, for example), a nil value will be returned.

This call locks a hash table bucket while the compute function is executed. It means that modifications on other entries in the bucket will be blocked until the valueFn executes. Consider this when the function includes long-running operations.

func (*Map) Range

func (m *Map) Range(f func(key string, value interface{}) bool)

Range calls f sequentially for each key and value present in the map. If f returns false, range stops the iteration.

Range does not necessarily correspond to any consistent snapshot of the Map's contents: no key will be visited more than once, but if the value for any key is stored or deleted concurrently, Range may reflect any mapping for that key from any point during the Range call.

It is safe to modify the map while iterating it, including entry creation, modification and deletion. However, the concurrent modification rule apply, i.e. the changes may be not reflected in the subsequently iterated entries.

func (*Map) Size

func (m *Map) Size() int

Size returns current size of the map.

func (*Map) Stats

func (m *Map) Stats() MapStats

Stats returns statistics for the Map. Just like other map methods, this one is thread-safe. Yet it's an O(N) operation, so it should be used only for diagnostics or debugging purposes.

func (*Map) Store

func (m *Map) Store(key string, value interface{})

Store sets the value for a key.

type MapConfig

MapConfig defines configurable Map/MapOf options.

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

type MapOf

MapOf is like a Go map[K]V but is safe for concurrent use by multiple goroutines without additional locking or coordination. It follows the interface of sync.Map with a number of valuable extensions like Compute or Size.

A MapOf must not be copied after first use.

MapOf uses a modified version of Cache-Line Hash Table (CLHT) data structure: https://github.com/LPD-EPFL/CLHT

CLHT is built around idea to organize the hash table in cache-line-sized buckets, so that on all modern CPUs update operations complete with at most one cache-line transfer. Also, Get operations involve no write to memory, as well as no mutexes or any other sort of locks. Due to this design, in all considered scenarios MapOf outperforms sync.Map.

MapOf also borrows ideas from Java's j.u.c.ConcurrentHashMap (immutable K/V pair structs instead of atomic snapshots) and C++'s absl::flat_hash_map (meta memory and SWAR-based lookups).

type MapOf[K comparable, V any] struct {
    // contains filtered or unexported fields
}

func NewMapOf

func NewMapOf[K comparable, V any](options ...func(*MapConfig)) *MapOf[K, V]

NewMapOf creates a new MapOf instance configured with the given options.

func NewMapOfPresized

func NewMapOfPresized[K comparable, V any](sizeHint int) *MapOf[K, V]

NewMapOfPresized creates a new MapOf instance with capacity enough to hold sizeHint entries. The capacity is treated as the minimal capacity meaning that the underlying hash table will never shrink to a smaller capacity. If sizeHint is zero or negative, the value is ignored.

Deprecated: use NewMapOf in combination with WithPresize.

func NewMapOfWithHasher

func NewMapOfWithHasher[K comparable, V any](hasher func(K, uint64) uint64, options ...func(*MapConfig)) *MapOf[K, V]

NewMapOfWithHasher creates a new MapOf instance configured with the given hasher and options. The hash function is used instead of the built-in hash function configured when a map is created with the NewMapOf function.

func (*MapOf[K, V]) Clear

func (m *MapOf[K, V]) Clear()

Clear deletes all keys and values currently stored in the map.

func (*MapOf[K, V]) Compute

func (m *MapOf[K, V]) Compute(key K, valueFn func(oldValue V, loaded bool) (newValue V, delete bool)) (actual V, ok bool)

Compute either sets the computed new value for the key or deletes the value for the key. When the delete result of the valueFn function is set to true, the value will be deleted, if it exists. When delete is set to false, the value is updated to the newValue. The ok result indicates whether value was computed and stored, thus, is present in the map. The actual result contains the new value in cases where the value was computed and stored. See the example for a few use cases.

This call locks a hash table bucket while the compute function is executed. It means that modifications on other entries in the bucket will be blocked until the valueFn executes. Consider this when the function includes long-running operations.

Example

package main

import (
	"errors"
	"fmt"

	"github.com/fufuok/utils/xsync"
)

func main() {
	counts := xsync.NewMapOf[int, int]()

	// Store a new value.
	v, ok := counts.Compute(42, func(oldValue int, loaded bool) (newValue int, delete bool) {
		// loaded is false here.
		newValue = 42
		delete = false
		return
	})
	// v: 42, ok: true
	fmt.Printf("v: %v, ok: %v\n", v, ok)

	// Update an existing value.
	v, ok = counts.Compute(42, func(oldValue int, loaded bool) (newValue int, delete bool) {
		// loaded is true here.
		newValue = oldValue + 42
		delete = false
		return
	})
	// v: 84, ok: true
	fmt.Printf("v: %v, ok: %v\n", v, ok)

	// Set a new value or keep the old value conditionally.
	var oldVal int
	minVal := 63
	v, ok = counts.Compute(42, func(oldValue int, loaded bool) (newValue int, delete bool) {
		oldVal = oldValue
		if !loaded || oldValue < minVal {
			newValue = minVal
			delete = false
			return
		}
		newValue = oldValue
		delete = false
		return
	})
	// v: 84, ok: true, oldVal: 84
	fmt.Printf("v: %v, ok: %v, oldVal: %v\n", v, ok, oldVal)

	// Delete an existing value.
	v, ok = counts.Compute(42, func(oldValue int, loaded bool) (newValue int, delete bool) {
		// loaded is true here.
		delete = true
		return
	})
	// v: 84, ok: false
	fmt.Printf("v: %v, ok: %v\n", v, ok)

	// Propagate an error from the compute function to the outer scope.
	var err error
	v, ok = counts.Compute(42, func(oldValue int, loaded bool) (newValue int, delete bool) {
		if oldValue == 42 {
			err = errors.New("something went wrong")
			return 0, true // no need to create a key/value pair
		}
		newValue = 0
		delete = false
		return
	})
	fmt.Printf("err: %v\n", err)
}

func (*MapOf[K, V]) Delete

func (m *MapOf[K, V]) Delete(key K)

Delete deletes the value for a key.

func (*MapOf[K, V]) Load

func (m *MapOf[K, V]) Load(key K) (value V, ok bool)

Load returns the value stored in the map for a key, or zero value of type V if no value is present. The ok result indicates whether value was found in the map.

func (*MapOf[K, V]) LoadAndDelete

func (m *MapOf[K, V]) LoadAndDelete(key K) (value V, loaded bool)

LoadAndDelete deletes the value for a key, returning the previous value if any. The loaded result reports whether the key was present.

func (*MapOf[K, V]) LoadAndStore

func (m *MapOf[K, V]) LoadAndStore(key K, value V) (actual V, loaded bool)

LoadAndStore returns the existing value for the key if present, while setting the new value for the key. It stores the new value and returns the existing one, if present. The loaded result is true if the existing value was loaded, false otherwise.

func (*MapOf[K, V]) LoadOrCompute

func (m *MapOf[K, V]) LoadOrCompute(key K, valueFn func() V) (actual V, loaded bool)

LoadOrCompute returns the existing value for the key if present. Otherwise, it computes the value using the provided function, and then stores and returns the computed value. The loaded result is true if the value was loaded, false if computed.

This call locks a hash table bucket while the compute function is executed. It means that modifications on other entries in the bucket will be blocked until the valueFn executes. Consider this when the function includes long-running operations.

func (*MapOf[K, V]) LoadOrStore

func (m *MapOf[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool)

LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value. The loaded result is true if the value was loaded, false if stored.

func (*MapOf[K, V]) LoadOrTryCompute

func (m *MapOf[K, V]) LoadOrTryCompute(key K, valueFn func() (newValue V, cancel bool)) (value V, loaded bool)

LoadOrTryCompute returns the existing value for the key if present. Otherwise, it tries to compute the value using the provided function and, if successful, stores and returns the computed value. The loaded result is true if the value was loaded, or false if computed (whether successfully or not). If the compute attempt was cancelled (due to an error, for example), a zero value of type V will be returned.

This call locks a hash table bucket while the compute function is executed. It means that modifications on other entries in the bucket will be blocked until the valueFn executes. Consider this when the function includes long-running operations.

func (*MapOf[K, V]) Range

func (m *MapOf[K, V]) Range(f func(key K, value V) bool)

Range calls f sequentially for each key and value present in the map. If f returns false, range stops the iteration.

Range does not necessarily correspond to any consistent snapshot of the Map's contents: no key will be visited more than once, but if the value for any key is stored or deleted concurrently, Range may reflect any mapping for that key from any point during the Range call.

It is safe to modify the map while iterating it, including entry creation, modification and deletion. However, the concurrent modification rule apply, i.e. the changes may be not reflected in the subsequently iterated entries.

func (*MapOf[K, V]) Size

func (m *MapOf[K, V]) Size() int

Size returns current size of the map.

func (*MapOf[K, V]) Stats

func (m *MapOf[K, V]) Stats() MapStats

Stats returns statistics for the MapOf. Just like other map methods, this one is thread-safe. Yet it's an O(N) operation, so it should be used only for diagnostics or debugging purposes.

func (*MapOf[K, V]) Store

func (m *MapOf[K, V]) Store(key K, value V)

Store sets the value for a key.

type MapStats

MapStats is Map/MapOf statistics.

Warning: map statistics are intented to be used for diagnostic purposes, not for production code. This means that breaking changes may be introduced into this struct even between minor releases.

type MapStats struct {
    // RootBuckets is the number of root buckets in the hash table.
    // Each bucket holds a few entries.
    RootBuckets int
    // TotalBuckets is the total number of buckets in the hash table,
    // including root and their chained buckets. Each bucket holds
    // a few entries.
    TotalBuckets int
    // EmptyBuckets is the number of buckets that hold no entries.
    EmptyBuckets int
    // Capacity is the Map/MapOf capacity, i.e. the total number of
    // entries that all buckets can physically hold. This number
    // does not consider the load factor.
    Capacity int
    // Size is the exact number of entries stored in the map.
    Size int
    // Counter is the number of entries stored in the map according
    // to the internal atomic counter. In case of concurrent map
    // modifications this number may be different from Size.
    Counter int
    // CounterLen is the number of internal atomic counter stripes.
    // This number may grow with the map capacity to improve
    // multithreaded scalability.
    CounterLen int
    // MinEntries is the minimum number of entries per a chain of
    // buckets, i.e. a root bucket and its chained buckets.
    MinEntries int
    // MinEntries is the maximum number of entries per a chain of
    // buckets, i.e. a root bucket and its chained buckets.
    MaxEntries int
    // TotalGrowths is the number of times the hash table grew.
    TotalGrowths int64
    // TotalGrowths is the number of times the hash table shrinked.
    TotalShrinks int64
}

func (*MapStats) ToString

func (s *MapStats) ToString() string

ToString returns string representation of map stats.

type RBMutex

A RBMutex is a reader biased reader/writer mutual exclusion lock. The lock can be held by an many readers or a single writer. The zero value for a RBMutex is an unlocked mutex.

A RBMutex must not be copied after first use.

RBMutex is based on a modified version of BRAVO (Biased Locking for Reader-Writer Locks) algorithm: https://arxiv.org/pdf/1810.01553.pdf

RBMutex is a specialized mutex for scenarios, such as caches, where the vast majority of locks are acquired by readers and write lock acquire attempts are infrequent. In such scenarios, RBMutex performs better than sync.RWMutex on large multicore machines.

RBMutex extends sync.RWMutex internally and uses it as the "reader bias disabled" fallback, so the same semantics apply. The only noticeable difference is in reader tokens returned from the RLock/RUnlock methods.

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

func NewRBMutex

func NewRBMutex() *RBMutex

NewRBMutex creates a new RBMutex instance.

func (*RBMutex) Lock

func (mu *RBMutex) Lock()

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

func (*RBMutex) RLock

func (mu *RBMutex) RLock() *RToken

RLock locks m for reading and returns a reader token. The token must be used in the later RUnlock call.

Should not be used for recursive read locking; a blocked Lock call excludes new readers from acquiring the lock.

func (*RBMutex) RUnlock

func (mu *RBMutex) RUnlock(t *RToken)

RUnlock undoes a single RLock call. A reader token obtained from the RLock call must be provided. RUnlock does not affect other simultaneous readers. A panic is raised if m is not locked for reading on entry to RUnlock.

func (*RBMutex) TryLock

func (mu *RBMutex) TryLock() bool

TryLock tries to lock m for writing without blocking.

func (*RBMutex) TryRLock

func (mu *RBMutex) TryRLock() (bool, *RToken)

TryRLock tries to lock m for reading without blocking. When TryRLock succeeds, it returns true and a reader token. In case of a failure, a false is returned.

func (*RBMutex) Unlock

func (mu *RBMutex) Unlock()

Unlock unlocks m for writing. A panic is raised if m is not locked for writing on entry to Unlock.

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

type RToken

RToken is a reader lock token.

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

type SPSCQueue

A SPSCQueue is a bounded single-producer single-consumer concurrent queue. This means that not more than a single goroutine must be publishing items to the queue while not more than a single goroutine must be consuming those items.

SPSCQueue instances must be created with NewSPSCQueue function. A SPSCQueue must not be copied after first use.

Based on the data structure from the following article: https://rigtorp.se/ringbuffer/

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

func NewSPSCQueue

func NewSPSCQueue(capacity int) *SPSCQueue

NewSPSCQueue creates a new SPSCQueue instance with the given capacity.

func (*SPSCQueue) TryDequeue

func (q *SPSCQueue) TryDequeue() (item interface{}, ok bool)

TryDequeue retrieves and removes the item from the head of the queue. Does not block and returns immediately. The ok result indicates that the queue isn't empty and an item was retrieved.

func (*SPSCQueue) TryEnqueue

func (q *SPSCQueue) TryEnqueue(item interface{}) bool

TryEnqueue inserts the given item into the queue. Does not block and returns immediately. The result indicates that the queue isn't full and the item was inserted.

type SPSCQueueOf

A SPSCQueueOf is a bounded single-producer single-consumer concurrent queue. This means that not more than a single goroutine must be publishing items to the queue while not more than a single goroutine must be consuming those items.

SPSCQueueOf instances must be created with NewSPSCQueueOf function. A SPSCQueueOf must not be copied after first use.

Based on the data structure from the following article: https://rigtorp.se/ringbuffer/

type SPSCQueueOf[I any] struct {
    // contains filtered or unexported fields
}

func NewSPSCQueueOf

func NewSPSCQueueOf[I any](capacity int) *SPSCQueueOf[I]

NewSPSCQueueOf creates a new SPSCQueueOf instance with the given capacity.

func (*SPSCQueueOf[I]) TryDequeue

func (q *SPSCQueueOf[I]) TryDequeue() (item I, ok bool)

TryDequeue retrieves and removes the item from the head of the queue. Does not block and returns immediately. The ok result indicates that the queue isn't empty and an item was retrieved.

func (*SPSCQueueOf[I]) TryEnqueue

func (q *SPSCQueueOf[I]) TryEnqueue(item I) bool

TryEnqueue inserts the given item into the queue. Does not block and returns immediately. The result indicates that the queue isn't full and the item was inserted.

Generated by gomarkdoc