RosettaCodeData/Task/Active-object/OoRexx/active-object.rexx

75 lines
1.8 KiB
Rexx

integrater = .integrater~new(.routines~sine) -- start the integrater function
call syssleep 2
integrater~input = .routines~zero -- update the integrater function
call syssleep .5
say integrater~output
integrater~stop -- terminate the updater thread
::class integrater
::method init
expose stopped start v last_v last_t k
use strict arg k
stopped = .false
start = .datetime~new -- initial time stamp
v = 0
last_v = 0
last_t = 0
self~input = k
self~start
-- spin off a new thread and start updating. Note, this method is unguarded
-- to allow other threads to make calls
::method start unguarded
expose stopped
reply -- this spins this method invocation off onto a new thread
do while \stopped
call sysSleep .1
self~update -- perform the update operation
end
-- turn off the thread. Since this is unguarded,
-- it can be called any time, any where
::method stop unguarded
expose stopped
stopped = .true
-- perform the update. Since this is a guarded method, the object
-- start is protected.
::method update
expose start v last_v t last_t k
numeric digits 20 -- give a lot of precision
current = .datetime~new
t = (current - start)~microseconds
new_v = k~call(t) -- call the input function
v += (last_v + new_v) * (t - last_t) / 2
last_t = t
last_v = new_v
say new value is v
-- a write-only attribute setter (this is GUARDED)
::attribute input SET
expose k last_t last_v
self~update -- update current values
use strict arg k -- update the call function to the provided value
last_t = 0
last_v = k~call(0) -- and update to the zero value
-- the output function...returns current calculated value
::attribute output GET
expose v
return v
::routine zero
return 0
::routine sine
use arg t
return rxcalcsin(rxcalcpi() * t)
::requires rxmath library