Active object: Difference between revisions
Content added Content deleted
m (→classes: += now supported) |
|||
Line 1,589: | 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. |
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}}== |
=={{header|ooRexx}}== |