Task: Active object



C#: using System;
using System.Threading.Tasks;

using static System.Diagnostics.Stopwatch;
using static System.Math;
using static System.Threading.Thread;

class ActiveObject
{
    static double timeScale = 1.0 / Frequency;

    Func<double, double> func;
    Task updateTask;
    double integral;
    double value;
    long timestamp0, timestamp;

    public ActiveObject(Func<double, double> input)
    {
        timestamp0 = timestamp = GetTimestamp();
        func = input;
        value = func(0);
        updateTask = Integrate();
    }

    public void ChangeInput(Func<double, double> input)
    {
        lock (updateTask)
        {
            func = input;
        }
    }

    public double Value
    {
        get
        {
            lock (updateTask)
            {
                return integral;
            }
        }
    }

    async Task Integrate()
    {
        while (true)
        {
            await Task.Yield();
            var newTime = GetTimestamp();
            double newValue;

            lock (updateTask)
            {
                newValue = func((newTime - timestamp0) * timeScale);
                integral += (newValue + value) * (newTime - timestamp) * timeScale / 2;
            }

            timestamp = newTime;
            value = newValue;
        }
    }
}

class Program
{
    static Func<double, double> Sine(double frequency) =>
        t => Sin(2 * PI * frequency * t);

    static void Main(string[] args)
    {
        var ao = new ActiveObject(Sine(0.5));
        Sleep(TimeSpan.FromSeconds(2));
        ao.ChangeInput(t => 0);
        Sleep(TimeSpan.FromSeconds(0.5));
        Console.WriteLine(ao.Value);
    }
}









Ada: with Ada.Calendar;                       use Ada.Calendar;
with Ada.Numerics;                       use Ada.Numerics;
with Ada.Numerics.Elementary_Functions;  use Ada.Numerics.Elementary_Functions;
with Ada.Text_IO;                        use Ada.Text_IO;
 
procedure Test_Integrator is
   type Func is access function (T : Time) return Float;

   function Zero (T : Time) return Float is
   begin
      return 0.0;
   end Zero;

   Epoch : constant Time := Clock;

   function Sine (T : Time) return Float is
   begin
      return Sin (Pi * Float (T - Epoch));
   end Sine;

   task type Integrator is
      entry Input  (Value : Func);
      entry Output (Value : out Float);
      entry Shut_Down;
   end Integrator;
 
   task body Integrator is
      K  : Func  := Zero'Access;
      S  : Float := 0.0;
      F0 : Float := 0.0;
      F1 : Float;
      T0 : Time  := Clock;
      T1 : Time;
   begin
      loop
         select
            accept Input (Value : Func) do
               K := Value;
            end Input;
         or accept Output (Value : out Float) do
               Value := S;
            end Output;
         or accept Shut_Down;
            exit;
         else
            T1 := Clock;
            F1 := K (T1);
            S  := S + 0.5 * (F1 + F0) * Float (T1 - T0);
            T0 := T1;
            F0 := F1;
         end select;
      end loop;
   end Integrator;
 
   I : Integrator;
   S : Float;
begin
   I.Input (Sine'Access);
   delay 2.0;
   I.Input (Zero'Access);
   delay 0.5;
   I.Output (S);
   Put_Line ("Integrated" & Float'Image (S) & "s");
   I.Shut_Down;
end Test_Integrator;