97 lines
1.4 KiB
Go
97 lines
1.4 KiB
Go
package payload
|
|
|
|
import "sync"
|
|
|
|
type pauserStatus int
|
|
|
|
const (
|
|
statusNormal pauserStatus = iota
|
|
statusPausing
|
|
statusPaused
|
|
)
|
|
|
|
type pauser struct {
|
|
l sync.Mutex
|
|
c *sync.Cond
|
|
worker int
|
|
pausing chan struct{}
|
|
paused chan struct{}
|
|
status pauserStatus
|
|
}
|
|
|
|
func newPauser() *pauser {
|
|
ret := &pauser{
|
|
pausing: make(chan struct{}),
|
|
paused: make(chan struct{}),
|
|
status: statusNormal,
|
|
}
|
|
ret.c = sync.NewCond(&ret.l)
|
|
return ret
|
|
}
|
|
|
|
func (p *pauser) Pause() bool {
|
|
p.l.Lock()
|
|
defer p.l.Unlock()
|
|
|
|
switch p.status {
|
|
case statusPaused:
|
|
return false
|
|
case statusNormal:
|
|
close(p.pausing)
|
|
p.status = statusPausing
|
|
}
|
|
|
|
for p.worker != 0 {
|
|
p.c.Wait()
|
|
}
|
|
|
|
if p.status == statusPaused {
|
|
return false
|
|
}
|
|
close(p.paused)
|
|
p.status = statusPaused
|
|
p.c.Broadcast()
|
|
|
|
return true
|
|
}
|
|
|
|
func (p *pauser) Resume() {
|
|
p.l.Lock()
|
|
defer p.l.Unlock()
|
|
p.status = statusNormal
|
|
p.paused = make(chan struct{})
|
|
p.pausing = make(chan struct{})
|
|
}
|
|
|
|
func (p *pauser) Working() bool {
|
|
p.l.Lock()
|
|
defer p.l.Unlock()
|
|
if p.status == statusPaused {
|
|
return false
|
|
}
|
|
p.worker++
|
|
return true
|
|
}
|
|
|
|
func (p *pauser) Done() {
|
|
p.l.Lock()
|
|
defer p.l.Unlock()
|
|
if p.status == statusPaused || p.worker == 0 {
|
|
return
|
|
}
|
|
p.worker--
|
|
p.c.Broadcast()
|
|
}
|
|
|
|
func (p *pauser) PausingTrigger() <-chan struct{} {
|
|
p.l.Lock()
|
|
defer p.l.Unlock()
|
|
return p.pausing
|
|
}
|
|
|
|
func (p *pauser) PausedTrigger() <-chan struct{} {
|
|
p.l.Lock()
|
|
defer p.l.Unlock()
|
|
return p.paused
|
|
}
|