Active object: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (syntax highlighting fixup automation)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(6 intermediate revisions by 5 users not shown)
Line 1:
[[Category:Object oriented]]
{{task|Concurrency}}
[[Category:Object oriented]]{{requires|Concurrency}}{{requires|Objects}}{{requires|Mutable State}}
 
In [[object-oriented programming]] an object is active when its state depends on clock. Usually an active object encapsulates a [[task]] that updates the object's state. To the outer world the object looks like a normal object with methods that can be called from outside. Implementation of such methods must have a certain synchronization mechanism with the encapsulated task in order to prevent object's state corruption.
Line 18 ⟶ 19:
Verify that now the object's output is approximately 0 (the sine has the period of 2s). The accuracy of the result will depend on the [[OS]] scheduler time slicing and the accuracy of the clock.
 
{{omit from|VBScript}}
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Calendar; use Ada.Calendar;
with Ada.Numerics; use Ada.Numerics;
with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions;
Line 91:
</pre>
 
=={{header|BBC BASICATS}}==
 
No memory management is needed. Everything is done in registers or on the stack, including the closure that is used to connect signal source and integrator.
 
The core code is templates for any floating point type, but, in the end, one must choose a type. Our choice is C '''float''' type.
 
<syntaxhighlight lang="ats">
(*------------------------------------------------------------------*)
(* I will not bother with threads. All we need is the ability to get
the time from the operating system. This is available as
clock(3). *)
 
#define ATS_PACKNAME "rosettacode.activeobject"
#define ATS_EXTERN_PREFIX "rosettacode_activeobject_"
 
#include "share/atspre_staload.hats"
 
(*------------------------------------------------------------------*)
(* Some math functionality, for all the standard floating point
types. The ats2-xprelude package includes this, and more, but one
may wish to avoid the dependency. And there is support for math
functions in libats/libc, but not with typekinds. *)
 
%{^
#include <math.h>
// sinpi(3) would be better than sin(3), but I do not yet have
// sinpi(3).
#define rosettacode_activeobject_pi \
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214L
#define rosettacode_activeobject_sinpi_float(x) \
(sinf (((atstype_float) rosettacode_activeobject_pi) * (x)))
#define rosettacode_activeobject_sinpi_double \
(sin (((atstype_double) rosettacode_activeobject_pi) * (x)))
#define rosettacode_activeobject_sinpi_ldouble \
(sinl (((atstype_ldouble) rosettacode_activeobject_pi) * (x)))
%}
 
extern fn sinpi_float : float -<> float = "mac#%"
extern fn sinpi_double : double -<> double = "mac#%"
extern fn sinpi_ldouble : ldouble -<> ldouble = "mac#%"
extern fn {tk : tkind} g0float_sinpi : g0float tk -<> g0float tk
implement g0float_sinpi<fltknd> x = sinpi_float x
implement g0float_sinpi<dblknd> x = sinpi_double x
implement g0float_sinpi<ldblknd> x = sinpi_ldouble x
 
overload sinpi with g0float_sinpi
 
(*------------------------------------------------------------------*)
(* Some clock(3) functionality for the three standard floating point
types. *)
 
%{^
#include <time.h>
 
typedef clock_t rosettacode_activeobject_clock_t;
 
ATSinline() rosettacode_activeobject_clock_t
rosettacode_activeobject_clock () // C23 drops the need for "void".
{
return clock ();
}
 
ATSinline() rosettacode_activeobject_clock_t
rosettacode_activeobject_clock_difference
(rosettacode_activeobject_clock_t t,
rosettacode_activeobject_clock_t t0)
{
return (t - t0);
}
 
ATSinline() atstype_float
rosettacode_activeobject_clock_scaled2float
(rosettacode_activeobject_clock_t t)
{
return ((atstype_float) t) / CLOCKS_PER_SEC;
}
 
ATSinline() atstype_double
rosettacode_activeobject_clock_scaled2double
(rosettacode_activeobject_clock_t t)
{
return ((atstype_double) t) / CLOCKS_PER_SEC;
}
 
ATSinline() atstype_ldouble
rosettacode_activeobject_clock_scaled2ldouble
(rosettacode_activeobject_clock_t t)
{
return ((atstype_ldouble) t) / CLOCKS_PER_SEC;
}
%}
 
typedef clock_t = $extype"clock_t"
extern fn clock : () -<> clock_t = "mac#%"
extern fn clock_difference : (clock_t, clock_t) -<> clock_t = "mac#%"
extern fn clock_scaled2float : clock_t -<> float = "mac#%"
extern fn clock_scaled2double : clock_t -<> double = "mac#%"
extern fn clock_scaled2ldouble : clock_t -<> ldouble = "mac#%"
 
extern fn {tk : tkind} clock_scaled2g0float : clock_t -<> g0float tk
 
implement clock_scaled2g0float<fltknd> t = clock_scaled2float t
implement clock_scaled2g0float<dblknd> t = clock_scaled2double t
implement clock_scaled2g0float<ldblknd> t = clock_scaled2ldouble t
 
overload - with clock_difference
overload clock2f with clock_scaled2g0float
 
(*------------------------------------------------------------------*)
 
%{^
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
// A small, machine-dependent pause, for improved performance of spin
// loops.
#define rosettacode_activeobject_pause() __builtin_ia32_pause ()
#else
// Failure to insert a small, machine-dependent pause may overwork
// your hardware, but the task can be done anyway.
#define rosettacode_activeobject_pause() do{}while(0)
#endif
%}
 
extern fn pause : () -<> void = "mac#%"
 
(*------------------------------------------------------------------*)
 
(* Types such as this can have their internals hidden, but here I will
not bother with such details. *)
vtypedef sinusoidal_generator (tk : tkind) =
@{
phase = g0float tk,
afreq = g0float tk, (* angular frequency IN UNITS OF 2*pi. *)
clock0 = clock_t,
stopped = bool
}
 
fn {tk : tkind}
sinusoidal_generator_Initize
(gen : &sinusoidal_generator tk?
>> sinusoidal_generator tk,
phase : g0float tk,
afreq : g0float tk) : void =
gen := @{phase = phase,
afreq = afreq,
clock0 = clock (),
stopped = true}
 
fn {tk : tkind}
sinusoidal_generator_Start
(gen : &sinusoidal_generator tk) : void =
gen.stopped := false
 
(* IMO changing the integrator's input is bad OO design: akin to
unplugging one generator and plugging in another. What we REALLY
want is to have the generator produce a different signal. So
gen.Stop() will connect the output to a constant
zero. (Alternatively, the channel between the signal source and the
integrator could effect the shutoff.) *)
fn {tk : tkind}
sinusoidal_generator_Stop
(gen : &sinusoidal_generator tk) : void =
gen.stopped := true
 
fn {tk : tkind}
sinusoidal_generator_Sample
(gen : !sinusoidal_generator tk) : g0float tk =
let
val @{phase = phase,
afreq = afreq,
clock0 = clock0,
stopped = stopped} = gen
in
if stopped then
g0i2f 0
else
let
val t = (clock2f (clock () - clock0)) : g0float tk
in
sinpi ((afreq * t) + phase)
end
end
 
overload .Initize with sinusoidal_generator_Initize
overload .Start with sinusoidal_generator_Start
overload .Stop with sinusoidal_generator_Stop
overload .Sample with sinusoidal_generator_Sample
 
(*------------------------------------------------------------------*)
 
vtypedef inputter (tk : tkind, p : addr) =
(* This is a closure type that can reside either in the heap or on
the stack. *)
@((() -<clo1> g0float tk) @ p | ptr p)
 
vtypedef active_integrator (tk : tkind, p : addr) =
@{
inputter = inputter (tk, p),
t_last = clock_t,
sample_last = g0float tk,
integral = g0float tk
}
vtypedef active_integrator (tk : tkind) =
[p : addr] active_integrator (tk, p)
 
fn {tk : tkind}
active_integrator_Input
{p : addr}
(igrator : &active_integrator tk?
>> active_integrator (tk, p),
inputter : inputter (tk, p)) : void =
let
val now = clock ()
in
igrator := @{inputter = inputter,
t_last = now,
sample_last = g0i2f 0,
integral = g0i2f 0}
end
 
fn {tk : tkind}
active_integrator_Output
{p : addr}
(igrator : !active_integrator (tk, p)) : g0float tk =
igrator.integral
 
fn {tk : tkind}
active_integrator_Integrate
{p : addr}
(igrator : &active_integrator (tk, p)) : void =
let
val @{inputter = @(pf | p),
t_last = t_last,
sample_last = sample_last,
integral = integral} = igrator
macdef inputter_closure = !p
 
val t_now = clock ()
val sample_now = inputter_closure ()
 
val integral = integral + ((sample_last + sample_now)
* clock2f (t_last - t_now)
* g0f2f 0.5)
val sample_last = sample_now
val t_last = t_now
 
val () = igrator := @{inputter = @(pf | p),
t_last = t_last,
sample_last = sample_last,
integral = integral}
in
end
 
overload .Input with active_integrator_Input
overload .Output with active_integrator_Output
overload .Integrate with active_integrator_Integrate
 
(*------------------------------------------------------------------*)
 
implement
main () =
let
(* We put on the stack all objects that are not in registers. Thus
we avoid the need for malloc/free. *)
 
vtypedef gen_vt = sinusoidal_generator float_kind
vtypedef igrator_vt = active_integrator float_kind
 
var gen : gen_vt
var igrator : igrator_vt
 
val phase = 0.0f
and afreq = 1.0f (* Frequency of 0.5 Hz. *)
val () = gen.Initize (phase, afreq)
val () = gen.Start ()
 
(* Create a thunk on the stack. This thunk acts as a channel
between the sinusoidal generator and the active integrator. We
could probably work this step into the OO style of most of the
code, but doing that is left as an exercise. The mechanics of
creating a closure on the stack are already enough for a person
to absorb. (Of course, rather than use a closure, we could have
set up a type hierarchy. However, IMO a type hierarchy is
needlessly clumsy. Joining the objects with a closure lets any
thunk of the correct type serve as input.) *)
val p_gen = addr@ gen
var gen_clo_on_stack =
lam@ () : float =<clo1>
let
(* A little unsafeness is needed here. AFAIK there is no way
to SAFELY enclose the stack variable "gen" in the
closure. A negative effect is that (at least without some
elaborate scheme) it becomes POSSIBLE to use this
closure, even after "gen" has been destroyed. But we will
be careful not to do that. *)
extern praxi p2view :
{p : addr} ptr p -<prf>
(gen_vt @ p, gen_vt @ p -<lin,prf> void)
prval @(pf, fpf) = p2view p_gen
macdef gen = !p_gen
val sample = gen.Sample ()
prval () = fpf pf
in
sample
end
val sinusoidal_inputter =
@(view@ gen_clo_on_stack | addr@ gen_clo_on_stack)
 
val () = igrator.Input (sinusoidal_inputter)
 
fn {}
integrate_for_seconds
(igrator : &igrator_vt,
seconds : float) : void =
let
val t0 = clock2f (clock ())
fun
loop (igrator : &igrator_vt) : void =
if clock2f (clock ()) - t0 < seconds then
begin
igrator.Integrate ();
pause ();
loop igrator
end
in
loop igrator
end
 
(* Start the sinusoid and then integrate for 2.0 seconds. *)
val () = gen.Start ()
val () = integrate_for_seconds (igrator, 2.0f)
 
(* Stop the sinusoid and then integrate for 0.5 seconds. *)
val () = gen.Stop ()
val () = integrate_for_seconds (igrator, 0.5f)
 
val () = println! ("integrator output = ", igrator.Output ());
 
(* The following "prval" lines are necessary for type-safety, and
produce no executable code. *)
prval @{inputter = @(pf | _),
t_last = _,
sample_last = _,
integral = _} = igrator
prval () = view@ gen_clo_on_stack := pf
in
0
end
 
(*------------------------------------------------------------------*)
</syntaxhighlight>
 
{{out}}
One will get different results on different runs.
<pre>$ patscc -std=gnu2x -Ofast active_object_task.dats -lm && ./a.out
integrator output = -0.000002</pre>
 
=={{header|BASIC}}==
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> INSTALL @lib$+"CLASSLIB"
INSTALL @lib$+"TIMERLIB"
INSTALL @lib$+"NOWAIT"
Line 125 ⟶ 482:
{{libheader|pthread}}
 
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
Line 200 ⟶ 557:
=={{header|C sharp|C#}}==
{{works with|C# 6}}
<syntaxhighlight lang="csharp">using System;
using System.Threading.Tasks;
 
Line 284 ⟶ 641:
=={{header|C++}}==
{{works with|C++14|}}
<syntaxhighlight lang="cpp">#include <atomic>
#include <chrono>
#include <cmath>
Line 341 ⟶ 698:
void Integrator::do_work()
{
while (continue_.test_and_set()) {
integrate();
std::this_thread::sleep_for(1ms);
Line 353 ⟶ 710:
dur_t start = t_prev - beginning;
dur_t fin = now - beginning;
if (func)
state += (func(start.count()) + func(fin.count())) * (fin - start).count() / 2;
t_prev = now;
Line 377 ⟶ 734:
 
=={{header|Clojure}}==
<syntaxhighlight lang="clojure">(ns active-object
(:import (java.util Timer TimerTask)))
 
Line 418 ⟶ 775:
{{libheader|Bordeaux Threads}}
 
<syntaxhighlight lang="lisp">
(defclass integrator ()
((input :initarg :input :writer input :reader %input)
Line 507 ⟶ 864:
{{trans|Python}}
Crystal currently runs all code in a single thread, so a trivial example wouldn't have any issues with thread safety. However, this behavior will likely change in the future. This example was written with that in mind, and is somewhat more complex to show better idioms and be future-proof.
<syntaxhighlight lang="ruby">require "math"
require "time"
 
Line 591 ⟶ 948:
=={{header|D}}==
{{trans|Java}}
<syntaxhighlight lang=D"d">import core.thread;
import std.datetime;
import std.math;
Line 671 ⟶ 1,028:
{{libheader| System.Classes}}
{{Trans|Python}}
<syntaxhighlight lang=Delphi"delphi">
program Active_object;
 
Line 765 ⟶ 1,122:
=={{header|E}}==
 
<syntaxhighlight lang="e">def makeIntegrator() {
var value := 0.0
var input := fn { 0.0 }
Line 819 ⟶ 1,176:
=={{header|EchoLisp}}==
We use the functions (at ..) : scheduling, (wait ...), and (every ...) ot the timer.lib. The accuracy will be function of the browser's functions setTimeout and setInterval ...
<syntaxhighlight lang="lisp">
(require 'timer)
Line 852 ⟶ 1,209:
</syntaxhighlight>
{{Out}}
<syntaxhighlight lang="lisp">
(define (experiment)
(define (K t) (sin (* PI t )))
Line 876 ⟶ 1,233:
=={{header|Erlang}}==
I could not see what time to use between each integration so it is the argument to task().
<syntaxhighlight lang=Erlang"erlang">
-module( active_object ).
-export( [delete/1, input/2, new/0, output/1, task/1] ).
Line 942 ⟶ 1,299:
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">open System
open System.Threading
 
Line 988 ⟶ 1,345:
=={{header|Factor}}==
Working with dynamic quotations requires the stack effect to be known in advance. The apply-stack-effect serves this purpose.
<syntaxhighlight lang="factor">USING: accessors alarms calendar combinators kernel locals math
math.constants math.functions prettyprint system threads ;
IN: rosettacode.active
Line 1,034 ⟶ 1,391:
=={{header|FBSL}}==
The Dynamic Assembler and Dynamic C JIT compilers integrated in FBSL v3.5 handle multithreading perfectly well. However, pure FBSL infrastructure has never been designed especially to support own multithreading nor can it handle long long integers natively. Yet a number of tasks with careful design and planning are quite feasible in pure FBSL too:
<syntaxhighlight lang="qbasic">#APPTYPE CONSOLE
 
#INCLUDE <Include\Windows.inc>
Line 1,134 ⟶ 1,491:
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">#define twopi 6.2831853071795864769252867665590057684
dim shared as double S = 0 'set up the state as a global variable
dim shared as double t0, t1, ta
Line 1,168 ⟶ 1,525:
=={{header|Go}}==
Using time.Tick to sample K at a constant frequency. Three goroutines are involved, main, aif, and tk. Aif controls access to the accumulator s and the integration function K. Tk and main must talk to aif through channels to access s and K.
<syntaxhighlight lang="go">package main
 
import (
Line 1,255 ⟶ 1,612:
=={{header|Groovy}}==
{{trans|Java}}
<syntaxhighlight lang="groovy">/**
* Integrates input function K over time
* S + (t1 - t0) * (K(t1) + K(t0)) / 2
Line 1,330 ⟶ 1,687:
=={{header|Haskell}}==
 
<syntaxhighlight lang="haskell">module Integrator (
newIntegrator, input, output, stop,
Time, timeInterval
Line 1,412 ⟶ 1,769:
Implementation:
 
<syntaxhighlight lang=J"j">coclass 'activeobject'
require'dates'
 
Line 1,439 ⟶ 1,796:
Task example (code):
 
<syntaxhighlight lang=J"j">cocurrent 'testrig'
 
delay=: 6!:3
Line 1,465 ⟶ 1,822:
 
First column is time relative to start of processing, second column is object's output at that time.
 
=== Using a task thread ===
 
Variant using an independent task thread:
 
<syntaxhighlight lang=J>delay=: 6!:3
 
task=: {{
obj=. '' conew 'integra'
F__obj=: 1 o. o.
delay 2
F__obj=: 0:
delay 0.5
s=. S__obj
destroy__obj''
s
}}
 
coclass'integra'
reqthreads=: {{ 0&T.@''^:(0>.y-1 T.'')0 }}
time=: 6!:1
F=: 0:
K=: S=: SHUTDOWN=: 0
create=: {{
reqthreads cores=. {.8 T. ''
integrator t. '' T=: time''
}}
destroy=: {{ codestroy '' [ SHUTDOWN=: 1 }}
integrator=: {{
while. -.SHUTDOWN do.
t=. time''
k=. F t
S=: S + (k+K)*t-T
T=: t
K=: k
end.
}}
</syntaxhighlight>
 
This exhibits more timing variance because of the loose coupling of scheduling between threads:
 
<syntaxhighlight lang=J> task''
0.0194745
task''
_4.40316e_15
task''
0.00874017
task''
_0.0159841
</syntaxhighlight>
 
=={{header|Java}}==
<syntaxhighlight lang="java">/**
* Integrates input function K over time
* S + (t1 - t0) * (K(t1) + K(t0)) / 2
Line 1,545 ⟶ 1,952:
{{trans|E}}
 
<syntaxhighlight lang="javascript">function Integrator(sampleIntervalMS) {
var inputF = function () { return 0.0 };
var sum = 0.0;
Line 1,574 ⟶ 1,981:
Test program as a HTML fragment:
 
<syntaxhighlight lang="html4strict"><p><span id="a">Test running...</span> <code id="b">-</code></p>
 
<script type="text/javascript">
Line 1,599 ⟶ 2,006:
Julia has inheritance of data structures and first-class types, but structures do not have methods.
Instead, methods are functions with multiple dispatch based on argument type.
<syntaxhighlight lang="julia">mutable struct Integrator
func::Function
runningsum::Float64
Line 1,643 ⟶ 2,050:
{{trans|Java}}
Athough this is a faithful translation of the Java entry, on my machine the output of the latter is typically an order of magnitude smaller than this version. I have no idea why.
<syntaxhighlight lang="scala">// version 1.2.0
 
import kotlin.math.*
Line 1,720 ⟶ 2,127:
=={{header|Lingo}}==
Parent script "Integrator":
<syntaxhighlight lang=Lingo"lingo">property _sum
property _func
property _timeLast
Line 1,763 ⟶ 2,170:
 
In some movie script:
<syntaxhighlight lang=Lingo"lingo">global gIntegrator
 
-- entry point
Line 1,788 ⟶ 2,195:
=={{header|Lua}}==
Pure/native Lua is not multithreaded, so this task should perhaps be marked "omit from|Lua" if following the implicit ''intent'' of the task. However, the explicit ''wording'' of the task does not seem to require a multithreaded solution. Perhaps this is ''cheating'', but I thought it might interest the reader to see the integrator portion nonetheless, so it is demonstrated using a mock sampling method at various intervals (to ''simulate'' multithreaded updates).
<syntaxhighlight lang="lua">local seconds = os.clock
 
local integrator = {
Line 1,839 ⟶ 2,246:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang=Mathematica"mathematica">Block[{start = SessionTime[], K, t0 = 0, t1, kt0, S = 0},
K[t_] = Sin[2 Pi f t] /. f -> 0.5; kt0 = K[t0];
While[True, t1 = SessionTime[] - start;
Line 1,854 ⟶ 2,261:
Of course, it is necessary to take some precautions when accessing or updating the shared object. We use a lock for this purpose.
 
<syntaxhighlight lang="text">
# Active object.
# Compile with "nim c --threads:on".
Line 1,981 ⟶ 2,388:
Not totally certain this is a correct implementation since the value coming out is not close to zero. It does show all of the basics of multithreading and object synchronization though.
 
<syntaxhighlight lang=ooRexx"oorexx">
integrater = .integrater~new(.routines~sine) -- start the integrater function
call syssleep 2
Line 2,064 ⟶ 2,471:
 
With a high precision timer the result is around -.0002
<syntaxhighlight lang="oxygenbasic">
double MainTime
 
Line 2,239 ⟶ 2,646:
 
=={{header|Oz}}==
<syntaxhighlight lang="oz">declare
fun {Const X}
fun {$ _} X end
Line 2,301 ⟶ 2,708:
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict;
Line 2,375 ⟶ 2,782:
{{libheader|Phix/Class}}
 
<!--<syntaxhighlight lang=Phix"phix">-->
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0.8.2"</span><span style="color: #0000FF;">)</span>
Line 2,461 ⟶ 2,868:
Just lock everything, it is not that hard, and you should never need much more than the stuff below.
 
<!--<syntaxhighlight lang=Phix"phix">-->
<span style="color: #004080;">sequence</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">TERMINATE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">INTERVAL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">KFUN</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">VALUE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">T0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">K0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ID</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ISIZE</span><span style="color: #0000FF;">=$</span>
Line 2,534 ⟶ 2,941:
 
=={{header|PicoLisp}}==
<syntaxhighlight lang=PicoLisp"picolisp">(load "@lib/math.l")
 
(class +Active)
Line 2,581 ⟶ 2,988:
=={{header|PureBasic}}==
Using the open-source precompiler [http://www.development-lounge.de/viewtopic.php?t=5915 SimpleOOP].
<syntaxhighlight lang=PureBasic"purebasic">Prototype.d ValueFunction(f.d, t.d)
 
Class IntegralClass
Line 2,659 ⟶ 3,066:
 
 
<syntaxhighlight lang="python">from time import time, sleep
from threading import Thread
 
Line 2,700 ⟶ 3,107:
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">
#lang racket
 
Line 2,738 ⟶ 3,145:
There is some jitter in the timer, but it is typically accurate to within a few thousandths of a second.
 
<syntaxhighlight lang=perl6"raku" line>class Integrator {
has $.f is rw = sub ($t) { 0 };
has $.now is rw;
Line 2,791 ⟶ 3,198:
=={{header|Rust}}==
 
<syntaxhighlight lang="rust">#![feature(mpsc_select)]
 
extern crate num;
Line 2,966 ⟶ 3,373:
=={{header|Scala}}==
 
<syntaxhighlight lang=Scala"scala">object ActiveObject {
 
class Integrator {
Line 3,017 ⟶ 3,424:
=={{header|Smalltalk}}==
 
<syntaxhighlight lang=Smalltalk"smalltalk">
Object subclass:#Integrator
instanceVariableNames:'tickRate input s thread'
Line 3,081 ⟶ 3,488:
</syntaxhighlight>
running:
<syntaxhighlight lang=Smalltalk"smalltalk">Integrator example</syntaxhighlight>
 
output:
Line 3,104 ⟶ 3,511:
=={{header|SuperCollider}}==
Instead of writing a class, here we just use an environment to encapsulate state.
<syntaxhighlight lang=SuperCollider"supercollider">
(
a = TaskProxy { |envir|
Line 3,139 ⟶ 3,546:
 
=={{header|Swift}}==
<syntaxhighlight lang=Swift"swift">// For NSObject, NSTimeInterval and NSThread
import Foundation
// For PI and sin
Line 3,214 ⟶ 3,621:
 
This implementation Tcl 8.6 for object support (for the active integrator object) and coroutine support (for the controller task). It could be rewritten to only use 8.5 plus the TclOO library.
<syntaxhighlight lang=Tcl"tcl">package require Tcl 8.6
oo::class create integrator {
variable e sum delay tBase t0 k0 aid
Line 3,271 ⟶ 3,678:
Since this object is CPU intensive, shutting it down when done is crucial. To facilitate this, the IDisposable pattern was used.
 
<syntaxhighlight lang="vbnet">Module Module1
Sub Main()
Line 3,355 ⟶ 3,762:
 
What I've done instead is to pre-compute the number of updates performed on my machine for a given function and time period which is a fairly stable figure (though it will obviously be different on other machines). I've then used this figure to measure elapsed time for each update. On average this gives results of around 0.003 seconds which I consider acceptable in the circumstances.
<syntaxhighlight lang=ecmascript"wren">import "scheduler" for Scheduler
import "timer" for Timer
 
Line 3,419 ⟶ 3,826:
{{trans|Python}}
Uses cheese ball thread safety: since the integrator runs continuously and I don't want to queue the output, just sample it, strong references are used as they change atomically.
<syntaxhighlight lang="zkl">class Integrator{
// continuously integrate a function `K`, at each `interval` seconds'
fcn init(f,interval=1e-4){
Line 3,438 ⟶ 3,845:
fcn setF(f) { K.set(f) }
}</syntaxhighlight>
<syntaxhighlight lang="zkl">ai:=Integrator(fcn(t){ ((0.0).pi*t).sin() });
Atomic.sleep(2);
ai.sample().println();
Line 3,451 ⟶ 3,858:
</pre>
{{omit from|6502 Assembly|Not an object-oriented language.}}
{{omit from|68000 Assembly}}
{{omit from|8080 Assembly}}
{{omit from|8086 Assembly}}
{{omit from|68000 Assembly}}
{{omit from|ACL2}}
{{omit from|ARM Assembly}}
Line 3,461 ⟶ 3,868:
{{omit from|LaTeX}}
{{omit from|Locomotive Basic}}
{{omit from|Make}}
{{omit from|Metafont}}
{{omit from|M4}}
{{omit from|Make}}
{{omit from|Maxima}}
{{omit from|Metafont}}
{{omit from|ML/I}}
{{omit from|Octave}}
{{omit from|PlainTeX}}
{{omit from|TI-89 BASIC}} <!-- Does not have concurrency or background processes. -->
{{omit from|Retro}}
{{omit from|TI-89 BASIC}} <!-- Does not have concurrency or background processes. -->
{{omit from|UNIX Shell}}
{{omit from|VBScript}}
{{omit from|x86 Assembly}}
{{omit from|Z80 Assembly}}
9,479

edits