pkg/fsync/fsync_shared.go
Nalin Dahyabhai bd3b44be3e Add a file-backed read-write mutex implementation
The fsync package provides Mutex and RWMutex types which aim to provide
the same semantics as their namesakes in the sync package, extending
that locking across processes by using file locks and randomly-generated
identifiers to allow processes to determine whether or not they were the
last to modify a resource that's protected by the lock.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com> (github: nalind)
2016-07-15 17:21:14 -04:00

95 lines
1.9 KiB
Go

package fsync
import (
"sync"
)
// rmutex is a wrapper for a Mutex which provides Lock and Unlock methods which
// merely call the underlying Mutex's RLock and RUnlock methods.
type rmutex struct {
m *Mutex
}
type RLocker interface {
sync.Locker
Updated() bool
}
// RLocker returns a Locker which obtains and releases read locks on the underlying Mutex.
func (m *Mutex) RLocker() RLocker {
return &rmutex{m: m}
}
// Lock obtains a read lock on the underlying Mutex.
func (r *rmutex) Lock() {
r.m.RLock()
}
// Unlock releases a read lock on the underlying Mutex.
func (r *rmutex) Unlock() {
r.m.RUnlock()
}
// Updated checks if the data protected by the lock was changed since we last
// modified it.
func (r *rmutex) Updated() bool {
return r.m.Updated()
}
var lockMgr struct {
m sync.Mutex
locks map[string]*Mutex
}
func init() {
lockMgr.locks = make(map[string]*Mutex)
}
// Get returns a mutex which is tied to a lock on the specified lockfile, or nil on error. The file descriptor is kept open.
func Get(lockfile string) (*Mutex, error) {
m, err := get(lockfile)
if err != nil {
return nil, err
}
return m, nil
}
// RLock obtains a read lock on the specified lock file, or returns an error.
func RLock(lockfile string) error {
fl, err := Get(lockfile)
if err != nil {
return err
}
fl.RLock()
return nil
}
// RUnlock releases a read lock on the specified lock file, or returns an error.
func RUnlock(lockfile string) error {
fl, err := Get(lockfile)
if err != nil {
return err
}
fl.RUnlock()
return nil
}
// Lock obtains a write lock on the specified lock file, or returns an error.
func Lock(lockfile string) error {
fl, err := Get(lockfile)
if err != nil {
return err
}
fl.Lock()
return nil
}
// Unlock releases a write lock on the specified lock file, or returns an error.
func Unlock(lockfile string) error {
fl, err := Get(lockfile)
if err != nil {
return err
}
fl.Unlock()
return nil
}