Timers in Prolog

Our first example demonstrates timers in Prolog. Timers allow us to execute code at a specific point in the future or repeatedly at intervals. We’ll focus on timers in this example.

:- use_module(library(system)).

main :-
    % Timers represent a single event in the future. You
    % tell the timer how long you want to wait, and it
    % will notify you when that time has elapsed.
    % This timer will wait 2 seconds.
    get_time(Start),
    sleep(2),
    get_time(End),
    TimerDuration is End - Start,
    format('Timer 1 fired after ~2f seconds~n', [TimerDuration]),

    % If you just wanted to wait, you could have used
    % sleep/1. One reason a timer may be useful is
    % that you can cancel it before it fires.
    % Here's an example of that.
    thread_create(timer2, Timer2Id, []),
    thread_signal(Timer2Id, throw(stop)),
    thread_join(Timer2Id, Result),
    (   Result == stopped
    ->  format('Timer 2 stopped~n')
    ;   true
    ),

    % Give the timer2 enough time to fire, if it ever
    % was going to, to show it is in fact stopped.
    sleep(2).

timer2 :-
    catch(
        (   sleep(1),
            format('Timer 2 fired~n')
        ),
        stop,
        format('Timer 2 stopped~n')
    ).

To run the program, save it as timers.pl and use your Prolog interpreter. For example, with SWI-Prolog:

$ swipl -q -t main -s timers.pl
Timer 1 fired after 2.00 seconds
Timer 2 stopped

In this Prolog version:

  1. We use get_time/1 and sleep/1 to simulate a timer. After sleeping for 2 seconds, we calculate and print the elapsed time.

  2. To demonstrate cancelling a timer, we create a separate thread for the second timer using thread_create/3. We then immediately send a stop signal to this thread using thread_signal/2.

  3. The timer2/0 predicate uses a catch/3 to handle the stop signal. If it receives the signal, it prints “Timer 2 stopped” instead of firing.

  4. We use sleep/1 at the end to give enough time for Timer 2 to fire if it wasn’t stopped.

This example showcases how to work with time and threads in Prolog to achieve similar functionality to Go’s timers. The concepts are similar, but the implementation details differ due to the nature of Prolog as a logic programming language.