Active object: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(48 intermediate revisions by 21 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}}==
<langsyntaxhighlight 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 84 ⟶ 85:
Put_Line ("Integrated" & Float'Image (S) & "s");
I.Shut_Down;
end Test_Integrator;</langsyntaxhighlight>
Sample output:
<pre>
Line 90 ⟶ 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}}
<langsyntaxhighlight lang="bbcbasic"> INSTALL @lib$+"CLASSLIB"
INSTALL @lib$+"TIMERLIB"
INSTALL @lib$+"NOWAIT"
Line 114 ⟶ 472:
PROCwait(50)
PRINT "Final value = " FN(myinteg.output)
PROC_discard(myinteg{})</langsyntaxhighlight>
Output:
<pre>
Line 124 ⟶ 482:
{{libheader|pthread}}
 
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
Line 193 ⟶ 551:
 
return 0;
}</langsyntaxhighlight>
output
<pre>-9.99348e-05</pre>
 
=={{header|C sharp|C#}}==
{{works with|C# 6}}
<langsyntaxhighlight lang="csharp">using System;
using System.Threading.Tasks;
 
Line 276 ⟶ 634:
Console.WriteLine(ao.Value);
}
}</langsyntaxhighlight>
 
Output:
Line 283 ⟶ 641:
=={{header|C++}}==
{{works with|C++14|}}
<langsyntaxhighlight lang="cpp">#include <atomic>
#include <chrono>
#include <cmath>
Line 340 ⟶ 698:
void Integrator::do_work()
{
while (continue_.test_and_set()) {
integrate();
std::this_thread::sleep_for(1ms);
Line 352 ⟶ 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 371 ⟶ 729:
std::this_thread::sleep_for(500ms);
std::cout << foo.output();
}</langsyntaxhighlight>
output
<pre>1.23136e-011</pre>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(ns active-object
(:import (java.util Timer TimerTask)))
 
Line 412 ⟶ 770:
user> (test-integrator)
1.414065859052494E-5
</syntaxhighlight>
</lang>
 
=={{header|Common Lisp}}==
{{libheader|Bordeaux Threads}}
 
<syntaxhighlight lang="lisp">
(defclass integrator ()
((input :initarg :input :writer input :reader %input)
(lock :initform (bt:make-lock) :reader lock)
(start-time :initform (get-internal-real-time) :reader start-time)
(interval :initarg :interval :reader interval)
(thread :reader thread :writer %set-thread)
(area :reader area :initform 0 :accessor %area)))
 
(defmethod shared-initialize
((integrator integrator) slot-names &key (interval nil interval-s-p) &allow-other-keys)
(declare (ignore interval))
(cond
;; Restart the thread if any unsynchronized slots are
;; being initialized
((or
(eql slot-names t)
(member 'thread slot-names)
(member 'interval slot-names)
(member 'start-time slot-names)
(member 'lock slot-names)
interval-s-p)
;; If the instance already has a thread, stop it and wait for it
;; to stop before initializing any slots
(when (slot-boundp integrator 'thread)
(input nil integrator)
(bt:join-thread (thread integrator)))
(call-next-method)
(let* ((now (get-internal-real-time))
(current-value (funcall (%input integrator) (- (start-time integrator) now))))
(%set-thread
(bt:make-thread
(lambda ()
(loop
;; Sleep for the amount required to reach the next interval;
;; mitigates drift from theoretical interval times
(sleep
(mod
(/ (- (start-time integrator) (get-internal-real-time))
internal-time-units-per-second)
(interval integrator)))
(let* ((input
(bt:with-lock-held ((lock integrator))
;; If input is nil, exit the thread
(or (%input integrator) (return))))
(previous-time (shiftf now (get-internal-real-time)))
(previous-value
(shiftf
current-value
(funcall input (/ (- now (start-time integrator)) internal-time-units-per-second)))))
(bt:with-lock-held ((lock integrator))
(incf (%area integrator)
(*
(/ (- now previous-time)
internal-time-units-per-second)
(/ (+ previous-value current-value)
2)))))))
:name "integrator-thread")
integrator)))
(t
;; If lock is not in SLOT-NAMES, it must already be initialized,
;; so it can be taken while slots synchronized to it are set
(bt:with-lock-held ((lock integrator))
(call-next-method)))))
 
(defmethod input :around (new-value (integrator integrator))
(bt:with-lock-held ((lock integrator))
(call-next-method)))
 
(defmethod area :around ((integrator integrator))
(bt:with-lock-held ((lock integrator))
(call-next-method)))
 
(let ((integrator
(make-instance 'integrator
:input (lambda (time) (sin (* 2 pi 0.5 time)))
:interval 1/1000)))
(unwind-protect
(progn
(sleep 2)
(input (constantly 0) integrator)
(sleep 0.5)
(format t "~F~%" (area integrator)))
(input nil integrator)))
</syntaxhighlight>
 
=={{header|Crystal}}==
{{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"
 
# 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</syntaxhighlight>
 
Output:
<pre>
-2.5475883655389925e-10
</pre>
 
=={{header|D}}==
{{trans|Java}}
<syntaxhighlight lang="d">import core.thread;
import std.datetime;
import std.math;
import std.stdio;
 
void main() {
auto func = (double t) => sin(cast(double) PI * t);
Integrator integrator = new Integrator(func);
Thread.sleep(2000.msecs);
 
integrator.setFunc(t => 0.0);
Thread.sleep(500.msecs);
 
integrator.stop();
writeln(integrator.getOutput());
}
 
/**
* Integrates input function K over time
* S + (t1 - t0) * (K(t1) + K(t0)) / 2
*/
public class Integrator {
public alias Function = double function (double);
 
private SysTime start;
private shared bool running;
 
private Function func;
private shared double t0;
private shared double v0;
private shared double sum = 0.0;
 
public this(Function func) {
this.start = Clock.currTime();
setFunc(func);
new Thread({
integrate();
}).start();
}
 
public void setFunc(Function func) {
this.func = func;
v0 = func(0.0);
t0 = 0.0;
}
 
public double getOutput() {
return sum;
}
 
public void stop() {
running = false;
}
 
private void integrate() {
running = true;
while (running) {
Thread.sleep(1.msecs);
update();
}
}
 
private void update() {
import core.atomic;
 
Duration t1 = (Clock.currTime() - start);
double v1 = func(t1.total!"msecs");
double rect = (t1.total!"msecs" - t0) * (v0 + v1) / 2;
atomicOp!"+="(this.sum, rect);
t0 = t1.total!"msecs";
v0 = v1;
}
}</syntaxhighlight>
 
{{out}}
<pre>-3.07837e-13</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| System.Classes}}
{{Trans|Python}}
<syntaxhighlight lang="delphi">
program Active_object;
 
{$APPTYPE CONSOLE}
 
uses
System.SysUtils,
System.Classes;
 
type
TIntegrator = class(TThread)
private
{ Private declarations }
interval, s: double;
IsRunning: Boolean;
protected
procedure Execute; override;
public
k: Tfunc<Double, Double>;
constructor Create(k: Tfunc<Double, Double>; inteval: double = 1e-4); overload;
procedure Join;
end;
 
{ TIntegrator }
 
constructor TIntegrator.Create(k: Tfunc<Double, Double>; inteval: double = 1e-4);
begin
self.interval := Interval;
self.K := k;
self.S := 0.0;
IsRunning := True;
FreeOnTerminate := True;
inherited Create(false);
end;
 
procedure TIntegrator.Execute;
var
interval, t0, k0, t1, k1: double;
start: Cardinal;
begin
inherited;
 
interval := self.interval;
start := GetTickCount;
t0 := 0;
k0 := self.K(0);
 
while IsRunning do
begin
t1 := (GetTickCount - start) / 1000;
k1 := self.K(t1);
self.S := self.S + ((k1 + k0) * (t1 - t0) / 2.0);
t0 := t1;
k0 := k1;
end;
end;
 
procedure TIntegrator.Join;
begin
IsRunning := false;
end;
 
var
Integrator: TIntegrator;
 
begin
Integrator := TIntegrator.create(
function(t: double): double
begin
Result := sin(pi * t);
end);
 
sleep(2000);
 
Writeln(Integrator.s);
 
Integrator.k :=
function(t: double): double
begin
Result := 0;
end;
 
sleep(500);
Writeln(Integrator.s);
Integrator.Join;
Readln;
end.</syntaxhighlight>
{{out}}
<pre>
-1.51242391413465E-0016
-1.51242391413465E-0016
</pre>
=={{header|E}}==
 
<langsyntaxhighlight lang="e">def makeIntegrator() {
var value := 0.0
var input := fn { 0.0 }
Line 465 ⟶ 1,172:
})
return result
}</langsyntaxhighlight>
 
=={{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 ...
<langsyntaxhighlight lang="lisp">
(require 'timer)
Line 500 ⟶ 1,207:
(else (error "active:bad message" message))))))
</syntaxhighlight>
</lang>
{{Out}}
<langsyntaxhighlight lang="lisp">
(define (experiment)
(define (K t) (sin (* PI t )))
Line 522 ⟶ 1,229:
3/7/2015 20:34:28 : result
result 0.00026510586971023164
</syntaxhighlight>
</lang>
 
=={{header|Erlang}}==
I could not see what time to use between each integration so it is the argument to task().
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( active_object ).
-export( [delete/1, input/2, new/0, output/1, task/1] ).
Line 589 ⟶ 1,296:
 
zero( _ ) -> 0.
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">open System
open System.Threading
 
// current time in seconds
let now() = float( DateTime.Now.Ticks / 10000L ) / 1000.0
 
type Integrator( intervalMs ) as x =
let mutable k = fun _ -> 0.0 // function to integrate
let mutable s = 0.0 // current value
let mutable t0 = now() // last time s was updated
let mutable running = true // still running?
 
do x.ScheduleNextUpdate()
 
member x.Input(f) = k <- f
 
member x.Output() = s
 
member x.Stop() = running <- false
 
member private x.Update() =
let t1 = now()
s <- s + (k t0 + k t1) * (t1 - t0) / 2.0
t0 <- t1
x.ScheduleNextUpdate()
 
member private x.ScheduleNextUpdate() =
if running then
async { do! Async.Sleep( intervalMs )
x.Update()
}
|> Async.Start
let i = new Integrator(10)
 
i.Input( fun t -> Math.Sin (2.0 * Math.PI * 0.5 * t) )
Thread.Sleep(2000)
 
i.Input( fun _ -> 0.0 )
Thread.Sleep(500)
 
printfn "%f" (i.Output())
i.Stop()</syntaxhighlight>
 
=={{header|Factor}}==
Working with dynamic quotations requires the stack effect to be known in advance. The apply-stack-effect serves this purpose.
<langsyntaxhighlight lang="factor">USING: accessors alarms calendar combinators kernel locals math
math.constants math.functions prettyprint system threads ;
IN: rosettacode.active
Line 633 ⟶ 1,385:
0.5 seconds sleep
[ output . ] [ destroy ] bi ;
MAIN: active-test</langsyntaxhighlight>
( scratchpad ) "rosettacode.active" run
-5.294207647335787e-05
Line 639 ⟶ 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:
<langsyntaxhighlight lang="qbasic">#APPTYPE CONSOLE
 
#INCLUDE <Include\Windows.inc>
Line 732 ⟶ 1,484:
FUNCTION Task(BYVAL t AS DOUBLE) AS DOUBLE
RETURN SIN(2 * PI * 0.5 * t)
END FUNCTION</langsyntaxhighlight>
 
'''Typical console output:'''
Line 738 ⟶ 1,490:
Press any key to continue...
 
=={{header|F_Sharp|F#FreeBASIC}}==
<syntaxhighlight lang="freebasic">#define twopi 6.2831853071795864769252867665590057684
<lang fsharp>open System
dim shared as double S = 0 'set up the state as a global variable
open System.Threading
dim shared as double t0, t1, ta
 
function sine( x as double, f as double ) as double
// current time in seconds
return sin(twopi*f*x)
let now() = float( DateTime.Now.Ticks / 10000L ) / 1000.0
end function
 
function zero( x as double, f as double ) as double
type Integrator( intervalMs ) as x =
return 0
let mutable k = fun _ -> 0.0 // function to integrate
end function
let mutable s = 0.0 // current value
let mutable t0 = now() // last time s was updated
let mutable running = true // still running?
 
sub integrate( K as function(as double, as double) as double, f as double )
do x.ScheduleNextUpdate()
'represent input as pointers to functions
t1 = timer
s += (K(t1,f) + K(t0,f))*(t1-t0)/2.0
t0 = t1
end sub
 
t0 = timer
member x.Input(f) = k <- f
ta = timer
 
while timer-ta <= 2.5
member x.Output() = s
if timer-ta <= 2 then integrate( @sine, 0.5 ) else integrate( @zero, 0 )
wend
 
print S
member x.Stop() = running <- false
</syntaxhighlight>
 
{{out}}<pre>
member private x.Update() =
8.926050531860172e-07
let t1 = now()
</pre>
s <- s + (k t0 + k t1) * (t1 - t0) / 2.0
t0 <- t1
x.ScheduleNextUpdate()
 
member private x.ScheduleNextUpdate() =
if running then
async { do! Async.Sleep( intervalMs )
x.Update()
}
|> Async.Start
let i = new Integrator(10)
 
i.Input( fun t -> Math.Sin (2.0 * Math.PI * 0.5 * t) )
Thread.Sleep(2000)
 
i.Input( fun _ -> 0.0 )
Thread.Sleep(500)
 
printfn "%f" (i.Output())
i.Stop()</lang>
 
=={{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.
<langsyntaxhighlight lang="go">package main
 
import (
Line 864 ⟶ 1,604:
time.Sleep(time.Second / 2) // 4. sleep .5 sec
fmt.Println(a.output()) // output should be near zero
}</langsyntaxhighlight>
Output:
<pre>
2.4517135756807704e-05
</pre>
 
=={{header|Groovy}}==
{{trans|Java}}
<syntaxhighlight lang="groovy">/**
* Integrates input function K over time
* S + (t1 - t0) * (K(t1) + K(t0)) / 2
*/
class Integrator {
interface Function {
double apply(double timeSinceStartInSeconds)
}
 
private final long start
private volatile boolean running
 
private Function func
private double t0
private double v0
private double sum
 
Integrator(Function func) {
this.start = System.nanoTime()
setFunc(func)
new Thread({ this.&integrate() }).start()
}
 
void setFunc(Function func) {
this.func = func
def temp = func.apply(0.0.toDouble())
v0 = temp
t0 = 0.0.doubleValue()
}
 
double getOutput() {
return sum
}
 
void stop() {
running = false
}
 
private void integrate() {
running = true
while (running) {
try {
Thread.sleep(1)
update()
} catch (InterruptedException ignored) {
return
}
}
}
 
private void update() {
double t1 = (System.nanoTime() - start) / 1.0e9
double v1 = func.apply(t1)
double rect = (t1 - t0) * (v0 + v1) / 2.0
this.sum += rect
t0 = t1
v0 = v1
}
 
static void main(String[] args) {
Integrator integrator = new Integrator({ t -> Math.sin(Math.PI * t) })
Thread.sleep(2000)
 
integrator.setFunc({ t -> 0.0.toDouble() })
Thread.sleep(500)
 
integrator.stop()
System.out.println(integrator.getOutput())
}
}</syntaxhighlight>
{{out}}
<pre>0.0039642136156300455</pre>
 
=={{header|Haskell}}==
 
<langsyntaxhighlight lang="haskell">module Integrator (
newIntegrator, input, output, stop,
Time, timeInterval
Line 948 ⟶ 1,763:
 
-- Execute 'action' until it returns false.
whileM action = do b <- action; if b then whileM action else return ()</langsyntaxhighlight>
 
=={{header|J}}==
Line 954 ⟶ 1,769:
Implementation:
 
<langsyntaxhighlight Jlang="j">coclass 'activeobject'
require'dates'
 
Line 977 ⟶ 1,792:
getoutput=:3 :0
Zero+G T''
)</langsyntaxhighlight>
 
Task example (code):
 
<langsyntaxhighlight Jlang="j">cocurrent 'testrig'
 
delay=: 6!:3
Line 997 ⟶ 1,812:
delay 0.5
 
smoutput (T__object,getoutput__object) ''</langsyntaxhighlight>
 
Task example (output):
Line 1,008 ⟶ 1,823:
First column is time relative to start of processing, second column is object's output at that time.
 
=== Using a task thread ===
=={{header|Java}}==
<lang java>
package rosetta;
 
Variant using an independent task thread:
import java.util.function.Function;
 
<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 + (K(t1) +- K(t0)) * (K(t1) -+ K(t0)) / 2
*
*
*/
public class Integrator {
 
public interface Function {
private Function<Long, Double> f;
double apply(double timeSinceStartInSeconds);
private double s, lastS;
}
private long t0, t1;
private volatile boolean run;
 
private final long start;
public Integrator(Function<Long, Double> input) {
private volatile boolean running;
this.s = 0;
this.lastS = 0;
this.t0 = System.currentTimeMillis();
setInput(input);
run = true;
new Thread(() -> {
while (run) {
try {
Thread.sleep(1);
update();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
}
}
}).start();
}
 
private Function func;
private void update() {
private double t0;
long t = System.currentTimeMillis() - this.t0;
private double v0;
double v = this.f.apply(t);
private double sum;
this.s += (lastS + v) * (t - this.t1) / 2;
this.t1 = t;
}
 
public void setInput public Integrator(Function<Long, Double> inputfunc) {
this.fstart = inputSystem.nanoTime();
setFunc(func);
lastS = input.apply(0L);
new Thread(this::integrate).start();
t1 = 0;
}
}
 
public doublevoid getOutputsetFunc(Function func) {
this.func = func;
return s;
v0 = func.apply(0.0);
}
t0 = 0;
}
public void stop() {
run = false;
}
public static void main(String[] args) throws InterruptedException {
Integrator i = new Integrator((t) -> Math.sin(Math.PI * t));
Thread.sleep(2000);
i.setInput((t) -> 0.);
Thread.sleep(500);
System.out.println(i.getOutput());
i.stop();
}
}
 
public double getOutput() {
</lang>
return sum;
}
 
public void stop() {
running = false;
}
 
private void integrate() {
running = true;
while (running) {
try {
Thread.sleep(1);
update();
} catch (InterruptedException e) {
return;
}
}
}
 
private void update() {
double t1 = (System.nanoTime() - start) / 1.0e9;
double v1 = func.apply(t1);
double rect = (t1 - t0) * (v0 + v1) / 2;
this.sum += rect;
t0 = t1;
v0 = v1;
}
 
public static void main(String[] args) throws InterruptedException {
Integrator integrator = new Integrator(t -> Math.sin(Math.PI * t));
Thread.sleep(2000);
 
integrator.setFunc(t -> 0.0);
Thread.sleep(500);
 
integrator.stop();
System.out.println(integrator.getOutput());
}
}
</syntaxhighlight>
Output:
<pre>4.783602720556498E-13</pre>
Line 1,085 ⟶ 1,952:
{{trans|E}}
 
<langsyntaxhighlight lang="javascript">function Integrator(sampleIntervalMS) {
var inputF = function () { return 0.0 };
var sum = 0.0;
Line 1,110 ⟶ 1,977:
shutdown: function () { clearInterval(updater) },
});
}</langsyntaxhighlight>
 
Test program as a HTML fragment:
 
<langsyntaxhighlight lang="html4strict"><p><span id="a">Test running...</span> <code id="b">-</code></p>
 
<script type="text/javascript">
Line 1,133 ⟶ 2,000:
}, 2000);
}, 1)
</script></langsyntaxhighlight>
 
=={{header|MathematicaJulia}}==
{{works with|Julia|0.6}}
<lang Mathematica>Block[{start = SessionTime[], K, t0 = 0, t1, kt0, S = 0},
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
dt::Float64
running::Bool
function Integrator(f::Function, dt::Float64)
this = new()
this.func = f
this.runningsum = 0.0
this.dt = dt
this.running = false
return this
end
end
 
function run(integ::Integrator, lastval::Float64 = 0.0)
lasttime = time()
while integ.running
sleep(integ.dt)
newtime = time()
measuredinterval = newtime - lasttime
newval = integ.func(measuredinterval)
integ.runningsum += (lastval + newval) * measuredinterval / 2.0
lasttime = newtime
lastval = newval
end
end
 
start!(integ::Integrator) = (integ.running = true; @async run(integ))
stop!(integ) = (integ.running = false)
f1(t) = sin(2π * t)
f2(t) = 0.0
 
it = Integrator(f1, 0.00001)
start!(it)
sleep(2.0)
it.func = f2
sleep(0.5)
v2 = it.runningsum
println("After 2.5 seconds, integrator value was $v2")</syntaxhighlight>
 
=={{header|Kotlin}}==
{{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.*
 
typealias Function = (Double) -> Double
 
/**
* Integrates input function K over time
* S + (t1 - t0) * (K(t1) + K(t0)) / 2
*/
class Integrator {
private val start: Long
private @Volatile var running = false
private lateinit var func: Function
private var t0 = 0.0
private var v0 = 0.0
private var sum = 0.0
 
constructor(func: Function) {
start = System.nanoTime()
setFunc(func)
Thread(this::integrate).start()
}
 
fun setFunc(func: Function) {
this.func = func
v0 = func(0.0)
t0 = 0.0
}
 
fun getOutput() = sum
 
fun stop() {
running = false
}
 
private fun integrate() {
running = true
while (running) {
try {
Thread.sleep(1)
update()
}
catch(e: InterruptedException) {
return
}
}
}
 
private fun update() {
val t1 = (System.nanoTime() - start) / 1.0e9
val v1 = func(t1)
val rect = (t1 - t0) * (v0 + v1) / 2.0
sum += rect
t0 = t1
v0 = v1
}
}
 
fun main(args: Array<String>) {
val integrator = Integrator( { sin(PI * it) } )
Thread.sleep(2000)
 
integrator.setFunc( { 0.0 } )
Thread.sleep(500)
 
integrator.stop()
println(integrator.getOutput())
}</syntaxhighlight>
 
Sample output:
<pre>
2.884266305153741E-4
</pre>
 
=={{header|Lingo}}==
Parent script "Integrator":
<syntaxhighlight lang="lingo">property _sum
property _func
property _timeLast
property _valueLast
property _ms0
property _updateTimer
 
on new (me, func)
if voidP(func) then func = "0.0"
me._sum = 0.0
-- update frequency: 100/sec (arbitrary)
me._updateTimer = timeout().new("update", 10, #_update, me)
me.input(func)
return me
end
 
on stop (me)
me._updateTimer.period = 0 -- deactivates timer
end
 
-- func is a term (as string) that might contain "t" and is evaluated at runtime
on input (me, func)
me._func = func
me._ms0 = _system.milliseconds
me._timeLast = 0.0
t = 0.0
me._valueLast = value(me._func)
end
 
on output (me)
return me._sum
end
 
on _update (me)
now = _system.milliseconds - me._ms0
t = now/1000.0
val = value(me._func)
me._sum = me._sum + (me._valueLast+val)*(t - me._timeLast)/2
me._timeLast = t
me._valueLast = val
end</syntaxhighlight>
 
In some movie script:
<syntaxhighlight lang="lingo">global gIntegrator
 
-- entry point
on startMovie
gIntegrator = script("Integrator").new("sin(PI * t)")
timeout().new("timer", 2000, #step1)
end
 
on step1 (_, timer)
gIntegrator.input("0.0")
timer.timeoutHandler = #step2
timer.period = 500
end
 
on step2 (_, timer)
gIntegrator.stop()
put gIntegrator.output()
timer.forget()
end</syntaxhighlight>
 
{{out}}
<pre>-- 0.0004</pre>
 
=={{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 = {
new = function(self, fn)
return setmetatable({fn=fn,t0=seconds(),v0=0,sum=0,nup=0},self)
end,
update = function(self)
self.t1 = seconds()
self.v1 = self.fn(self.t1)
self.sum = self.sum + (self.v0 + self.v1) * (self.t1 - self.t0) / 2
self.t0, self.v0, self.nup = self.t1, self.v1, self.nup+1
end,
input = function(self, fn) self.fn = fn end,
output = function(self) return self.sum end,
}
integrator.__index = integrator
 
-- "fake multithreaded sleep()"
-- waits for "duration" seconds calling "f" at every "interval" seconds
local function sample(duration, interval, f)
local now = seconds()
local untilwhen, nextinterval = now+duration, now+interval
f()
repeat
if seconds() >= nextinterval then f() nextinterval=nextinterval+interval end
until seconds() >= untilwhen
end
 
local pi, sin = math.pi, math.sin
local ks = function(t) return sin(2.0*pi*0.5*t) end
local kz = function(t) return 0 end
local intervals = { 0.5, 0.25, 0.1, 0.05, 0.025, 0.01, 0.005, 0.0025, 0.001 }
for _,interval in ipairs(intervals) do
local i = integrator:new(ks)
sample(2.0, interval, function() i:update() end)
i:input(kz)
sample(0.5, interval, function() i:update() end)
print(string.format("sampling interval: %f, %5d updates over 2.5s total = %.15f", interval, i.nup, i:output()))
end</syntaxhighlight>
{{out}}
<pre>sampling interval: 0.500000, 6 updates over 2.5s total = -0.003628054395752
sampling interval: 0.250000, 11 updates over 2.5s total = 0.003994231784540
sampling interval: 0.100000, 25 updates over 2.5s total = 0.001891527454886
sampling interval: 0.050000, 51 updates over 2.5s total = 0.023521980508657
sampling interval: 0.025000, 101 updates over 2.5s total = -0.000573259909112
sampling interval: 0.010000, 250 updates over 2.5s total = 0.003001745575344
sampling interval: 0.005000, 501 updates over 2.5s total = -0.000415541052666
sampling interval: 0.002500, 999 updates over 2.5s total = -0.001480800340644
sampling interval: 0.001000, 2493 updates over 2.5s total = 0.000362576907805</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="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;
S += (kt0 + (kt0 = K[t1])) (t1 - t0)/2; t0 = t1;
If[t1 > 2, K[t_] = 0; If[t1 > 2.5, Break[]]]]; S]</langsyntaxhighlight>
 
1.1309*10^-6
Line 1,146 ⟶ 2,256:
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|OzNim}}==
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.
<lang oz>declare
fun {Const X}
fun {$ _} X end
end
 
Of course, it is necessary to take some precautions when accessing or updating the shared object. We use a lock for this purpose.
fun {Now}
{Int.toFloat {Property.get 'time.total'}} / 1000.0
end
 
<syntaxhighlight lang="text">
class Integrator from Time.repeat
# Active object.
attr
# Compile with "nim c --threads:on".
k:{Const 0.0}
s:0.0
t1 k_t1
t2 k_t2
meth init(SampleIntervalMS)
t1 := {Now}
k_t1 := {@k @t1}
{self setRepAll(action:Update
delay:SampleIntervalMS)}
thread
{self go}
end
end
 
import locks
meth input(K)
import os
k := K
import std/monotimes
end
 
type
meth output($)
@s
end
 
# Function to use for integration.
meth Update
TimeFunction = proc (t: float): float {.gcsafe.}
t2 := {Now}
k_t2 := {@k @t2}
s := @s + (@k_t1 + @k_t2) * (@t2 - @t1) / 2.0
t1 := @t2
k_t1 := @k_t2
end
end
 
# Integrator object.
Pi = 3.14159265
Integrator = ptr TIntegrator
F = 0.5
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.
 
#---------------------------------------------------------------------------------------------------
I = {New Integrator init(10)}
in
{I input(fun {$ T}
{Sin 2.0 * Pi * F * T}
end)}
 
proc newIntegrator(f: TimeFunction; dt: int): Integrator =
{Delay 2000} %% ms
## Create an integrator.
 
result = cast[Integrator](allocShared(sizeof(TIntegrator)))
{I input({Const 0.0})}
result.k = f
result.dt = dt
result.s = 0
result.lock.initLock()
result.isRunning = false
 
#---------------------------------------------------------------------------------------------------
{Delay 500} %% ms
 
proc process(integrator: Integrator) {.thread, gcsafe.} =
{Show {I output($)}}
## Do the integration.
{I stop}</lang>
 
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()
</syntaxhighlight>
 
{{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}}==
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">
<lang ooRexx>
integrater = .integrater~new(.routines~sine) -- start the integrater function
call syssleep 2
Line 1,287 ⟶ 2,464:
::requires rxmath library
 
</syntaxhighlight>
</lang>
 
=={{header|Perl}}==
<lang perl>#!/usr/bin/perl
 
use strict;
use 5.10.0;
 
package Integrator;
use threads;
use threads::shared;
 
sub new {
my $cls = shift;
my $obj = bless { t => 0,
sum => 0,
ref $cls ? %$cls : (),
stop => 0,
tid => 0,
func => shift,
}, ref $cls || $cls;
 
share($obj->{sum});
share($obj->{stop});
 
$obj->{tid} = async {
my $upd = 0.1; # update every 0.1 second
while (!$obj->{stop}) {
{
my $f = $obj->{func};
my $t = $obj->{t};
 
$obj->{sum} += ($f->($t) + $f->($t + $upd))* $upd/ 2;
$obj->{t} += $upd;
}
select(undef, undef, undef, $upd);
}
# say "stopping $obj";
};
$obj
}
 
sub output { shift->{sum} }
 
sub delete {
my $obj = shift;
$obj->{stop} = 1;
$obj->{tid}->join;
}
 
sub setinput {
# This is surprisingly difficult because of the perl sharing model.
# Func refs can't be shared, thus can't be replaced by another thread.
# Have to create a whole new object... there must be a better way.
my $obj = shift;
$obj->delete;
$obj->new(shift);
}
 
package main;
 
my $x = Integrator->new(sub { sin(atan2(1, 1) * 8 * .5 * shift) });
 
sleep(2);
say "sin after 2 seconds: ", $x->output;
 
$x = $x->setinput(sub {0});
 
select(undef, undef, undef, .5);
say "0 after .5 seconds: ", $x->output;
 
$x->delete;</lang>
 
=={{header|OxygenBasic}}==
Line 1,365 ⟶ 2,471:
 
With a high precision timer the result is around -.0002
<langsyntaxhighlight lang="oxygenbasic">
double MainTime
 
Line 1,537 ⟶ 2,643:
print str(integral,4)
 
Rudolpho.clear</langsyntaxhighlight>
 
=={{header|Oz}}==
<syntaxhighlight lang="oz">declare
fun {Const X}
fun {$ _} X end
end
 
fun {Now}
{Int.toFloat {Property.get 'time.total'}} / 1000.0
end
 
class Integrator from Time.repeat
attr
k:{Const 0.0}
s:0.0
t1 k_t1
t2 k_t2
meth init(SampleIntervalMS)
t1 := {Now}
k_t1 := {@k @t1}
{self setRepAll(action:Update
delay:SampleIntervalMS)}
thread
{self go}
end
end
 
meth input(K)
k := K
end
 
meth output($)
@s
end
 
meth Update
t2 := {Now}
k_t2 := {@k @t2}
s := @s + (@k_t1 + @k_t2) * (@t2 - @t1) / 2.0
t1 := @t2
k_t1 := @k_t2
end
end
 
Pi = 3.14159265
F = 0.5
 
I = {New Integrator init(10)}
in
{I input(fun {$ T}
{Sin 2.0 * Pi * F * T}
end)}
 
{Delay 2000} %% ms
 
{I input({Const 0.0})}
 
{Delay 500} %% ms
 
{Show {I output($)}}
{I stop}</syntaxhighlight>
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict;
use 5.10.0;
 
package Integrator;
use threads;
use threads::shared;
 
sub new {
my $cls = shift;
my $obj = bless { t => 0,
sum => 0,
ref $cls ? %$cls : (),
stop => 0,
tid => 0,
func => shift,
}, ref $cls || $cls;
 
share($obj->{sum});
share($obj->{stop});
 
$obj->{tid} = async {
my $upd = 0.1; # update every 0.1 second
while (!$obj->{stop}) {
{
my $f = $obj->{func};
my $t = $obj->{t};
 
$obj->{sum} += ($f->($t) + $f->($t + $upd))* $upd/ 2;
$obj->{t} += $upd;
}
select(undef, undef, undef, $upd);
}
# say "stopping $obj";
};
$obj
}
 
sub output { shift->{sum} }
 
sub delete {
my $obj = shift;
$obj->{stop} = 1;
$obj->{tid}->join;
}
 
sub setinput {
# This is surprisingly difficult because of the perl sharing model.
# Func refs can't be shared, thus can't be replaced by another thread.
# Have to create a whole new object... there must be a better way.
my $obj = shift;
$obj->delete;
$obj->new(shift);
}
 
package main;
 
my $x = Integrator->new(sub { sin(atan2(1, 1) * 8 * .5 * shift) });
 
sleep(2);
say "sin after 2 seconds: ", $x->output;
 
$x = $x->setinput(sub {0});
 
select(undef, undef, undef, .5);
say "0 after .5 seconds: ", $x->output;
 
$x->delete;</syntaxhighlight>
 
=={{header|Phix}}==
===classes===
{{libheader|Phix/Class}}
 
<!--<syntaxhighlight lang="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>
<span style="color: #004080;">integer</span> <span style="color: #000000;">xlock</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">class</span> <span style="color: #000000;">integrator</span>
<span style="color: #000080;font-style:italic;">--
-- Integrates input function f over time
-- v + (t1 - t0) * (f(t1) + f(t0)) / 2
--</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">f</span> <span style="color: #000080;font-style:italic;">-- function f(atom t); (see note)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">interval</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;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">running</span>
<span style="color: #008080;">public</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">id</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_func</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rid</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">update</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">f</span> <span style="color: #000080;font-style:italic;">-- (nb: no "this")</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">k1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">v</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">k1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">k0</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span>
<span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t1</span>
<span style="color: #000000;">k0</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">k1</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">tick</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">running</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">running</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">interval</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">update</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">stop</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">running</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #000000;">wait_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_output</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">v</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">class</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">new_integrator</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">interval</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">integrator</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">rid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">interval</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()})</span>
<span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">update</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">tick</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">zero</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000080;font-style:italic;">/*t*/</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">sine</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">*</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000000;">integrator</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">new_integrator</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sine</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.01</span><span style="color: #0000FF;">);</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">get_output</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">set_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">zero</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">stop</span><span style="color: #0000FF;">()</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">get_output</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
 
Note that were f a regular member function of the class, it would get a "this" parameter/argument, which we avoid by stashing it in a local integer prior to the call. Alternatively you could of course use zero/sine functions with an ignored parameter and the usual this.f() syntax [along with the usual "this." being optional inside the class definition].
{{out}}
<pre>
0.0003532983803
4.049495114e-17
</pre>
 
===pre-classes===
Note that in Phix you cannot pass a variable to another procedure and have it "change under your feet". <small>[erm, now you can, see classes above]</small><br>
The copy-on-write semantics mean it would not have any effect, in that the original would be preserved
(deemed in phix to be a "very good thing") while the value passed along, a shared reference until it gets
modified and a copy made, would most likely simply be discarded, unless explicitly returned and stored,
which obviously cannot be done from a separate thread.
Instead we pass around an index (dx) as a way of emulating the "pointer references" of other languages.
 
If anything phix requires more locking that other languages due to the hidden shared reference counts.<br>
Just lock everything, it is not that hard, and you should never need much more than the stuff below.
 
<!--<syntaxhighlight lang="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>
<span style="color: #004080;">integer</span> <span style="color: #000000;">xlock</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">zero</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000080;font-style:italic;">/*t*/</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">sine</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">*</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">update</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">k1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">call_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">KFUN</span><span style="color: #0000FF;">],{</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">k1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">K0</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">*</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">T0</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">T0</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t1</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">K0</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">k1</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">tick</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">TERMINATE</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">INTERVAL</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">update</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">new_integrator</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">interval</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ISIZE</span><span style="color: #0000FF;">))</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">TERMINATE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">INTERVAL</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">interval</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">KFUN</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rid</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">T0</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">update</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ID</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tick</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">dx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_input</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">KFUN</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rid</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">K0</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_output</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xlock</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">v</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">stop_integrator</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">TERMINATE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #000000;">wait_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ID</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">new_integrator</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sine</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.01</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%f\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">get_output</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">set_input</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">zero</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%f\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">get_output</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">stop_integrator</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
 
{{out}}
<pre>
-0.00326521
0.00196980
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/math.l")
 
(class +Active)
Line 1,583 ⟶ 2,984:
(wait 500) # Wait 0.5 sec
(prinl "Output: " (output> Obj)) # Print return value
(stop> Obj) ) ) # Stop active object</langsyntaxhighlight>
 
=={{header|PureBasic}}==
Using the open-source precompiler [http://www.development-lounge.de/viewtopic.php?t=5915 SimpleOOP].
<langsyntaxhighlight PureBasiclang="purebasic">Prototype.d ValueFunction(f.d, t.d)
 
Class IntegralClass
Line 1,658 ⟶ 3,059:
Delay( 500) ; Wait 1/2 sec
MessageRequester("Info", StrD(*a\Output())) ; Present the result
*a= FreeObject</langsyntaxhighlight>
 
=={{header|Python}}==
{{works with|Python|3}}
Assignment is thread-safe in Python, so no extra locks are needed in this case.
 
 
<langsyntaxhighlight lang="python">from time import time, sleep
from threading import Thread
 
Line 1,698 ⟶ 3,100:
ai = Integrator(lambda t: sin(pi*t))
sleep(2)
print (ai.S)
ai.K = lambda t: 0
sleep(0.5)
print (ai.S)</langsyntaxhighlight>
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 1,736 ⟶ 3,138:
(sleep/yield 0.5)
(displayln (send active output))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.12}}
There is some jitter in the timer, but it is typically accurate to within a few thousandths of a second.
 
<syntaxhighlight lang="raku" line>class Integrator {
has $.f is rw = sub ($t) { 0 };
has $.now is rw;
has $.value is rw = 0;
has $.integrator is rw;
 
method init() {
self.value = &(self.f)(0);
self.integrator = Thread.new(
:code({
loop {
my $t1 = now;
self.value += (&(self.f)(self.now) + &(self.f)($t1)) * ($t1 - self.now) / 2;
self.now = $t1;
sleep .001;
}
}),
:app_lifetime(True)
).run
}
 
method Input (&f-of-t) {
self.f = &f-of-t;
self.now = now;
self.init;
}
 
method Output { self.value }
}
 
my $a = Integrator.new;
 
$a.Input( sub ($t) { sin(2 * π * .5 * $t) } );
 
say "Initial value: ", $a.Output;
 
sleep 2;
 
say "After 2 seconds: ", $a.Output;
 
$a.Input( sub ($t) { 0 } );
 
sleep .5;
 
say "f(0): ", $a.Output;</syntaxhighlight>
 
{{out|Typical output}}
<pre>Initial value: 0
After 2 seconds: -0.0005555887464620366
f(0): 0</pre>
 
=={{header|Rust}}==
 
<syntaxhighlight lang="rust">#![feature(mpsc_select)]
 
extern crate num;
extern crate schedule_recv;
 
use num::traits::Zero;
use num::Float;
use schedule_recv::periodic_ms;
use std::f64::consts::PI;
use std::ops::Mul;
use std::sync::mpsc::{self, SendError, Sender};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
 
pub type Actor<S> = Sender<Box<Fn(u32) -> S + Send>>;
pub type ActorResult<S> = Result<(), SendError<Box<Fn(u32) -> S + Send>>>;
 
/// Rust supports both shared-memory and actor models of concurrency, and the `Integrator` utilizes
/// both. We use an `Actor` to send the `Integrator` new functions, while we use a `Mutex`
/// (shared-memory concurrency) to hold the result of the integration.
///
/// Note that these are not the only options here--there are many, many ways you can deal with
/// concurrent access. But when in doubt, a plain old `Mutex` is often a good bet. For example,
/// this might look like a good situation for a `RwLock`--after all, there's no reason for a read
/// in the main task to block writes. Unfortunately, unless you have significantly more reads than
/// writes (which is certainly not the case here), a `Mutex` will usually outperform a `RwLock`.
pub struct Integrator<S: 'static, T: Send> {
input: Actor<S>,
output: Arc<Mutex<T>>,
}
 
/// In Rust, time durations are strongly typed. This is usually exactly what you want, but for a
/// problem like this--where the integrated value has unusual (unspecified?) units--it can actually
/// be a bit tricky. Right now, `Duration`s can only be multiplied or divided by `i32`s, so in
/// order to be able to actually do math with them we say that the type parameter `S` (the result
/// of the function being integrated) must yield `T` (the type of the integrated value) when
/// multiplied by `f64`. We could possibly replace `f64` with a generic as well, but it would make
/// things a bit more complex.
impl<S, T> Integrator<S, T>
where
S: Mul<f64, Output = T> + Float + Zero,
T: 'static + Clone + Send + Float,
{
pub fn new(frequency: u32) -> Integrator<S, T> {
// We create a pipe allowing functions to be sent from tx (the sending end) to input (the
// receiving end). In order to change the function we are integrating from the task in
// which the Integrator lives, we simply send the function through tx.
let (tx, input) = mpsc::channel();
// The easiest way to do shared-memory concurrency in Rust is to use atomic reference
// counting, or Arc, around a synchronized type (like Mutex<T>). Arc gives you a guarantee
// that memory will not be freed as long as there is at least one reference to it.
// It is similar to C++'s shared_ptr, but it is guaranteed to be safe and is never
// incremented unless explicitly cloned (by default, it is moved).
let s: Arc<Mutex<T>> = Arc::new(Mutex::new(Zero::zero()));
let integrator = Integrator {
input: tx,
// Here is the aforementioned clone. We have to do it before s enters the closure,
// because once that happens it is moved into the closure (and later, the new task) and
// becomes inaccessible to the outside world.
output: Arc::clone(&s),
};
thread::spawn(move || -> () {
// The frequency is how often we want to "tick" as we update our integrated total. In
// Rust, timers can yield Receivers that are periodically notified with an empty
// message (where the period is the frequency). This is useful because it lets us wait
// on either a tick or another type of message (in this case, a request to change the
// function we are integrating).
let periodic = periodic_ms(frequency);
let mut t = 0;
let mut k: Box<Fn(u32) -> S + Send> = Box::new(|_| Zero::zero());
let mut k_0: S = Zero::zero();
loop {
// Here's the selection we talked about above. Note that we are careful to call
// the *non*-failing function, recv(), here. The reason we do this is because
// recv() will return Err when the sending end of a channel is dropped. While
// this is unlikely to happen for the timer (so again, you could argue for failure
// there), it's normal behavior for the sending end of input to be dropped, since
// it just happens when the Integrator falls out of scope. So we handle it cleanly
// and break out of the loop, rather than failing.
select! {
res = periodic.recv() => match res {
Ok(_) => {
t += frequency;
let k_1: S = k(t);
// Rust Mutexes are a bit different from Mutexes in many other
// languages, in that the protected data is actually encapsulated by
// the Mutex. The reason for this is that Rust is actually capable of
// enforcing (via its borrow checker) the invariant that the contents
// of a Mutex may only be read when you have acquired its lock. This
// is enforced by way of a MutexGuard, the return value of lock(),
// which implements some special traits (Deref and DerefMut) that allow
// access to the inner element "through" the guard. The element so
// acquired has a lifetime bounded by that of the MutexGuard, the
// MutexGuard can only be acquired by taking a lock, and the only way
// to release the lock is by letting the MutexGuard fall out of scope,
// so it's impossible to access the data incorrectly. There are some
// additional subtleties around the actual implementation, but that's
// the basic idea.
let mut s = s.lock().unwrap();
*s = *s + (k_1 + k_0) * (f64::from(frequency) / 2.);
k_0 = k_1;
}
Err(_) => break,
},
res = input.recv() => match res {
Ok(k_new) => k = k_new,
Err(_) => break,
}
}
}
});
integrator
}
 
pub fn input(&self, k: Box<Fn(u32) -> S + Send>) -> ActorResult<S> {
// The meat of the work is done in the other thread, so to set the
// input we just send along the Sender we set earlier...
self.input.send(k)
}
 
pub fn output(&self) -> T {
// ...and to read the input, we simply acquire a lock on the output Mutex and return a
// copy. Why do we have to copy it? Because, as mentioned above, Rust won't let us
// retain access to the interior of the Mutex unless we have possession of its lock. There
// are ways and circumstances in which one can avoid this (e.g. by using atomic types) but
// a copy is a perfectly reasonable solution as well, and a lot easier to reason about :)
*self.output.lock().unwrap()
}
}
 
/// This function is fairly straightforward. We create the integrator, set its input function k(t)
/// to 2pi * f * t, and then wait as described in the Rosetta stone problem.
fn integrate() -> f64 {
let object = Integrator::new(10);
object
.input(Box::new(|t: u32| {
let two_seconds_ms = 2 * 1000;
let f = 1. / f64::from(two_seconds_ms);
(2. * PI * f * f64::from(t)).sin()
}))
.expect("Failed to set input");
thread::sleep(Duration::from_secs(2));
object.input(Box::new(|_| 0.)).expect("Failed to set input");
thread::sleep(Duration::from_millis(500));
object.output()
}
 
fn main() {
println!("{}", integrate());
}
 
/// Will fail on a heavily loaded machine
#[test]
#[ignore]
fn solution() {
// We should just be able to call integrate, but can't represent the closure properly due to
// rust-lang/rust issue #17060 if we make frequency or period a variable.
// FIXME(pythonesque): When unboxed closures are fixed, fix integrate() to take two arguments.
let object = Integrator::new(10);
object
.input(Box::new(|t: u32| {
let two_seconds_ms = 2 * 1000;
let f = 1. / (two_seconds_ms / 10) as f64;
(2. * PI * f * t as f64).sin()
}))
.expect("Failed to set input");
thread::sleep(Duration::from_millis(200));
object.input(Box::new(|_| 0.)).expect("Failed to set input");
thread::sleep(Duration::from_millis(100));
assert_eq!(object.output() as u32, 0)
}</syntaxhighlight>
 
=={{header|Scala}}==
 
<langsyntaxhighlight Scalalang="scala">object ActiveObject {
 
class Integrator {
Line 1,787 ⟶ 3,420:
integrator.bye
}
}</langsyntaxhighlight>
 
=={{header|Smalltalk}}==
 
<syntaxhighlight lang="smalltalk">
<lang Smalltalk>
Object subclass:#Integrator
instanceVariableNames:'tickRate input s thread'
Line 1,853 ⟶ 3,486:
showCR:(i stop).
].
</syntaxhighlight>
</lang>
running:
<syntaxhighlight lang Smalltalk="smalltalk">Integrator example</langsyntaxhighlight>
 
output:
Line 1,878 ⟶ 3,511:
=={{header|SuperCollider}}==
Instead of writing a class, here we just use an environment to encapsulate state.
<syntaxhighlight lang="supercollider">
<lang SuperCollider>
(
a = TaskProxy { |envir|
Line 1,910 ⟶ 3,543:
}
)
</syntaxhighlight>
</lang>
 
=={{header|Swift}}==
<langsyntaxhighlight Swiftlang="swift">// For NSObject, NSTimeInterval and NSThread
import Foundation
// For PI and sin
Line 1,978 ⟶ 3,611:
 
println(activeObject.Output())
</syntaxhighlight>
</lang>
Sample output:
<pre>
Line 1,988 ⟶ 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.
<langsyntaxhighlight Tcllang="tcl">package require Tcl 8.6
oo::class create integrator {
variable e sum delay tBase t0 k0 aid
Line 2,037 ⟶ 3,670:
pause 0.5
puts [format %.15f [i output]]
}</langsyntaxhighlight>
Sample output:
-0.000000168952702
Line 2,045 ⟶ 3,678:
Since this object is CPU intensive, shutting it down when done is crucial. To facilitate this, the IDisposable pattern was used.
 
<langsyntaxhighlight lang="vbnet">Module Module1
Sub Main()
Line 2,118 ⟶ 3,751:
End Sub
End Class</langsyntaxhighlight>
 
 
Output: 0.000241446762282308
 
=={{header|Wren}}==
Wren doesn't have threads but does have fibers which are cooperatively (rather than preemptively) scheduled. Only one fiber can run at a time.
 
However, it is possible to perform asynchronous operations in Wren-cli using a combination of the Scheduler and Timer classes which use the C library ''libuv'' under the hood. The problem is that, due to a bug, the Timer.sleep method doesn't just pause the current fiber, it also pauses the System.clock method! So we can't use the latter to measure time here.
 
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="wren">import "scheduler" for Scheduler
import "timer" for Timer
 
var Interval = 0
 
class Integrator {
construct new() {
_sum = 0
}
 
input(k) {
_k = k
_v0 = k.call(0)
_t = 0
_running = true
integrate_()
}
 
output { _sum }
 
stop() {
_running = false
}
 
integrate_() {
while (_running) {
Timer.sleep(1)
update_()
}
}
 
update_() {
_t = _t + Interval
var v1 = _k.call(_t)
var trap = Interval * (_v0 + v1) / 2
_sum = _sum + trap
_v0 = v1
}
}
 
var integrator = Integrator.new()
Scheduler.add {
Interval = 2 / 1550 // machine specific value
integrator.input(Fn.new { |t| (Num.pi * t).sin })
}
Timer.sleep(2000)
 
Scheduler.add {
Interval = 0.5 / 775 // machine specific value
integrator.input(Fn.new { |t| 0 })
}
Timer.sleep(500)
 
integrator.stop()
System.print(integrator.output)</syntaxhighlight>
 
{{out}}
<pre>
0.0028437802254386
</pre>
 
=={{header|zkl}}==
{{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.
<langsyntaxhighlight lang="zkl">class Integrator{
// continuously integrate a function `K`, at each `interval` seconds'
fcn init(f,interval=1e-4){
Line 2,144 ⟶ 3,844:
fcn sample { S.value }
fcn setF(f) { K.set(f) }
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">ai:=Integrator(fcn(t){ ((0.0).pi*t).sin() });
Atomic.sleep(2);
ai.sample().println();
Line 2,151 ⟶ 3,851:
ai.setF(fcn{ 0 });
Atomic.sleep(0.5);
ai.sample().println();</langsyntaxhighlight>
{{out}}
<pre>
Line 2,157 ⟶ 3,857:
1.11571e-07
</pre>
{{omit from|6502 Assembly|Not an object-oriented language.}}
 
{{omit from|8080 Assembly}}
{{omit from|8086 Assembly}}
{{omit from|68000 Assembly}}
{{omit from|ACL2}}
{{omit from|ARM Assembly}}
{{omit from|AWK}}
{{omit from|gnuplot}}
Line 2,164 ⟶ 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}}
{{omit from|ZX Spectrum Basic}}
9,476

edits