Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
76
Task/Active-object/Crystal/active-object.crystal
Normal file
76
Task/Active-object/Crystal/active-object.crystal
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
require "math"
|
||||
require "time"
|
||||
|
||||
# this enum allows us to specify what type of message the proc_chan received.
|
||||
# this trivial example only has one action, but more enum members can be added
|
||||
# to update the proc, or take other actions
|
||||
enum Action
|
||||
Finished # we've waited long enough, and are asking for our result
|
||||
# Update # potential member representing an update to the integrator function
|
||||
end
|
||||
|
||||
class Integrator
|
||||
property interval : Float64
|
||||
getter s : Float64 = 0f64
|
||||
|
||||
# initialize our k function as a proc that takes a float and just returns 0
|
||||
getter k : Proc(Float64, Float64) = ->(t : Float64) { 0f64 }
|
||||
|
||||
# channels used for communicating with the main fiber
|
||||
@proc_chan : Channel(Tuple(Action, Proc(Float64, Float64)|Nil))
|
||||
@result_chan : Channel(Float64)
|
||||
|
||||
def initialize(@k, @proc_chan, @result_chan, @interval = 1e-4)
|
||||
# use a monotonic clock for accuracy
|
||||
start = Time.monotonic.total_seconds
|
||||
t0, k0 = 0f64, @k.call(0f64)
|
||||
|
||||
loop do
|
||||
# this sleep returns control to the main fiber. if the main fiber hasn't finished sleeping,
|
||||
# control will be returned to this loop
|
||||
sleep interval.seconds
|
||||
# check the channel to see if the function has changed
|
||||
self.check_channel()
|
||||
t1 = Time.monotonic.total_seconds - start
|
||||
k1 = @k.call(t1)
|
||||
@s += (k1 + k0) * (t1 - t0) / 2.0
|
||||
t0, k0 = t1, k1
|
||||
end
|
||||
end
|
||||
|
||||
# check the proc_chan for messages, update the integrator function or send the result as needed
|
||||
def check_channel
|
||||
select
|
||||
when message = @proc_chan.receive
|
||||
action, new_k = message
|
||||
case action
|
||||
when Action::Finished
|
||||
@result_chan.send @s
|
||||
@k = new_k unless new_k.nil?
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# this channel allows us to update the integrator function,
|
||||
# and inform the integrator to send the result over the result channel
|
||||
proc_chan = Channel(Tuple(Action, Proc(Float64, Float64)|Nil)).new
|
||||
|
||||
# channel used to return the result from the integrator
|
||||
result_chan = Channel(Float64).new
|
||||
|
||||
# run everything in a new top-level fiber to avoid shared memory issues.
|
||||
# since the fiber immediately sleeps, control is returned to the main code.
|
||||
# the main code then sleeps for two seconds, returning control to our state_clock fiber.
|
||||
# when two seconds is up, this state_clock fiber will return control
|
||||
# to the main code on the next `sleep interval.seconds`
|
||||
spawn name: "state_clock" do
|
||||
ai = Integrator.new ->(t : Float64) { Math.sin(Math::PI * t) }, proc_chan, result_chan
|
||||
end
|
||||
|
||||
sleep 2.seconds
|
||||
proc_chan.send({Action::Finished, ->(t : Float64) { 0f64 }})
|
||||
sleep 0.5.seconds
|
||||
puts result_chan.receive
|
||||
Loading…
Add table
Add a link
Reference in a new issue