Clocks, based on an idea by Adam Sampson.
A clock is similar to a timer, but it is entirely concerned with logical time, rather than any relation to actual time, and all clocks are entirely independent. A clock has the concept of enrollment, so at any time there are N processes enrolled on the clock. Each process may wait on the clock for a specific time. Once all N enrolled processes are waiting for a time (giving a list of times Ts), the clock moves forward to the next time in Ts.
Let's consider an example. Three processes are enrolled on an Int clock. The current time of the clock is 0. One process asks to wait for time 3, and blocks. A second process asks to wait for time 5, and blocks. Finally, the third process waits for time 3. At this point, the first and third process are free to proceed, and the new clock time is 3. The second process (waiting for time 5) stays waiting until the two processes have returned and waited again.
There is also the option to wait for the next available time. If our two enrolled processes wait again, with the first waiting for time 7, and the third waiting for the next available time, the second and third will wake up, with the new time on the clock being 5 (the first stays waiting for time 7).
There is also the ability for time to wrap around. If all processes are waiting for a time that is before the current time (using less-than from the Ord instance) or just the next available time, the earliest time of those will be taken. So if the current time is 26, and the processes are waiting for 11, 21 and next available time, the first and third will wake up and the new time will be 11. This is particularly useful for using your own algebraic type (data Phase = PhaseA | PhaseB | PhaseC deriving (Eq, Ord)). If you want to, you can use Integer and never use the time wrapping ability (see waitUnbounded).
What the units of a clock mean is entirely up to you. The only requirement is an Ord instance for comparing two times, to use the above rules. The item in a clock may be an Int, a Double, an Integer, or even types like Bool or Either, your own types or newtypes, or things like lists!
The following rules apply to clocks:
Clocks are similar to phased barriers (indeed, both have an instance of Waitable). The fundamental differences are:
This whole module was first added in version 1.2.0.
Normally, when waiting on a clock, if you wait for a time equal to (or earlier than) the current time, you will block until the clock wraps around. Sometimes, however, you may want your clock to never wrap around (and use Integer as the inner type, usually), and want to make sure that if a process waits for the current time or earlier, it returns instantly. That is what this function achieves.
Calling this function with Nothing has indentical behaviour to calling wait with Nothing. If you wait for the current time or earlier, all of the other processes waiting on the clock will remain blocked. Processes who have asked to wait for the current time will remain blocked -- it is generally not useful to mix waitUnbounded and wait on the same clock.
|Creates a clock that starts at the given time. The Show instance is needed to display times in traces.|
|Creates a clock that starts at the given time, and gives it the given label in traces. The Show instance is needed to display times in traces.|
|Produced by Haddock version 2.4.2|