From 032a2e33f1d21287e39d02860810161e8002ce33 Mon Sep 17 00:00:00 2001 From: andeya Date: Mon, 9 Jan 2023 18:11:36 +0800 Subject: [PATCH] feat(sync): add some scope methods Change-Id: I4be6e3a53d713d3d87dbea173ab214f753927624 --- sync.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/sync.go b/sync.go index a47d136..45cbaaa 100644 --- a/sync.go +++ b/sync.go @@ -65,6 +65,21 @@ func (m *Mutex[T]) Unlock(newData ...T) { m.inner.Unlock() } +// LockScope securely read and write the data in the mutex. +func (m *Mutex[T]) LockScope(f func(T) T) { + m.inner.Lock() + defer m.inner.Unlock() + m.data = f(m.data) +} + +// TryLockScope tries to securely read and write the data in the mutex. +func (m *Mutex[T]) TryLockScope(f func(T) T) { + if m.inner.TryLock() { + defer m.inner.Unlock() + m.data = f(m.data) + } +} + // RWMutex is a better generic-type wrapper for `sync.RWMutex` that holds a value. // A RWMutex is a reader/writer mutual exclusion lock. // The lock can be held by an arbitrary number of readers or a single writer. @@ -123,6 +138,21 @@ func (m *RWMutex[T]) Unlock(newData ...T) { m.inner.Unlock() } +// TryLockScope tries to securely read and write the data in the mutex. +func (m *RWMutex[T]) TryLockScope(f func(T) T) { + if m.inner.TryLock() { + defer m.inner.Unlock() + m.data = f(m.data) + } +} + +// LockScope securely read and write the data in the rwmutex. +func (m *RWMutex[T]) LockScope(f func(T) T) { + m.inner.Lock() + defer m.inner.Unlock() + m.data = f(m.data) +} + // Happens-before relationships are indicated to the race detector via: // - Unlock -> Lock: readerSem // - Unlock -> RLock: readerSem @@ -166,6 +196,21 @@ func (m *RWMutex[T]) RUnlock() { m.inner.RUnlock() } +// TryRLockScope tries to securely read the data in the mutex. +func (m *RWMutex[T]) TryRLockScope(f func(T) T) { + if m.inner.TryRLock() { + defer m.inner.RUnlock() + m.data = f(m.data) + } +} + +// RLockScope securely read the data in the rwmutex. +func (m *RWMutex[T]) RLockScope(f func(T) T) { + m.inner.RLock() + defer m.inner.RUnlock() + m.data = f(m.data) +} + // SyncMap is a better generic-type wrapper for `sync.Map`. // A SyncMap is like a Go map[interface{}]interface{} but is safe for concurrent use // by multiple goroutines without additional locking or coordination.