package foobar.util; import java.util.Calendar; /** * A Timer class that can be extended to invoke an action after a specified * number of seconds. It can optionally be configured to synchronize the timer * to the system clock. */ public class Timer { // Specifies the interval (in seconds) at which the timer should run // (The default interval is 30 seconds) public attribute interval: Integer; // Specifies whether the timer should be synchronized to the system clock. // This is useful when creating a timer that fires every minute on the // minute, every hour on the hour etc. public attribute synchronize: Boolean; // Controls whether the timer is running or not. Setting it to true starts // the timer, and setting this attribute to false terminates the timer. public attribute active: Boolean; // A user configurable action that is invoked when the specified interval // expires. This operation must be implemented in the class that extends // this Timer class public operation action(); // An internal counter used to synchronize this timer with the system clock private attribute countdown: Integer; // An internal attribute whose value changes everytime the specified // interval expires. private attribute tick: Integer; ... } attribute Timer.interval = 30; attribute Timer.countdown = 0; // Change the value of tick every time the specified interval expires. During // synchronization, the value of tick is changed every second until the // countdown is completed. attribute Timer.tick = bind if active and synchronize then [1..2] dur 2000 linear while synchronize and active continue if true else if active then [3..4] dur 2*interval*1000 linear while active continue if true else 0; // Invoke the user-specified action when the interval expires. During // synchronization, the action is invoked only when the timer is synchronized // with the clock. trigger on Timer.tick = value { if (active) { if (synchronize) { if (--countdown == 0) { synchronize = false; action(); } } else { action(); } } } // When the timer is enabled, determine the number of seconds to the next // minute and use this value to synchronize (if that attribute is set to true) // the timer with the system clock trigger on Timer.active = value { if (value) { var d: Calendar = Calendar.getInstance(); countdown = d.get(Calendar.SECOND); if (countdown > 0) { countdown = 60 - countdown; } } }