123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- package tomb
- import (
- "errors"
- "fmt"
- "sync"
- )
- type Tomb struct {
- m sync.Mutex
- dying chan struct{}
- dead chan struct{}
- reason error
- }
- var (
- ErrStillAlive = errors.New("tomb: still alive")
- ErrDying = errors.New("tomb: dying")
- )
- func (t *Tomb) init() {
- t.m.Lock()
- if t.dead == nil {
- t.dead = make(chan struct{})
- t.dying = make(chan struct{})
- t.reason = ErrStillAlive
- }
- t.m.Unlock()
- }
- func (t *Tomb) Dead() <-chan struct{} {
- t.init()
- return t.dead
- }
- func (t *Tomb) Dying() <-chan struct{} {
- t.init()
- return t.dying
- }
- func (t *Tomb) Wait() error {
- t.init()
- <-t.dead
- t.m.Lock()
- reason := t.reason
- t.m.Unlock()
- return reason
- }
- func (t *Tomb) Done() {
- t.Kill(nil)
- close(t.dead)
- }
- func (t *Tomb) Kill(reason error) {
- t.init()
- t.m.Lock()
- defer t.m.Unlock()
- if reason == ErrDying {
- if t.reason == ErrStillAlive {
- panic("tomb: Kill with ErrDying while still alive")
- }
- return
- }
- if t.reason == nil || t.reason == ErrStillAlive {
- t.reason = reason
- }
-
-
-
- select {
- case <-t.dying:
- default:
- close(t.dying)
- }
- }
- func (t *Tomb) Killf(f string, a ...interface{}) error {
- err := fmt.Errorf(f, a...)
- t.Kill(err)
- return err
- }
- func (t *Tomb) Err() (reason error) {
- t.init()
- t.m.Lock()
- reason = t.reason
- t.m.Unlock()
- return
- }
|