concurrency - How to synchronize multiple goroutines to the termination of a selected goroutine (ie. Thread.join()) -


i asked in previous question, people felt original question not detailed enough ("why ever want timed condition wait??") here more specific one.

i have goroutine running, call server. started, execute amount of time, , thing. then, exit since done.

during execution large number of other goroutines start. call them "client" threads if like. run step a, , step b. then, must wait "server" goroutine finish specified amount of time, , exit status if "server not finished, , run step c if finishes.

(please not tell me how restructure workflow. hypothetical , given. cannot changed.)

a normal, sane way have server thread signal condition variable selectall or broadcast function, , have other threads in timed wait state monitoring condition variable.

func (s *server) join(timemillis int) error {   s.mux.lock()   defer s.mux.unlock()   while !s.isfinished {      err = s.cond.wait(timemillis)      if err != nil {         stepc()      }   }   return err } 

where server enter state isfinished becomes true , broadcast signal condition variable atomically respect mutex. except impoosible, since go not support timed condition waits. (but there broadcast())

so, "go-centric" way this? i've reall of go blogs , documentation, , pattern or equivalent, despite obviousness, never comes up, nor equivalent "reframing" of basic problem - ipc style channels between 1 routine , 1 other routine. yes, there fan-in/fan-out, remember these threads appearing , vanishing. should simple - , crucially /not leave thousands of "wait-state" goroutines hanging around waiting server die when other "branch" of mux channel (the timer) has signalled/.

note of "client" above might started before server goroutine has started (this when channel created), might appear during, , might appear after... in cases should run stepc if , if server has run , exited after timemillis milliseconds post entering join() function...

in general channels facility seems sorely lacking when there's more 1 consumer. "first build registry of channels listeners mapped" , "there's nifty recursive data structure sends on channel holds field" so.not.ok replacements nice, reliable, friendly, obvious: wait(forsometime)

i think want can done selecting on single shared channel, , having server close when it's done.

say create global "exit channel", that's shared across goroutines. can created before "server" goroutine created. important part server goroutine never sends down channel, closes it.

now client goroutines, this:

select {     case <- ch:     fmt.println("channel closed, server done!")     case <-time.after(time.second):     fmt.println("timed out. recovery stuff")  } 

and server goroutine does:

close(ch) 

more complete example:

package main  import(     "fmt"     "time"  )   func waiter(ch chan struct{}) {     fmt.println("doing stuff")      fmt.println("waiting...")      select {         case <- ch:         fmt.println("channel closed")         case <-time.after(time.second):         fmt.println("timed out. recovery stuff")      } }   func main(){      ch := make(chan struct{})      go waiter(ch)     go waiter(ch)     time.sleep(100*time.millisecond)     fmt.println("closing channel")     close(ch)      time.sleep(time.second)  } 

this can abstracted following utility api:

type timedcondition struct {     ch chan struct{} }  func newtimedcondition()*timedcondition {     return &timedcondition {         ch: make(chan struct{}),     } }  func (c *timedcondition)broadcast() {     close(c.ch) }  func (c *timedcondition)wait(t time.duration) error {     select {         // channel closed, meaning broadcast called         case <- c.ch:             return nil         case <-time.after(t):             return errors.new("time out")        } } 

Comments

Popular posts from this blog

java - Spring Data JPA: Why findOne(id) executing delete query internally? -

python - Mongodb How to add addtional information when aggregating? -

java - Incorrect order of records in M-M relationship in hibernate -