syncutils

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2025 License: MIT Imports: 4 Imported by: 0

README ΒΆ

syncutils

license release badge badge badge

This package provides thread-safe data structures and other utilities for working with concurrency.

😎 Features:

  • Type-safe, thanks to generics
  • Zero-dependency

1.1. πŸ“¦ Installation

go get github.com/esome/golang-sync

1.2. πŸ› οΈ Usage

1.2.1. syncutils.Slice

Slice is a thread-safe wrapper around a slice. It provides all methods needed to manipulate the slice in a thread-safe way. For that matter it uses a sync.Mutex for locking purposes and uses the Go 1.21 slices package for changing the slice.

import "github.com/esome/golang-sync"

var s1 Slice[string]           // thread-safe nil []string slice  
s2 := NewSlice[string](10)     // thread-safe variant of make([]string, 10)
s3 := NewSlice[string](0, 10)  // thread-safe variant of make([]string, 0, 10)

s1.Append("a", "b", "c")       // appends multiple elements
s1.Replace(1, 2, "d")          // replaces multiple elements - results in ["a", "d"]

for range s1.Iter() {          // iterates over the slice in a thread-safe non-blocking way
    // do something            // for that matter, the slice might be changed during the iteration, 
}                              // and the elements do not necessarily reflect any consistent state of the slice    
1.2.2. syncutils.Map

Map is a thread-safe wrapper around a map. It provides all methods needed to manipulate the map in a thread-safe way. For that matter it uses a sync.Mutex for locking purposes.

import "github.com/esome/golang-sync"

var m1 Map[string, string]        // thread-safe map[string]string  
m2 := NewMap[string, string](10)  // thread-safe variant of make(map[string]string, 10)

m1.Store("foo", "bar")                // same as m1["foo"] = "bar"
v, ok := m1.Load("foo")               // same as v, ok := m1["foo"]
v, ok := m1.LoadOrStore("foo", "baz") // read value of m1["foo"]. When not found store "baz" and return it 
v, ok := m1.LoadAndDelete("foo")      // removes the value and returns it

for range m1.Iter() {            // iterates over the map in a thread-safe non-blocking way
    // do something              // for that matter, the map might be changed during the iteration, 
}                                // and the elements do not necessarily reflect any consistent state of the map
1.2.3. syncutils.MapCmp

MapCmp extends the Map type with utility methods for deleting or swapping values only when the current value matches an expected one. For this to be possible, the value type must be comparable.

import "github.com/esome/golang-sync"

var m1 MapCmp[string, string]        // thread-safe map[string]string  

m1.Store("foo", "bar")              // same as m1["foo"] = "bar"
v, ok := m1.Load("foo")             // same as v, ok := m1["foo"]

m1.SwapIfEqual("foo", "baz", "bar") // swaps the value only if it is "bar"
m1.DeleteIfEqual("foo", "bar")      // deletes the value only if it is "bar"
1.2.4. channels package

The channels package provides a set of utilities for working with channels. Please refer to the docs, to learn more about the available functions.

import (
    "context"
    
    "github.com/esome/golang-sync/channels"
)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

ints := make(chan int)  
err := channels.Send(ctx, ints, 1, 2, 3, 4)  // sends values to the channel, returns an error if the context is done

recv1, recv2 := make(chan int), make(chan int)   
err := channels.Broadcast(ctx, ints, recv1, recv2)    // broadcasts each value from the ints channel to every recv* channel

// wraps a channel with a function that transforms the values
// uints is of type (<-chan uint) and contains the transformed values
uints := channels.Wrap(ctx, ints, func(_ context.Context, i int) ) (uint, bool) {
	return uint(i), i >= 0 // avoid overflow - if false, the value is skipped
})

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

This section is empty.

Types ΒΆ

type Map ΒΆ

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

Map is a plain simple thread-safe map implementation, using a mutex for synchronization

func NewMap ΒΆ

func NewMap[K comparable, V any](size ...int) *Map[K, V]

NewMap creates a new thread-safe map of type K, V An empty map is allocated with enough space to hold the specified number of elements. The size may be omitted, in which case a small starting size is allocated.

func (*Map) Clear ΒΆ

func (m *Map) Clear()

Clear removes all items from the map

func (*Map[K, V]) Clone ΒΆ

func (m *Map[K, V]) Clone() Map[K, V]

Clone returns a copy of the map

func (*Map) Delete ΒΆ

func (m *Map) Delete(key K)

Delete removes the key from the map

func (*Map) Has ΒΆ

func (m *Map) Has(key K) bool

Has checks if the map has the key

func (*Map) Iter ΒΆ

func (m *Map) Iter() iter.Seq2[K, V]

Iter returns an iterator for the map

Iter does not necessarily correspond to any consistent snapshot of the map's contents: no key will be visited more than once. Iter does not block other methods on the receiver

func (*Map) Keys ΒΆ

func (m *Map) Keys() []K

Keys return slice with all map keys.

func (*Map) Len ΒΆ

func (m *Map) Len() int

Len returns the number of items in the map

func (*Map) Load ΒΆ

func (m *Map) Load(key K) (V, bool)

Load returns the value for the key and a boolean indicating if the key was found

func (*Map) LoadAndDelete ΒΆ

func (m *Map) LoadAndDelete(key K) (cur 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.

func (*Map) LoadOrStore ΒΆ

func (m *Map) LoadOrStore(key K, val V) (cur V, ok 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) Snapshot ΒΆ

func (m *Map) Snapshot() map[K]V

Snapshot returns a snapshot copy of the underlying map

func (*Map) Store ΒΆ

func (m *Map) Store(key K, value V)

Store sets a new key-value pair to the map

func (*Map) Swap ΒΆ

func (m *Map) Swap(key K, val V) (V, bool)

Swap replaces the value for the given key and returns the old value and a boolean indicating if the key was found

func (*Map) Values ΒΆ

func (m *Map) Values() []V

Values return slice with all map values.

type MapCmp ΒΆ

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

MapCmp is a thread-safe map implementation with comparable values It extends the Map with additional methods for conditionally deleting or swapping values

func NewMapCmp ΒΆ

func NewMapCmp[K, V comparable](size ...int) *MapCmp[K, V]

NewMapCmp creates a new thread-safe map of type with comparable values An empty map is allocated with enough space to hold the specified number of elements. The size may be omitted, in which case a small starting size is allocated.

func (*MapCmp) Clear ΒΆ

func (m *MapCmp) Clear()

Clear removes all items from the map

func (*MapCmp[K, V]) Clone ΒΆ

func (m *MapCmp[K, V]) Clone() MapCmp[K, V]

Clone returns a copy of the map

func (*MapCmp) Delete ΒΆ

func (m *MapCmp) Delete(key K)

Delete removes the key from the map

func (*MapCmp[K, V]) DeleteIfEqual ΒΆ

func (m *MapCmp[K, V]) DeleteIfEqual(key K, expected V) bool

DeleteIfEqual removes the key from the map when the value is equal to the expected value It returns true if the key was found and removed

func (*MapCmp) Has ΒΆ

func (m *MapCmp) Has(key K) bool

Has checks if the map has the key

func (*MapCmp) Iter ΒΆ

func (m *MapCmp) Iter() iter.Seq2[K, V]

Iter returns an iterator for the map

Iter does not necessarily correspond to any consistent snapshot of the map's contents: no key will be visited more than once. Iter does not block other methods on the receiver

func (*MapCmp) Keys ΒΆ

func (m *MapCmp) Keys() []K

Keys return slice with all map keys.

func (*MapCmp) Len ΒΆ

func (m *MapCmp) Len() int

Len returns the number of items in the map

func (*MapCmp) Load ΒΆ

func (m *MapCmp) Load(key K) (V, bool)

Load returns the value for the key and a boolean indicating if the key was found

func (*MapCmp) LoadAndDelete ΒΆ

func (m *MapCmp) LoadAndDelete(key K) (cur 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.

func (*MapCmp) LoadOrStore ΒΆ

func (m *MapCmp) LoadOrStore(key K, val V) (cur V, ok 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 (*MapCmp) Snapshot ΒΆ

func (m *MapCmp) Snapshot() map[K]V

Snapshot returns a snapshot copy of the underlying map

func (*MapCmp) Store ΒΆ

func (m *MapCmp) Store(key K, value V)

Store sets a new key-value pair to the map

func (*MapCmp) Swap ΒΆ

func (m *MapCmp) Swap(key K, val V) (V, bool)

Swap replaces the value for the given key and returns the old value and a boolean indicating if the key was found

func (*MapCmp[K, V]) SwapIfEqual ΒΆ

func (m *MapCmp[K, V]) SwapIfEqual(key K, expected, val V) bool

SwapIfEqual removes the key from the map when the value is equal to the expected value

func (*MapCmp) Values ΒΆ

func (m *MapCmp) Values() []V

Values return slice with all map values.

type Slice ΒΆ

type Slice[E any] struct {
	// contains filtered or unexported fields
}

Slice is a thread-safe slice implementation

func NewSlice ΒΆ

func NewSlice[E any](sizes ...int) *Slice[E]

NewSlice creates a new thread-safe slice of type E The size specifies the length. The capacity of the slice is equal to its length. A second integer argument may be provided to specify a different capacity; it must be no smaller than the length. For example, make([] int, 0, 10) allocates an underlying array of size 10 and returns a slice of length 0 and capacity 10 that is backed by this underlying array.

func NewSliceFrom ΒΆ

func NewSliceFrom[E any](elements []E) *Slice[E]

NewSliceFrom creates a new thread-safe slice of type E from the given elements The size of the slice is equal to the length of the elements, as well as the capacity The elements are copied into the resulting Slice

func (*Slice[E]) Append ΒΆ

func (s *Slice[E]) Append(items ...E)

Append appends new items to the slice. The new items are added to the end of the slice.

func (*Slice[E]) At ΒΆ

func (s *Slice[E]) At(i int) E

At returns the element at the given index. If the index is out of range, At panics.

func (*Slice[E]) Cap ΒΆ

func (s *Slice[E]) Cap() int

Cap returns the capacity of the slice

func (*Slice[E]) Clear ΒΆ

func (s *Slice[E]) Clear() int

Clear removes all elements from the slice but maintains the current capacity, returning the capacity of the slice.

func (*Slice[E]) Clip ΒΆ

func (s *Slice[E]) Clip() int

Clip removes unused capacity from the slice, returning the new capacity.

func (*Slice[E]) Concat ΒΆ

func (s *Slice[E]) Concat(other ...[]E) (int, int)

Concat concatenates the passed in slices to the current one, returning the new length and capacity of the slice.

func (*Slice[E]) Delete ΒΆ

func (s *Slice[E]) Delete(i, j int) (int, int)

Delete removes the elements s[i:j] from s, returning the new length and capacity of the slice. Delete panics if j > len(s) or s[i:j] is not a valid slice of s. Delete is O(len(s)-i), so if many items must be deleted, it is better to make a single call deleting them all together than to delete one at a time. Delete zeroes the elements s[len(s)-(j-i):len(s)].

func (*Slice[E]) DeleteFunc ΒΆ

func (s *Slice[E]) DeleteFunc(del func(E) bool) (int, int)

DeleteFunc removes any elements from s for which del returns true, returning the new length and capacity of the slice. DeleteFunc zeroes the elements between the new length and the original length.

func (*Slice[E]) Grow ΒΆ

func (s *Slice[E]) Grow(n int) int

Grow increases the slice's capacity, if necessary, to guarantee space for another n elements. After Grow(n), at least n elements can be appended to the slice without another allocation. If n is negative or too large to allocate the memory, Grow panics. It returns the new capacity of the slice.

func (*Slice[E]) Insert ΒΆ

func (s *Slice[E]) Insert(i int, v ...E) (int, int)

Insert inserts the values v... into s at index i, and returns the new length and capacity of the slice. The elements at s[i:] are shifted up to make room. In the resulting slice r, r[i] == v[0], and r[i+len(v)] == value originally at r[i]. Insert panics if i is out of range. This function is O(len(s) + len(v)).

func (*Slice[E]) Iter ΒΆ

func (s *Slice[E]) Iter() iter.Seq2[int, E]

Iter returns an iterator for the slice

Iter does not necessarily correspond to any consistent snapshot of the slice's contents: no key will be visited more than once. Iter does not block other methods on the receiver

func (*Slice[E]) Len ΒΆ

func (s *Slice[E]) Len() int

Len returns the length of the slice

func (*Slice[E]) Replace ΒΆ

func (s *Slice[E]) Replace(i, j int, v ...E) (int, int)

Replace replaces the elements s[i:j] by the given v, returning the new length and capacity of the slice. Replace panics if j > len(s) or s[i:j] is not a valid slice of s. When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.

func (*Slice[E]) Snapshot ΒΆ

func (s *Slice[E]) Snapshot() []E

Snapshot returns a copy of the slice

func (*Slice[E]) Store ΒΆ

func (s *Slice[E]) Store(i int, val E)

Store sets the element at the given index to the given value. If the index is out of range, Store panics.

Directories ΒΆ

Path Synopsis

Jump to

Keyboard shortcuts

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