clockwork icon indicating copy to clipboard operation
clockwork copied to clipboard

Add a new interface method: AfterTime

Open maxtaco opened this issue 8 years ago • 2 comments

Without this iterface, there is an unresolvable race condition with After vs. Advance. In one go routine, you might:

    deadline := /* some deadline in the future */;
    wait := deadline.Sub(fc.Now());
    select {
      case <-fc.After(wait):
    }

And in another, you might:

   fc.Advance(3)

The problem is that two go-routines might interleave arbitrarily. The solution is to compute the deadline and to call After atomically, but you can't do that without sleeping on a lock. I believe BlockUntil was partially invented to handle this problem, so that you could call Advance only after you know that the other go-routine was selecting on the After. But it can be quite challenging to figure out which parameter to pass to BlockUntil, especially if your code is happy to let old After calls just dangle until they expire (which otherwise isn't a problem).

The solution is just to add a new interface method, which is to write to a channel after a given time has been surpassed. This feature was basically available internally, but this PR makes it available publicly.

maxtaco avatar Dec 09 '16 21:12 maxtaco

Fyi, #13 seems to fix the problem as well, as it's rewriting the After method to use timers. (At least it fixes the snippet from above)

pierrebeaucamp avatar Jul 12 '18 15:07 pierrebeaucamp

What's the status of this PR? Is there a reason it's been sitting for so long?

muir avatar Jul 27 '22 20:07 muir

I'm not sure I like the idea of adding a non-standard method either. Although I'm not sure I understand the problem completely, sounds like #44 could be a fix for the above. Can you please try and let me know? Thanks!

sagikazarmark avatar Oct 08 '22 07:10 sagikazarmark

Closing with no activity (recent changes may have provided a fix for the root cause).

sagikazarmark avatar Mar 26 '23 00:03 sagikazarmark