sync2

package module
v0.0.0-...-a6801fb Latest Latest
Warning

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

Go to latest
Published: Feb 10, 2025 License: MIT Imports: 5 Imported by: 0

README

sync2

Synchronization Primitives Beyond Go's Standard Library.

  1. Cancellable Sleep:

     func ExampleSleep() {
         ctx, cancel := context.WithTimeout(context.Background(),
             time.Millisecond)
         defer cancel()
         // It won't sleep for an hour
         fmt.Println(sync2.Sleep(ctx, time.Hour))
         // Output:
         // context deadline exceeded
     }
    
  2. Cancellable mutex:

     func ExampleMutexGroup_Cancel() {
         ctx, cancel := context.WithCancel(context.Background())
         g := sync2.NewMutexGroupWithContext(ctx)
         m := g.NewMutex()
         m.Lock()
         go cancel()
         fmt.Println(m.Lock()) // Won't block for long.
         // Output:
         // context canceled
     }
    
  3. Atomic locking of multiple mutexes:

     func ExampleMutexGroup_LockAll() {
         g := sync2.NewMutexGroup()
         m1, m2 := g.NewMutex(), g.NewMutex()
         m1.Lock()
         m2.Lock()
         go func() {
             m1.Unlock()
             fmt.Println("m1 unlocked")
             m2.Unlock()
             fmt.Println("m2 unlocked")
         }()
         g.LockAll(m1, m2)
         fmt.Println("atomically locked m1 and m2")
         // Output:
         // m1 unlocked
         // m2 unlocked
         // atomically locked m1 and m2
     }
    

The full example is available here: Dining philosophers problem

Dining philosophers

Documentation

Overview

The sync2 package provides synchronization primitives beyond those offered by the sync package.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrCanceled = errors.New("mutex group canceled")

ErrCanceled is the cause of cancellation when a mutext group is canceled by MutexGroup.Cancel.

Functions

func Sleep

func Sleep(ctx context.Context, d time.Duration) error

Sleep behaves like time.Sleep, but is cancellable using the provided context. It returns ctx.Err() if the context is done before the d elapses.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/mkch/sync2"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(),
		time.Millisecond)
	defer cancel()
	// It won't sleep for an hour
	fmt.Println(sync2.Sleep(ctx, time.Hour))
}
Output:

context deadline exceeded

Types

type Mutex

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

A Mutex is a mutual exclusion lock that is part of a MutexGroup.

A Mutex must not be copied.

Mutex has the same locking and unlocking behavior as sync.Mutex, with the added ability to interact with MutexGroup.

func (*Mutex) Lock

func (m *Mutex) Lock() error

Lock locks m as sync.Mutex.Lock does. If the associated MutexGroup is canceled, Lock returns the cause.

func (*Mutex) Unlock

func (m *Mutex) Unlock() error

Unlock unlocks m. It is a run-time error if m is not locked. If the associated MutexGroup is canceled, Unlock returns the cause.

type MutexGroup

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

MutexGroup provides atomic locking and cancellation for a group of Mutex es. See MutexGroup.LockAll.

A Mutex must not be copied.

func NewMutexGroup

func NewMutexGroup() *MutexGroup

NewMutexGroup creates a new MutexGroup.

func NewMutexGroupWithContext

func NewMutexGroupWithContext(ctx context.Context) (g *MutexGroup)

NewMutexGroupWithContext creates a new MutexGroup that is cancelled when ctx is done.

func (*MutexGroup) Cancel

func (g *MutexGroup) Cancel()

Cancel tells g to cancel with cause ErrCanceled. Cancel does not wait for g to cancel. Cancel may be called by multiple goroutines simultaneously. After the first call, subsequent calls to Cancel do nothing.

Example
package main

import (
	"context"
	"fmt"

	"github.com/mkch/sync2"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	g := sync2.NewMutexGroupWithContext(ctx)
	m := g.NewMutex()
	m.Lock()
	go cancel()
	fmt.Println(m.Lock()) // Won't block for long.
}
Output:

context canceled

func (*MutexGroup) LockAll

func (g *MutexGroup) LockAll(ms ...*Mutex) error

LockAll atomically locks all mutexes in ms. If any mutex in ms is already locked, the calling goroutine blocks until all mutexes are available. If g is canceled, LockAll returns the cause. It panics if ms is empty or if any mutex in ms was not created by g.

Example
package main

import (
	"fmt"

	"github.com/mkch/sync2"
)

func main() {
	g := sync2.NewMutexGroup()
	m1, m2 := g.NewMutex(), g.NewMutex()
	m1.Lock()
	m2.Lock()
	go func() {
		m1.Unlock()
		fmt.Println("m1 unlocked")
		m2.Unlock()
		fmt.Println("m2 unlocked")
	}()
	g.LockAll(m1, m2)
	fmt.Println("atomically locked m1 and m2")
}
Output:

m1 unlocked
m2 unlocked
atomically locked m1 and m2

func (*MutexGroup) NewMutex

func (g *MutexGroup) NewMutex() *Mutex

NewMutex creates a mutex associated with group g.

Directories

Path Synopsis
example
dinning command

Jump to

Keyboard shortcuts

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