Timers in Chapel

We often want to execute code at some point in the future, or repeatedly at some interval. Chapel’s built-in timer features make both of these tasks easy. We’ll look at timers in this example.

use Time;
use IO;

proc main() {
    // Timers represent a single event in the future. You
    // tell the timer how long you want to wait, and it
    // will pause the execution for that duration.
    // This timer will wait 2 seconds.
    var timer1 = new Timer();
    timer1.start();
    sleep(2);
    timer1.stop();
    writeln("Timer 1 fired");

    // If you just wanted to wait, you could have used
    // sleep(). One reason a timer may be useful is
    // that you can measure elapsed time.
    // Here's an example of that.
    var timer2 = new Timer();
    timer2.start();

    sync {
        begin {
            sleep(1);
            writeln("Timer 2 fired");
        }
        
        // Stop the timer before it completes
        timer2.stop();
        if timer2.elapsed() < 1 {
            writeln("Timer 2 stopped");
        }
    }

    // Give enough time for the task to complete, if it ever
    // was going to, to show it is in fact stopped.
    sleep(2);
}

The first timer will fire ~2s after we start the program, but the second should be stopped before it has a chance to fire.

$ chpl timers.chpl -o timers
$ ./timers
Timer 1 fired
Timer 2 stopped

In this Chapel version:

  1. We use the Time module for timer and sleep functionality.
  2. Instead of channels, we use Chapel’s sync and begin constructs for concurrency.
  3. The Timer class in Chapel is used to measure elapsed time, rather than scheduling future events.
  4. We use sleep() to simulate waiting, as Chapel doesn’t have a direct equivalent to Go’s timer channels.
  5. The elapsed() method is used to check if the timer was stopped before the sleep completed.

This example demonstrates basic timer usage in Chapel, although the semantics differ slightly from Go due to language differences.