Skip to content
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
Closed

sync: add WaitTimeout method to Cond #9578

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

Comments

@runner-mei
Copy link

@runner-mei 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
Copy link
Contributor

@adg 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
Copy link
Contributor

@bradfitz 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
Copy link
Member

@minux 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
Copy link
Author

@runner-mei 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
Copy link
Contributor

@ianlancetaylor 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
Copy link
Contributor

@rsc rsc commented Apr 10, 2015

I agree with Ian.

@rsc rsc closed this Apr 10, 2015
@dtromb
Copy link

@dtromb 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
Copy link
Contributor

@ianlancetaylor 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
Copy link
Contributor

@ianlancetaylor 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.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
8 participants