New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: add WaitTimeout method to Cond #9578

Closed
runner-mei opened this Issue Jan 13, 2015 · 9 comments

Comments

Projects
None yet
8 participants
@runner-mei
Copy link

runner-mei commented Jan 13, 2015

can add func (c *Cond) WaitTimeout(timeout time.Duration) bool for sync.Cond,

example:
...
if !this.c.WaitTimeout(10 * time.Second) {
return errors.New("time out")
}
...

@adg adg changed the title can add func (c *Cond) WaitTimeout(timeout time.Duration) bool for sync.Cond sync: add WaitTimeout method to Cond Jan 13, 2015

@adg adg added the feature label Jan 13, 2015

@adg

This comment has been minimized.

Copy link
Contributor

adg commented Jan 13, 2015

Here's how you can do it:

done := make(chan struct{})
go func() {
  cond.Wait()
  close(done)
}()
select {
case <-time.After(timeout):
  // timed out
case <-done:
  // Wait returned
}
@bradfitz

This comment has been minimized.

Copy link
Member

bradfitz commented Jan 13, 2015

That's how you do it at a lot of cost (goroutine + 2 channels). The OP might be asking for scheduler integration.

@runner-mei, why do you want this?

@minux

This comment has been minimized.

Copy link
Member

minux commented Jan 13, 2015

The problem of timed wait is that for normal use cases, you also
want kill the task to avoid leaking/wasting resources. but that's not
going to happen for goroutine, you will need to do your own framework
to have killable tasks, but in that case, you will definitely need to write
your own timed wait.

However, if the requirement is not waiting and killing the task if it
executes too long, I think using sync.Cond is the wrong solution.
You should use channel to signal readiness and then it's trivial
to use select and time.After for timeout.

It all depend on the use case.

@runner-mei

This comment has been minimized.

Copy link

runner-mei commented Jan 13, 2015

my case is:

next_id := 0

// goroutine (net read):
for {
   id := recv() // read from network
   mu.Lock()
   next_id = id
   mu.Unlock()
   cond.Broadcast()
}

// goroutine n:  0 <= n < 100 in any time
func wait(id int, t time.Duration) bool {
   mu.Lock()
   defer mu.Unlock()
   start_at := time.Now()
   for next_id < id {
      if  t >= 0 {
         return false
      }

      if !cond.WaitTimeout(t) {
        return false
      }
      t = time.Now().Sub(start_at)
   }
   return true
}

Create cost of channel is too high, because calling too often

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

ianlancetaylor commented Jan 13, 2015

Condition variables are generally not the right thing to use in Go, it's hard for me to see why we should add features to them.

@rsc

This comment has been minimized.

Copy link
Contributor

rsc commented Apr 10, 2015

I agree with Ian.

@rsc rsc closed this Apr 10, 2015

@dtromb

This comment has been minimized.

Copy link

dtromb commented Apr 28, 2015

"Condition variables are generally not the right thing to use in Go, it's hard for me to see why we should add features to them."

@ianlancetaylor - Please provide a reasonable alternative or a "Go-like" way to do this, here, then?

You haven't neglected to add a feature, you've taken /away/ a feature from the more-or-less standard set of stuff any systems programmer expects to find where a Mutex/Cond pattern is provided. All thre threading libraries I know directly support this, and I cannot find any good alternatives. (Yes, I've read https://blog.golang.org/pipelines The question(s) are about accomplishing this standard pattern w/o the cost of creating lightweight tasks or additional object allocations - it often happens in extremely tight loops)

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

ianlancetaylor commented Apr 28, 2015

If you carefully design an abstract problem so that you must have condition variables and can not use channels, then, yes, there are cases where a timeout on a condition variable becomes useful. In Go, however, we prefer channels. Mutexes have their uses in Go. Condition variables are almost always better implemented using channels.

To say more requires discussing a specific problem.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

ianlancetaylor commented Apr 28, 2015

Sorry, I should also have said: this is a discussion to have on the mailing list golang-nuts@googlegroups.com, not on a closed issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.