mirror of
https://github.com/asticode/go-astikit.git
synced 2025-12-24 11:50:53 +08:00
Added fifo mutex
This commit is contained in:
48
sync.go
48
sync.go
@@ -554,3 +554,51 @@ func (d *AtomicDuration) Duration() time.Duration {
|
||||
defer d.m.Unlock()
|
||||
return d.d
|
||||
}
|
||||
|
||||
// FIFOMutex is a mutex guaranteeing FIFO order
|
||||
type FIFOMutex struct {
|
||||
busy bool
|
||||
m sync.Mutex // Locks busy and waiting
|
||||
waiting []*sync.Cond
|
||||
}
|
||||
|
||||
func (m *FIFOMutex) Lock() {
|
||||
// No need to wait
|
||||
m.m.Lock()
|
||||
if !m.busy {
|
||||
m.busy = true
|
||||
m.m.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// Create cond
|
||||
c := sync.NewCond(&sync.Mutex{})
|
||||
|
||||
// Make sure to lock cond when waiting mutex is still held
|
||||
c.L.Lock()
|
||||
|
||||
// Add to waiting queue
|
||||
m.waiting = append(m.waiting, c)
|
||||
m.m.Unlock()
|
||||
|
||||
// Wait
|
||||
c.Wait()
|
||||
}
|
||||
|
||||
func (m *FIFOMutex) Unlock() {
|
||||
// Lock
|
||||
m.m.Lock()
|
||||
defer m.m.Unlock()
|
||||
|
||||
// Waiting queue is empty
|
||||
if len(m.waiting) == 0 {
|
||||
m.busy = false
|
||||
return
|
||||
}
|
||||
|
||||
// Signal and remove first item in waiting queue
|
||||
m.waiting[0].L.Lock()
|
||||
m.waiting[0].Signal()
|
||||
m.waiting[0].L.Unlock()
|
||||
m.waiting = m.waiting[1:]
|
||||
}
|
||||
|
||||
26
sync_test.go
26
sync_test.go
@@ -192,3 +192,29 @@ func TestDebugMutex(t *testing.T) {
|
||||
t.Fatalf("%s doesn't contain %s", g, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFIFOMutex(t *testing.T) {
|
||||
m := FIFOMutex{}
|
||||
var r []int
|
||||
m.Lock()
|
||||
wg := sync.WaitGroup{}
|
||||
testFIFOMutex(1, &m, &r, &wg)
|
||||
m.Unlock()
|
||||
wg.Wait()
|
||||
if e, g := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, r; !reflect.DeepEqual(e, g) {
|
||||
t.Fatalf("expected %v, got %v", e, g)
|
||||
}
|
||||
}
|
||||
|
||||
func testFIFOMutex(i int, m *FIFOMutex, r *[]int, wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if i < 10 {
|
||||
testFIFOMutex(i+1, m, r, wg)
|
||||
}
|
||||
m.Lock()
|
||||
*r = append(*r, i)
|
||||
m.Unlock()
|
||||
}()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user