Tickers in Standard ML
Our first example demonstrates the use of tickers, which are used for performing actions repeatedly at regular intervals. Here’s an example of a ticker that ticks periodically until we stop it.
(* We'll use the Time structure for timing operations *)
structure Time = Time
(* We'll simulate channels using references *)
type 'a channel = 'a option ref
(* Function to create a new channel *)
fun newChannel () = ref NONE
(* Function to send a value on a channel *)
fun send (ch: 'a channel) (value: 'a) =
ch := SOME value
(* Function to receive a value from a channel *)
fun receive (ch: 'a channel) =
case !ch of
SOME value => (ch := NONE; SOME value)
| NONE => NONE
(* Main function *)
fun main () =
let
(* Create a ticker that ticks every 500 milliseconds *)
val ticker = ref true
val tickerChannel = newChannel ()
(* Create a done channel *)
val done = newChannel ()
(* Function to simulate the ticker *)
fun tickerFunc () =
if !ticker then
(
send tickerChannel (Time.now());
Time.sleep (Time.fromMilliseconds 500);
tickerFunc ()
)
else
()
(* Start the ticker in a separate thread *)
val _ = Thread.spawn tickerFunc
(* Function to handle ticks *)
fun handleTicks () =
case receive tickerChannel of
SOME t => (
print ("Tick at " ^ Time.toString t ^ "\n");
handleTicks ()
)
| NONE =>
if !(receive done) then
()
else
handleTicks ()
(* Start handling ticks in a separate thread *)
val _ = Thread.spawn handleTicks
(* Sleep for 1600 milliseconds *)
val _ = Time.sleep (Time.fromMilliseconds 1600)
(* Stop the ticker *)
val _ = ticker := false
val _ = send done true
val _ = print "Ticker stopped\n"
in
()
end
(* Run the main function *)
val _ = main ()
In this Standard ML version, we simulate the behavior of channels and tickers using references and threads. The Time
structure is used for timing operations.
We create a ticker that sends a value every 500 milliseconds. We use a separate thread to simulate the ticker’s behavior. Another thread is used to handle the ticks, printing the time of each tick.
The main thread sleeps for 1600 milliseconds, allowing about 3 ticks to occur, and then stops the ticker.
When we run this program, the ticker should tick 3 times before we stop it. The output might look something like this:
Tick at Tue Jul 11 10:30:00 2023
Tick at Tue Jul 11 10:30:00.500 2023
Tick at Tue Jul 11 10:30:01 2023
Ticker stopped
Note that Standard ML doesn’t have built-in support for concurrent operations like channels and tickers. This implementation is a simplified simulation of the concept using threads and shared mutable state, which isn’t idiomatic Standard ML. In a real Standard ML program, you would typically use a different approach to handle periodic events.