sync

package
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2019 License: BSD-3-Clause Imports: 2 Imported by: 0

Documentation

Overview

Package sync provides synchronization primitives.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrClosed   = errors.New("semaphore is closed")
	ErrCanceled = errors.New("semaphore operation was canceled")
	ErrTryAgain = errors.New("semaphore operation failed, try again")
)

Functions

This section is empty.

Types

type DebugMutex

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

DebugMutex supports checking whether a mutex is locked.

func (*DebugMutex) CheckLocked

func (m *DebugMutex) CheckLocked()

CheckLocked panics if the lock is not held.

func (*DebugMutex) Lock

func (m *DebugMutex) Lock()

func (*DebugMutex) Unlock

func (m *DebugMutex) Unlock()

type Semaphore

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

Semaphore is an implementation of unbounded semaphores. Abstractly, a semaphore holds a nonnegative integer value, and supports operations to increment and decrement the value. The semaphore value is not allowed to be negative; decrement operations block until the semaphore value is positive. http://en.wikipedia.org/wiki/Semaphore_%28programming%29

The standard suggestion for implementing semaphores in Go is to use a buffered channel, where the number of elements in the channel is the max value of the semaphore. However, what we implement here is _unbounded_ semaphores (up to a max value of 2^31-1).

A mutex and integer is used to keep track of the numerical value of the and a channel is used for notification of changes. When decrementing, the value of the semaphore is decremented and if not sufficient, DecN will block until it can subtract more.

Because of this looping, the semaphore is not fair. The reason for using a channel for notifications is for cancellation. The Dec(cancel <-chan struct{}) method takes a cancelation channel, so we use a "select" operation to determine whether to perform a semaphore operation or abort because the semaphore is close or the operation was canceled.

NOTE: when the Semaphore is closed, the Dec (or DecN) operations are unblocked, returning an error (ErrClosed) if the semaphore value is 0 (or less than the DecN value), respectively. However, even with the Semaphore closed, if the semaphore value is non-zero (or sufficient to satisfy the DecN value), Dec (or DecN) performs the decrement successfully and returns without an error. Regardless of whether the Semaphore is closed or not, Inc/IncN succeed in incrementing the semaphore value.

func NewSemaphore

func NewSemaphore() *Semaphore

NewSemaphore allocates a semaphore with an initial value.

func (*Semaphore) Close

func (s *Semaphore) Close()

Close closes the semaphore. Subsequent operations do not block.

func (*Semaphore) Dec

func (s *Semaphore) Dec(cancel <-chan struct{}) error

Dec decrements the semaphore by 1.

func (*Semaphore) DecN

func (s *Semaphore) DecN(n uint, cancel <-chan struct{}) error

DecN decrements the semaphore. Blocks until the final value of the semaphore is nonnegative, or the <cancel> channel is closed (or has a value).

func (*Semaphore) Inc

func (s *Semaphore) Inc() error

Inc increments the semaphore by 1.

func (*Semaphore) IncN

func (s *Semaphore) IncN(n uint) error

IncN increments the semaphore. Wakes any potential waiters.

func (*Semaphore) TryDec

func (s *Semaphore) TryDec() error

TryDec tries to decrement the semaphore by 1.

func (*Semaphore) TryDecN

func (s *Semaphore) TryDecN(n uint) error

TryDecN tries to decrement the semaphore.

type WaitGroup

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

WaitGroup implements a sync.WaitGroup-like structure that does not require all calls to Add to be made before Wait, instead calls to Add after Wait will fail.

As a result, WaitGroup cannot be "re-used" in the way that sync.WaitGroup can. In the following example using sync.WaitGroup, Add, Done and Wait behave in the same way in rounds 1 and 2.

var wg sync.WaitGroup

Round #1. wg.Add(1) go wg.Done() wg.Wait()

Round #2. wg.Add(1) go wg.Done() wg.Wait()

However, an equivalent program using WaitGroup would receive an error on the second call to TryAdd.

func (*WaitGroup) Done

func (w *WaitGroup) Done()

Done decrements the counter. If the counter goes negative, Done panics.

func (*WaitGroup) TryAdd

func (w *WaitGroup) TryAdd() (added bool)

TryAdd attempts to increment the counter. If Wait has already been called, TryAdd fails to increment the counter and returns false. If the counter becomes zero, all goroutines blocked on Wait are released.

func (*WaitGroup) Wait

func (w *WaitGroup) Wait()

Wait blocks until the counter is zero.

Jump to

Keyboard shortcuts

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