comp.lang.ada
 help / color / mirror / Atom feed
From: "T.G." <anon@anon.org>
Subject: Re: Abortable Timed Action
Date: Fri, 8 Jan 2016 20:24:31 +0000 (UTC)
Date: 2016-01-08T20:24:31+00:00	[thread overview]
Message-ID: <n6p5tu$9mv$1@adenine.netfront.net> (raw)
In-Reply-To: f48a91a2-7d72-4dc4-b219-4a02b1efe237@googlegroups.com

On 2016-01-06, Anh Vo <anhvofrcaus@gmail.com> wrote:
> After looking at your original post again, I believe your code
> should work after replacing delay statement by delay until
> statement. The delay until statement does not have time drifting
> issue. In addition, then Entry Finish can be replaced by the
> terminate alternative. The modified version is shown below.

>             select 
>                accept Cancel; 
>             or 
>                delay until (Ada.Calendar.Clock + Timeout); 
>                Put_Line ("Do Something"); 
>             end select; 

The reason why I had an explicit Finish instead of using terminate was
that I was thinking of creating the timer dynamically and then freeing
it with Ada.Unchecked_Deallocation. So I wanted to Finish the task
before freeing it. I'm not sure if calling Free on an access actually
terminates the task Normally.

delay until is an interesting idea. I'm assuming that time drift would
be an issue in periodic actions that repeat at a certain interval, but
in that case delay until could also have issues if it loses some
accuracy on each iteration. For example, modifying the code to run
periodically, with:

      Start_Time : Ada.Calendar.Time;
   begin
      ...
	    accept Exec_After (T : Duration) do
   	       Start_Time := Ada.Calendar.Clock;
	       Timeout    := T;
	    end Exec_After; 
	    Inner : loop
	       select 
		  accept Cancel; 
		  exit Inner;
	       or 
		  delay until (Ada.Calendar.Clock + Timeout); 
		  Put_Line (Duration'Image (Ada.Calendar.Clock - Start_Time));
	       end select; 
	    end loop Inner;

it will drift, however, we can still use delay until but with a
counter, for example:

   task body Timed_Action_Task is 
      Timeout        : Duration;
      Start_Time     : Ada.Calendar.Time;
      Counter        : Positive := 1;
   begin 
      loop 
	 select 
	    accept Exec_After (T : Duration) do 
	       Start_Time := Ada.Calendar.Clock;
	       Timeout    := T;
	       Counter    := 1;
	    end Exec_After; 
	    Inner : loop
	       select 
		  exit Inner;
		  accept Cancel; 
	       or 
		  delay until (Start_Time + (Timeout * Counter));
		  Counter := Counter + 1;
		  Put_Line (Duration'Image (Ada.Calendar.Clock - Start_Time));
	       end select; 
	    end loop Inner;
	 or 
	    terminate;
	 end select; 
      end loop; 
   end Timed_Action_Task;

This avoids the drift from the previous example.

In my actual code, I used Ada.Real_Time.Timing_Events. It ended up
being somewhat complicated, but only because I wanted to pass both
Action and User_Data to the Timer and make a more flexible/reusable
timer. Now after testing the code above, I think I want to recheck my
code for a possible time drift with periodic timed events.


--- news://freenews.netfront.net/ - complaints: news@netfront.net ---

  reply	other threads:[~2016-01-08 20:24 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-31  4:15 Abortable Timed Action T.G.
2015-12-31  6:40 ` Anh Vo
2015-12-31  7:32   ` T.G.
2015-12-31 16:21     ` Anh Vo
2015-12-31 18:09       ` T.G.
2016-01-06 21:14         ` Anh Vo
2016-01-08 20:24           ` T.G. [this message]
2016-01-09  8:45             ` Simon Wright
2016-01-09  9:10               ` Dmitry A. Kazakov
2016-01-09 14:41               ` Bob Duff
2016-01-09 15:59               ` T.G.
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox