cmds/exec_agent/sync.go (47 lines of code) (raw):
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
package main
import (
"bytes"
"sync"
)
// SafeSignal is a goroutine safe signalling mechanism
// It can have multiple goroutines that trigger the signal without
// interfering with eachother (or crashing as using a channel would)
// Currently designed for a single waiter goroutine.
type SafeSignal struct {
sync.Mutex
done bool
c *sync.Cond
}
func newSafeSignal() *SafeSignal {
s := &SafeSignal{}
s.c = &sync.Cond{L: s}
return s
}
func (s *SafeSignal) Signal() {
s.Lock()
s.done = true
s.Unlock()
s.c.Signal()
}
func (s *SafeSignal) Wait() {
s.Lock()
defer s.Unlock()
for !s.done {
s.c.Wait()
}
}
type SafeBuffer struct {
b bytes.Buffer
mu sync.Mutex
}
func (sb *SafeBuffer) Write(data []byte) (int, error) {
sb.mu.Lock()
defer sb.mu.Unlock()
return sb.b.Write(data)
}
func (sb *SafeBuffer) Read(data []byte) (int, error) {
sb.mu.Lock()
defer sb.mu.Unlock()
return sb.b.Read(data)
}
func (sb *SafeBuffer) Len() int {
sb.mu.Lock()
defer sb.mu.Unlock()
return sb.b.Len()
}