On 22 May 2014 18:08, Peter Waller <
pe...@scraperwiki.com> wrote:
> Thanks rog!
>
> I did look at tomb before writing this, but didn't consider it further
> because it says "A Tomb tracks the lifecycle of a goroutine as alive, dying
> or dead, and the reason for its death." i.e, a single goroutine rather than
> many. I didn't want to have to track each goroutine individually.
I think that sentence in the tomb documentation
is a bit misleading, as the first phase of shutting
down, at least, can involve any number of goroutines.
Specifically, any number of callers can call Kill, and any number of
listeners can wait on Dying.
> Also, in my particular case Tomb and death invoked the wrong image for me,
> since it is a graceful shutdown signal. Also "Done flags the goroutine as
> dead, and should be called a single time", where I want many goroutines to
> be able to signal.
The structure we usually end up having is that there's one goroutine
that acts as a kind of overseer for the rest - it may use a WaitGroup
to wait for the others to die before calling Done. There's no *need*
to use Done or Dead though (see below), although they're convenient
when there are resources to be cleaned up.
> It does seem as though I might be able to use Tomb in my case, but I can't
> tell easily from the documentation, and it looks more complicated than what
> I was after.
FWIW, I believe that the below code implements exactly your
Barrier semantics.
type Barrier struct {
tomb tomb.Tomb
}
func (b *Barrier) Fall() {
b.tomb.Kill(nil)
}
func (b *Barrier) Barrier() <-chan struct{} {
return b.tomb.Dying()
}
cheers,
rog.