Active object: Difference between revisions

m (→‎classes: += now supported)
Line 1,589:
 
Curiously, this value never changes; it is always exactly the same (at 1.1309E-6). Note that closer answers could be achieved by using Mathematica's better interpolation methods, but it would require collecting the data (in a list), which would have a speed penalty large enough to negate the improved estimation.
 
=={{header|Nim}}==
In Nim, objects managed by the garbage collector are allocated in one heap per thread. In order to share an object, the active object, one solution consists to manage it manually and to create it in a shared heap.
 
Of course, it is necessary to take some precautions when accessing or updating the shared object. We use a lock for this purpose.
 
<lang>
# Active object.
# Compile with "nim c --threads:on".
 
import locks
import os
import std/monotimes
 
type
 
# Function to use for integration.
TimeFunction = proc (t: float): float {.gcsafe.}
 
# Integrator object.
Integrator = ptr TIntegrator
TIntegrator = object
k: TimeFunction # The function to integrate.
dt: int # Time interval in milliseconds.
thread: Thread[Integrator] # Thread which does the computation.
s: float # Computed value.
lock: Lock # Lock to manage concurrent accesses.
isRunning: bool # True if integrator is running.
 
#---------------------------------------------------------------------------------------------------
 
proc newIntegrator(f: TimeFunction; dt: int): Integrator =
## Create an integrator.
 
result = cast[Integrator](allocShared(sizeof(TIntegrator)))
result.k = f
result.dt = dt
result.s = 0
result.lock.initLock()
result.isRunning = false
 
#---------------------------------------------------------------------------------------------------
 
proc process(integrator: Integrator) {.thread, gcsafe.} =
## Do the integration.
 
integrator.isRunning = true
let start = getMonotime().ticks
var t0: float = 0
var k0 = integrator.k(0)
while true:
sleep(integrator.dt)
withLock integrator.lock:
if not integrator.isRunning:
break
let t1 = float(getMonoTime().ticks - start) / 1e9
let k1 = integrator.k(t1)
integrator.s += (k1 + k0) * (t1 - t0) / 2
t0 = t1
k0 = k1
 
#---------------------------------------------------------------------------------------------------
 
proc start(integrator: Integrator) =
## Start the integrator by launching a thread to do the computation.
integrator.thread.createThread(process, integrator)
 
#---------------------------------------------------------------------------------------------------
 
proc stop(integrator: Integrator) =
## Stop the integrator.
 
withLock integrator.lock:
integrator.isRunning = false
integrator.thread.joinThread()
 
#---------------------------------------------------------------------------------------------------
 
proc setInput(integrator: Integrator; f: TimeFunction) =
## Set the function.
withLock integrator.lock:
integrator.k = f
 
#---------------------------------------------------------------------------------------------------
 
proc output(integrator: Integrator): float =
## Return the current output.
withLock integrator.lock:
result = integrator.s
 
#---------------------------------------------------------------------------------------------------
 
proc destroy(integrator: Integrator) =
## Destroy an integrator, freing the resources.
 
if integrator.isRunning:
integrator.stop()
integrator.lock.deinitLock()
integrator.deallocShared()
 
#---------------------------------------------------------------------------------------------------
 
from math import PI, sin
 
# Create the integrator and start it.
let integrator = newIntegrator(proc (t: float): float {.gcsafe.} = sin(PI * t), 1)
integrator.start()
echo "Integrator started."
sleep(2000)
echo "Value after 2 seconds: ", integrator.output()
 
# Change the function to use.
integrator.setInput(proc (t: float): float {.gcsafe.} = 0)
echo "K function changed."
sleep(500)
 
# Stop the integrator and display the computed value.
integrator.stop()
echo "Value after 0.5 more second: ", integrator.output()
integrator.destroy()
</lang>
 
{{out}}
<pre>
Integrator started.
Value after 2 seconds: 2.058071586661761e-06
K function changed.
Value after 0.5 more second: -3.007318220146679e-09
</pre>
 
=={{header|ooRexx}}==
Anonymous user