Documentation ¶
Overview ¶
Package sync implements primitives for synchronization between processes.
Index ¶
- Constants
- Variables
- func DestroyCond(name string) error
- func DestroyEvent(name string) error
- func DestroyFutexMutex(name string) error
- func DestroyMutex(name string) error
- func DestroyRWMutex(name string) error
- func DestroySemaMutex(name string) error
- func DestroySemaphore(name string) error
- func DestroySpinMutex(name string) error
- func FutexWait(addr unsafe.Pointer, value int32, timeout time.Duration, flags int32) error
- func FutexWake(addr unsafe.Pointer, count int32, flags int32) (int, error)
- type Cond
- type Event
- type FutexMutex
- type IPCLocker
- type RWMutex
- type SemaMutex
- type Semaphore
- type SpinMutex
- type TimedIPCLocker
Examples ¶
Constants ¶
const ( // FUTEX_PRIVATE_FLAG is used to optimize futex usage for process-private futexes. FUTEX_PRIVATE_FLAG = 128 // FUTEX_CLOCK_REALTIME is used to tell the kernel, that is must treat timeouts for // FUTEX_WAIT_BITSET, FUTEX_WAIT_REQUEUE_PI, and FUTEX_WAIT as an absolute time based on CLOCK_REALTIME FUTEX_CLOCK_REALTIME = 256 )
const ( // CSemMaxVal is the maximum semaphore value, // which is guaranteed to be supported on all platforms. CSemMaxVal = 32767 )
Variables ¶
var ( // MaxCondWaiters is the maximum length of the waiting queue for this type of a cond. // This limit is actual for waitlist-based condvars, currently on windows and darwin. // If this limit is exceeded, Wait/WaitTimeout will panic with ErrTooManyWaiters. MaxCondWaiters = 128 // ErrTooManyWaiters is an error, that indicates, that the waiting queue is full. ErrTooManyWaiters = errors.New("waiters limit has been reached") )
Functions ¶
func DestroyCond ¶
DestroyCond permanently removes condvar with the given name.
func DestroyEvent ¶
DestroyEvent permanently destroys an event with the given name.
func DestroyFutexMutex ¶
DestroyFutexMutex permanently removes mutex with the given name.
func DestroyMutex ¶
DestroyMutex permanently removes mutex with the given name.
func DestroyRWMutex ¶
DestroyRWMutex permanently removes mutex with the given name.
func DestroySemaMutex ¶
DestroySemaMutex permanently removes mutex with the given name.
func DestroySemaphore ¶
DestroySemaphore removes the semaphore permanently.
func DestroySpinMutex ¶
DestroySpinMutex removes a mutex object with the given name
Types ¶
type Cond ¶
type Cond cond
Cond is a named interprocess condition variable.
Example ¶
DestroyMutex("mut") mut, err := NewMutex("mut", os.O_CREATE|os.O_EXCL, 0666) if err != nil { panic("new") } defer mut.Close() DestroyCond("cond") cond, err := NewCond("cond", os.O_CREATE|os.O_EXCL, 0666, mut) if err != nil { panic("new") } defer cond.Close() var sharedValue int go func() { mut.Lock() defer mut.Unlock() sharedValue = 1 cond.Signal() }() mut.Lock() defer mut.Unlock() if sharedValue == 0 { cond.Wait() if sharedValue == 0 { panic("bad value") } }
Output:
func NewCond ¶
NewCond returns new interprocess condvar.
name - unique condvar name. flag - a combination of open flags from 'os' package. perm - object's permission bits. l - a locker, associated with the shared resource.
type Event ¶
type Event event
Event is a synchronization primitive used for notification. If it is signaled by a call to Set(), it'll stay in this state, unless someone calls Wait(). After it the event is reset into non-signaled state.
Example ¶
event, err := NewEvent("event", os.O_CREATE|os.O_EXCL, 0666, false) if err != nil { return } go func() { event.Set() }() if event.WaitTimeout(time.Millisecond * 250) { // event has been set } else { // timeout elapsed } event.Destroy()
Output:
func NewEvent ¶
NewEvent creates a new interprocess event. It uses the default implementation on the current platform.
name - object name. flag - flag is a combination of open flags from 'os' package. perm - object's permission bits. initial - if true, the event will be set after creation.
type FutexMutex ¶
type FutexMutex struct {
// contains filtered or unexported fields
}
FutexMutex is a mutex based on linux/freebsd futex object.
func NewFutexMutex ¶
NewFutexMutex creates a new futex-based mutex. This implementation is based on a paper 'Futexes Are Tricky' by Ulrich Drepper, this document can be found in 'docs' folder.
name - object name. flag - flag is a combination of open flags from 'os' package. perm - object's permission bits.
func (*FutexMutex) Close ¶
func (f *FutexMutex) Close() error
Close indicates, that the object is no longer in use, and that the underlying resources can be freed.
func (*FutexMutex) LockTimeout ¶
func (f *FutexMutex) LockTimeout(timeout time.Duration) bool
LockTimeout tries to lock the locker, waiting for not more, than timeout.
func (*FutexMutex) TryLock ¶
func (f *FutexMutex) TryLock() bool
TryLock makes one attempt to lock the mutex. It return true on succeess and false otherwise.
func (*FutexMutex) Unlock ¶
func (f *FutexMutex) Unlock()
Unlock releases the mutex. It panics on an error, or if the mutex is not locked.
type IPCLocker ¶
IPCLocker is a minimal interface, which must be satisfied by any synchronization primitive on any platform.
Example ¶
DestroyMutex("mut") mut, err := NewMutex("mut", os.O_CREATE|os.O_EXCL, 0666) if err != nil { panic("new") } defer mut.Close() var sharedValue uint64 var wg sync.WaitGroup wg.Add(8) for i := 0; i < 8; i++ { go func() { defer wg.Done() mut, err := NewMutex("mut", 0, 0) if err != nil { panic("new") } defer mut.Close() for i := 0; i < 1000000; i++ { mut.Lock() sharedValue++ mut.Unlock() } }() } wg.Wait() if sharedValue != 8*1000000 { panic("invalid value ") }
Output:
type RWMutex ¶
type RWMutex struct {
// contains filtered or unexported fields
}
RWMutex is a mutex, that can be held by any number of readers or one writer.
Example ¶
const ( writers = 4 readers = 10 ) DestroyRWMutex("rw") m, err := NewRWMutex("rw", os.O_CREATE|os.O_EXCL, 0666) if err != nil { panic(err) } // we create a shared array of consistently increasing ints for reading and wriring. sharedData := make([]int, 128) for i := range sharedData { sharedData[i] = i } var wg sync.WaitGroup wg.Add(writers + readers) // writers will update the data. for i := 0; i < writers; i++ { go func() { defer wg.Done() start := rand.Intn(1024) m.Lock() for i := range sharedData { sharedData[i] = i + start } m.Unlock() }() } // readers will check the data. for i := 0; i < readers; i++ { go func() { defer wg.Done() m.RLock() for i := 1; i < len(sharedData); i++ { if sharedData[i] != sharedData[i-1]+1 { panic("bad data") } } m.RUnlock() }() } wg.Wait() fmt.Println("done")
Output: done
func NewRWMutex ¶
NewRWMutex returns new RWMutex
name - object name. flag - flag is a combination of open flags from 'os' package. perm - object's permission bits.
func (*RWMutex) Lock ¶
func (rw *RWMutex) Lock()
Lock locks the mutex exclusively. It panics on an error.
func (*RWMutex) RLock ¶
func (rw *RWMutex) RLock()
RLock locks the mutex for reading. It panics on an error.
func (*RWMutex) RLocker ¶
RLocker returns a Locker interface that implements the Lock and Unlock methods by calling rw.RLock and rw.RUnlock.
type SemaMutex ¶
type SemaMutex struct {
// contains filtered or unexported fields
}
SemaMutex is a semaphore-based mutex for unix.
func NewSemaMutex ¶
NewSemaMutex creates a new semaphore-based mutex.
name - object name. flag - flag is a combination of open flags from 'os' package. perm - object's permission bits.
func (*SemaMutex) LockTimeout ¶
LockTimeout tries to lock the locker, waiting for not more, than timeout.
type Semaphore ¶
type Semaphore semaphore
Semaphore is a synchronization object with a resource counter, which can be used to control access to a shared resource. It provides access to actual OS semaphore primitive via:
CreateSemaprore on windows semget on unix
Example ¶
// create new semaphore with initial count set to 3. DestroySemaphore("sema") sema, err := NewSemaphore("sema", os.O_CREATE|os.O_EXCL, 0666, 3) if err != nil { panic(err) } defer sema.Close() // in the following cycle we consume three units of the resource and won't block. for i := 0; i < 3; i++ { sema.Wait() fmt.Println("got one resource unit") } // the following two goroutines won't continue until we call Signal(). var wg sync.WaitGroup wg.Add(2) for i := 0; i < 2; i++ { go func() { defer wg.Done() // open existing semaphore sema, err := NewSemaphore("sema", 0, 0666, 0) if err != nil { panic(err) } defer sema.Close() sema.Wait() fmt.Println("got one resource unit after waiting") }() } // wake up goroutines fmt.Println("waking up...") sema.Signal(2) wg.Wait() fmt.Println("done")
Output: got one resource unit got one resource unit got one resource unit waking up... got one resource unit after waiting got one resource unit after waiting done
func NewSemaphore ¶
NewSemaphore creates new semaphore with the given name.
name - object name. flag - flag is a combination of open flags from 'os' package. perm - object's permission bits. initial - this value will be added to the semaphore's value, if it was created.
func (*Semaphore) Signal ¶
Signal increments the value of semaphore variable by 1, waking waiting process (if any).
func (*Semaphore) Wait ¶
func (s *Semaphore) Wait()
Wait decrements the value of semaphore variable by -1, and blocks if the value becomes negative.
func (*Semaphore) WaitTimeout ¶
WaitTimeout decrements the value of semaphore variable by 1. If the value becomes negative, it waites for not longer than timeout. On darwin and freebsd this func has some side effects, see sema_timed_bsd.go for details.
type SpinMutex ¶
type SpinMutex struct {
// contains filtered or unexported fields
}
SpinMutex is a synchronization object which performs busy wait loop.
func NewSpinMutex ¶
NewSpinMutex creates a new spin mutex.
name - object name. flag - flag is a combination of open flags from 'os' package. perm - object's permission bits.
func (*SpinMutex) Close ¶
Close indicates, that the object is no longer in use, and that the underlying resources can be freed.
func (*SpinMutex) Lock ¶
func (spin *SpinMutex) Lock()
Lock locks the mutex waiting in a busy loop if needed.
func (*SpinMutex) LockTimeout ¶
LockTimeout locks the mutex waiting in a busy loop for not longer, than timeout.
type TimedIPCLocker ¶
type TimedIPCLocker interface { IPCLocker // LockTimeout tries to lock the locker, waiting for not more, than timeout LockTimeout(timeout time.Duration) bool }
TimedIPCLocker is a locker, whose lock operation can be limited with duration.
Example ¶
DestroyMutex("mut") mut, err := NewMutex("mut", os.O_CREATE|os.O_EXCL, 0666) if err != nil { panic("new") } defer mut.Close() tmut, ok := mut.(TimedIPCLocker) if !ok { panic("not a timed locker") } var sharedValue int rand.Seed(time.Now().Unix()) go func() { mut, err := NewMutex("mut", 0, 0) if err != nil { panic("new") } defer mut.Close() mut.Lock() // change value after [0..500] ms delay. time.Sleep(time.Duration(rand.Int()%6) * time.Millisecond * 100) sharedValue = 1 mut.Unlock() }() // give another goroutine some time to lock the mutex. time.Sleep(10 * time.Millisecond) if tmut.LockTimeout(250 * time.Millisecond) { if sharedValue != 1 { panic("bad value") } tmut.Unlock() } else { } // timeout elapsed
Output:
Source Files ¶
- cond.go
- cond_event.go
- cond_futex.go
- doc.go
- event.go
- event_futex.go
- futex.go
- futex_linux.go
- lwevent.go
- lwmutex.go
- lwrwmutex.go
- mutex.go
- mutex_futex.go
- mutex_helper_futex.go
- mutex_sema.go
- mutex_spin.go
- rwmutex.go
- sema_sys.go
- sema_timed_linux.go
- sema_unix.go
- semaphore.go
- sync.go
- sys_sema_linux+darwin.go
- sys_sema_linux_amd64.go