sync

package
v0.2.1-0...-a47f784 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2026 License: BSD-3-Clause Imports: 1 Imported by: 0

Documentation

Overview

Package sync provides basic synchronization primitives such as mutual exclusion locks and condition variables.

Values containing the types defined in this package should not be copied.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cond

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

Cond is a condition variable, a rendezvous point for threads waiting for or announcing the occurrence of an event.

Each Cond is associated with a Mutex, which must be held when changing the condition and when calling Cond.Wait. The zero value is not usable; call Cond.Init before use. A Cond must not be copied after Init.

Example
package main

import (
	"solod.dev/so/conc"
	"solod.dev/so/sync"
)

type gate struct {
	mu    sync.Mutex
	cond  sync.Cond
	ready bool
}

func await(arg any) any {
	g := arg.(*gate)
	g.mu.Lock()
	for !g.ready {
		g.cond.Wait()
	}
	println("go!")
	g.mu.Unlock()
	return nil
}

func main() {
	var g gate
	g.mu.Init()
	g.cond.Init(&g.mu)
	defer g.mu.Free()
	defer g.cond.Free()

	thr := conc.Go(await, &g, nil)
	defer thr.Wait()

	g.mu.Lock()
	g.ready = true
	g.cond.Signal()
	g.mu.Unlock()
	// go!
}

func (*Cond) Broadcast

func (c *Cond) Broadcast()

Broadcast wakes all threads waiting on c, if any.

func (*Cond) Free

func (c *Cond) Free()

Free releases the resources held by c. The Cond is unusable afterward.

func (*Cond) Init

func (c *Cond) Init(mu *Mutex)

Init prepares c for use, associating it with mu. It must be called exactly once before any other method. A Cond must not be copied after Init.

func (*Cond) Signal

func (c *Cond) Signal()

Signal wakes at least one thread waiting on c, if any.

func (*Cond) Wait

func (c *Cond) Wait()

Wait atomically unlocks the associated mutex and suspends the calling thread until the Cond is signaled, then re-locks the mutex before returning. The caller must hold the mutex when calling Wait.

func (*Cond) WaitFor

func (c *Cond) WaitFor(nsec int64) bool

WaitFor behaves like Cond.Wait but stops waiting once nsec nanoseconds have elapsed on the monotonic clock.

Measuring against the monotonic clock keeps the timeout unaffected by wall-clock changes (NTP steps, manual resets). To honor a fixed deadline across spurious wakeups, recompute the remaining time on each call.

WaitFor reports whether it timed out: true means the deadline passed, false means the Cond was signaled. A non-positive nsec times out without blocking.

As with Wait, the caller must hold the mutex and it is re-locked before returning.

type Mutex

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

Mutex is a mutual exclusion lock.

The zero value is not usable; call Mutex.Init before use. A Mutex must not be copied after Init.

Example
package main

import (
	"solod.dev/so/conc"
	"solod.dev/so/mem"
	"solod.dev/so/sync"
)

type counter struct {
	mu  *sync.Mutex
	val int
}

func increment(arg any) {
	c := arg.(*counter)
	c.mu.Lock()
	c.val++
	c.mu.Unlock()
}

func main() {
	var mu sync.Mutex
	mu.Init()
	defer mu.Free()

	cnt := counter{mu: &mu, val: 0}
	opts := conc.PoolOpts{NumThreads: 4}
	pool := conc.NewPool(mem.System, opts)
	defer pool.Free()
	for range 100 {
		pool.Go(increment, &cnt)
	}
	pool.Wait()

	println(cnt.val)
	// 100
}

func (*Mutex) Free

func (m *Mutex) Free()

Free releases the resources held by m. The Mutex is unusable afterward.

func (*Mutex) Init

func (m *Mutex) Init()

Init prepares m for use, leaving it unlocked. It must be called exactly once before any other method. A Mutex must not be copied after Init.

func (*Mutex) Lock

func (m *Mutex) Lock()

Lock locks m, blocking until the lock is available.

func (*Mutex) TryLock

func (m *Mutex) TryLock() bool

TryLock tries to lock m and reports whether it succeeded. It returns false without blocking if the lock is already held.

func (*Mutex) Unlock

func (m *Mutex) Unlock()

Unlock unlocks m.

type Once

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

Once runs a function exactly once, even when Do is called concurrently from multiple threads.

The zero value is not usable; call Once.Init before use. A Once must not be copied after Init.

Example
package main

import (
	"solod.dev/so/conc"
	"solod.dev/so/mem"
	"solod.dev/so/sync"
)

func hello() {
	println("Hello, world!")
}

func onceHello(arg any) {
	once := arg.(*sync.Once)
	once.Do(hello)
}

func main() {
	var once sync.Once
	once.Init()
	defer once.Free()

	opts := conc.PoolOpts{NumThreads: 4}
	pool := conc.NewPool(mem.System, opts)
	for range 10 {
		pool.Go(onceHello, &once)
	}
	pool.Free()
	// Hello, world!
}

func (*Once) Do

func (o *Once) Do(f func())

Do calls f if and only if Do is being called for the first time for this o. If Do is called concurrently, the callers block until the one call to f returns; every Do returns only after f has completed.

Because no call to Do returns until the one call to f returns, f must not call Do on the same o, or it will deadlock.

func (*Once) Free

func (o *Once) Free()

Free releases the resources held by o. The Once is unusable afterward.

func (*Once) Init

func (o *Once) Init()

Init prepares o for use. It must be called exactly once before any other method. A Once must not be copied after Init.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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