@@ -357,3 +357,60 @@ So the function that executes the election timer based on some conditions is thi
357
357
358
358
{% endhighlight %}
359
359
360
+ ## Refactoring timer event code
361
+
362
+ The key requirement that lead to this is a mechanism to pause and restart the timer at various stages. Further testing
363
+ may disprove this hypothesis but for now we will try to reuse the timer instead of discarding and starting a new one.
364
+
365
+ The OCaml eio library has just such a facility. It is cleaner than the original timer shown above.
366
+ I have shown only that part of the code below.
367
+
368
+ {% highlight ocaml %}
369
+
370
+ let unpaused = ref (Promise.create_resolved ())
371
+ let unpaused_resolver = ref None
372
+
373
+ let pause () =
374
+ let p, r = Promise.create() in
375
+ unpaused := p;
376
+ unpaused_resolver := Some r
377
+
378
+ let unpause () =
379
+ match !unpaused_resolver with
380
+ | Some r ->
381
+ Promise.resolve r ()
382
+ | None -> ()
383
+
384
+ let periodic_timer env =
385
+ Eio.Switch.run @@ fun _ ->
386
+ let timeout_duration = election_timeout in
387
+ let term_started = current_term.currentterm in
388
+ let mutex = Eio.Mutex.create() in
389
+ let cond = Eio.Condition.create () in
390
+ let clock = Eio.Stdenv.clock env in
391
+ Fiber.both (fun () ->
392
+ while true do
393
+ Promise.await !unpaused;
394
+ Eio.Condition.broadcast cond;
395
+ Eio.Time.sleep clock 0.5;
396
+ done
397
+ )
398
+
399
+ (fun () ->
400
+ let rec loop () =
401
+ traceln "Waiting for timer event ";
402
+ await_timeout cond;
403
+ checkelection_state mutex timeout_duration term_started;
404
+
405
+ traceln "timer event ";
406
+ Fiber.yield ();
407
+ loop ()
408
+ in
409
+ loop ()
410
+ );
411
+
412
+
413
+ {% endhighlight %}
414
+
415
+ This code facilitates a mechanism that allows use to _ pause_ the timer when we don't need it and start
416
+ it again.
0 commit comments