indexing description: "Alarm Clock that provides a wake up service for"; "TM_EVENT objects that register with it." "Part of the Time Manager Framework." class TM_CLOCK creation make, make_with_ticks feature register( e : TM_EVENT ) is -- Save `e' for a later callback require e /= Void not is_present( e ) do -- if e.periodic then -- e.set_absolute_time( milliseconds + e.period ) -- else e.set_absolute_time( milliseconds + e.time_to_wake_up ) -- end twl.extend( e ) ensure is_present( e ) num_events = old num_events + 1 end cancel( e : TM_EVENT ) is -- Remove `e' from consideration by the Clock. do twl.start twl.prune( e ) ensure canceled: not is_present( e ) new_num_events: old is_present( e ) implies num_events = old num_events - 1 end purge( t : TM_CLIENT ) is -- Remove all events associated with `t'. do from twl.start until twl.after loop if equal( twl.item.client, t ) then twl.remove end end ensure -- for_all e : TM_EVENT -- ( e.client = t implies not is_present( e )) end replace( o, n : TM_EVENT ) is -- Cancel `o' and register `n'. require n /= Void ; n /= o do cancel( o ) register( n ) ensure not is_present( o ) is_present( n ) end is_present( e : TM_EVENT ) : BOOLEAN is -- Is`e' being managed by the clock? do Result := twl.has( e ) end num_events : INTEGER is -- Number of events currently managed by -- the clock. do Result := twl.count end tick : INTEGER -- The clock's granularity. The smallest time unit the clock -- will track. Measured in milliseconds. minimal_tick : INTEGER -- The platform dependent minimal granularity that the -- system can track. milliseconds : INTEGER -- Time in milliseconds since clock was started or reset. seconds : INTEGER is -- Number of seconds clock has been running since -- originally started or reset. do Result := milliseconds // 1000 ensure Result = milliseconds // 1000 end ticks : INTEGER is -- Number of ticks clock has been running since -- originally started or reset. do Result := milliseconds // tick ensure Result = milliseconds // tick end reset is -- Reset the clock to its initial state do milliseconds := 0 is_running := False twl.wipe_out ensure milliseconds = 0 num_events = 0 -- for_all e : TM_EVENT ( not is_present( e ) ) not is_running end is_running : BOOLEAN -- Is the clock currently running? start is -- Get time moving (again). do is_running := True ensure is_running end stop is -- Stop time in its tracks. do is_running := False ensure not is_running end wake_up is -- Wake up all clients whose time has come. do if is_running then milliseconds := milliseconds + tick wake_clients end end change_tick( t : INTEGER ) is -- Set the application granularity to `t' milliseconds require t > 0 do tick := t ensure tick = t end change_minimal_tick( mt : INTEGER ) is -- Set the platform dependent granularity to `mt' milliseconds do minimal_tick := mt ensure minimal_tick = mt end feature{NONE} twl : SORTED_TWO_WAY_LIST[ TM_EVENT ] wake_clients is -- wake clients whose time has come. local tme : TM_EVENT do from until twl.empty or else twl.first.absolute_time > milliseconds loop twl.start tme := twl.item twl.remove -- tme.client.wake_up( tme ) -- Problem with wake_up here. If part of wakeup is to cancel -- this event then the next line effectively undoes the cancel! -- Move to after the if statement. if tme.periodic then tme.set_absolute_time( milliseconds + tme.period ) twl.extend( tme ) end tme.client.wake_up( tme ) end end make_with_ticks( t, mt : INTEGER ) is require t > 0 ; mt > 0 do tick := t minimal_tick := mt !!twl.make ensure tick = t ; minimal_tick = mt end make is -- Just use defaults do !!twl.make ensure tick = 0 ; minimal_tick = 0 end invariant tick >= 0 -- tick >= minimal_tick milliseconds >= 0 seconds >= 0 ticks >= 0 end