comp.lang.ada
 help / color / mirror / Atom feed
* Periodic tasks - organization
@ 2008-07-13 21:47 Maciej Sobczak
  2008-07-13 23:35 ` tmoran
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Maciej Sobczak @ 2008-07-13 21:47 UTC (permalink / raw)


Consider a program that has a couple of periodic tasks. Let's say
there are two tasks, one with a period of 3s and another with a period
of 4s. Let's say that exact triggering is not required.

The simplest way to do it is to just have appropriate delay statements
in main loops of these tasks. The advantage of such a setup is that
the tasks are completely self-contained and independent on any other
program entity. The disadvantage is that they are bound to the way
their periodicity is implemented.

Another way is to have additional task that will serve as a clock,
"ticking" two protected objects that are countdown counters with
single entry that waits for the counter to reach zero. In this case
the tick would be 1s, as the greatest common divisor of two periods.
The working tasks can then wait on respective entries in these
protected objects, which are released when the counters reach zero.
The advantage of this approach is that the notion of time is extracted
from the working tasks themselves and can be easily changed to
something else, like waiting on a different kind of clock or an
interrupts or whatever without disturbing main working tasks. The
disadvantage is that there are more program entities (+ two protected
countdowns + 1 ticking task) to handle.

What can you say about these two approaches? Which would you recommend
and when?

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-13 21:47 Periodic tasks - organization Maciej Sobczak
@ 2008-07-13 23:35 ` tmoran
  2008-07-14  3:52 ` george.priv
  2008-07-14  9:08 ` Alex R. Mosteo
  2 siblings, 0 replies; 13+ messages in thread
From: tmoran @ 2008-07-13 23:35 UTC (permalink / raw)


>What can you say about these two approaches? Which would you recommend
>and when?
  If the task is inherently periodic (updating a wall clock display, for
instance), use the simple periodic form.  If the task responds to some,
not necessarily periodic, event, then program it that way.  The only
legitimate reason to force the program into an unnatural form would be if
some so-far-unmentioned constraint (e.g. other interfaces to the task,
or performance, or management decree) required that.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-13 21:47 Periodic tasks - organization Maciej Sobczak
  2008-07-13 23:35 ` tmoran
@ 2008-07-14  3:52 ` george.priv
  2008-07-14  9:08 ` Alex R. Mosteo
  2 siblings, 0 replies; 13+ messages in thread
From: george.priv @ 2008-07-14  3:52 UTC (permalink / raw)


On Jul 13, 5:47 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> Consider a program that has a couple of periodic tasks. Let's say
> there are two tasks, one with a period of 3s and another with a period
> of 4s. Let's say that exact triggering is not required.

If you are not concerned about those two oscillators drifting out of
phase then independent tasks will be fine.  If you do then simpler
seems to be using delay until construct.

>
> The simplest way to do it is to just have appropriate delay statements
> in main loops of these tasks. The advantage of such a setup is that
> the tasks are completely self-contained and independent on any other
> program entity. The disadvantage is that they are bound to the way
> their periodicity is implemented.
>
> Another way is to have additional task that will serve as a clock,
> "ticking" two protected objects that are countdown counters with
> single entry that waits for the counter to reach zero. In this case
> the tick would be 1s, as the greatest common divisor of two periods.
> The working tasks can then wait on respective entries in these
> protected objects, which are released when the counters reach zero.
> The advantage of this approach is that the notion of time is extracted
> from the working tasks themselves and can be easily changed to
> something else, like waiting on a different kind of clock or an
> interrupts or whatever without disturbing main working tasks. The
> disadvantage is that there are more program entities (+ two protected
> countdowns + 1 ticking task) to handle.
>
> What can you say about these two approaches? Which would you recommend
> and when?
>
> --
> Maciej Sobczak *www.msobczak.com*www.inspirel.com

George



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-13 21:47 Periodic tasks - organization Maciej Sobczak
  2008-07-13 23:35 ` tmoran
  2008-07-14  3:52 ` george.priv
@ 2008-07-14  9:08 ` Alex R. Mosteo
  2008-07-14 15:31   ` Anh Vo
  2 siblings, 1 reply; 13+ messages in thread
From: Alex R. Mosteo @ 2008-07-14  9:08 UTC (permalink / raw)


Maciej Sobczak wrote:

> Consider a program that has a couple of periodic tasks. Let's say
> there are two tasks, one with a period of 3s and another with a period
> of 4s. Let's say that exact triggering is not required.
> 
> The simplest way to do it is to just have appropriate delay statements
> in main loops of these tasks. The advantage of such a setup is that
> the tasks are completely self-contained and independent on any other
> program entity. The disadvantage is that they are bound to the way
> their periodicity is implemented.
> 
> Another way is to have additional task that will serve as a clock,
> "ticking" two protected objects that are countdown counters with
> single entry that waits for the counter to reach zero. In this case
> the tick would be 1s, as the greatest common divisor of two periods.
> The working tasks can then wait on respective entries in these
> protected objects, which are released when the counters reach zero.
> The advantage of this approach is that the notion of time is extracted
> from the working tasks themselves and can be easily changed to
> something else, like waiting on a different kind of clock or an
> interrupts or whatever without disturbing main working tasks. The
> disadvantage is that there are more program entities (+ two protected
> countdowns + 1 ticking task) to handle.
> 
> What can you say about these two approaches? Which would you recommend
> and when?

I would use "delay until", which prevents any drift and still avoids using
extra machinery.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-14  9:08 ` Alex R. Mosteo
@ 2008-07-14 15:31   ` Anh Vo
  2008-07-16 21:38     ` Simon Wright
  0 siblings, 1 reply; 13+ messages in thread
From: Anh Vo @ 2008-07-14 15:31 UTC (permalink / raw)


On Jul 14, 2:08 am, "Alex R. Mosteo" <devn...@mailinator.com> wrote:
> Maciej Sobczak wrote:
> > Consider a program that has a couple of periodic tasks. Let's say
> > there are two tasks, one with a period of 3s and another with a period
> > of 4s. Let's say that exact triggering is not required.
>
> > The simplest way to do it is to just have appropriate delay statements
> > in main loops of these tasks. The advantage of such a setup is that
> > the tasks are completely self-contained and independent on any other
> > program entity. The disadvantage is that they are bound to the way
> > their periodicity is implemented.
>
> > Another way is to have additional task that will serve as a clock,
> > "ticking" two protected objects that are countdown counters with
> > single entry that waits for the counter to reach zero. In this case
> > the tick would be 1s, as the greatest common divisor of two periods.
> > The working tasks can then wait on respective entries in these
> > protected objects, which are released when the counters reach zero.
> > The advantage of this approach is that the notion of time is extracted
> > from the working tasks themselves and can be easily changed to
> > something else, like waiting on a different kind of clock or an
> > interrupts or whatever without disturbing main working tasks. The
> > disadvantage is that there are more program entities (+ two protected
> > countdowns + 1 ticking task) to handle.
>
> > What can you say about these two approaches? Which would you recommend
> > and when?
>
> I would use "delay until", which prevents any drift and still avoids using
> extra machinery.- Hide quoted text -
>
> - Show quoted text -

It is even better to use periodic timers built on top
Ada.Real_Time.Timing_Events. Then, explicit tasks are not needed.

Anh Vo



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-14 15:31   ` Anh Vo
@ 2008-07-16 21:38     ` Simon Wright
  2008-07-16 22:47       ` Anh Vo
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Wright @ 2008-07-16 21:38 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> writes:

> It is even better to use periodic timers built on top
> Ada.Real_Time.Timing_Events. Then, explicit tasks are not needed.

Only 'better' if that solution meets a need that's not met by the
straightforward approach.

I see that Timing Event Handlers are meant to be executed directly by
the protected handler operation
(http://www.adaic.com/standards/05rm/html/RM-D-15.html 25/2), so
clearly the intent is that some task should be released by the action
of the handler (similar to interrupts). So you still need explicit
tasks! just replacing a delay with a blocking wait on the PO which
will be triggered by the timing event -- a lot of complication.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-16 21:38     ` Simon Wright
@ 2008-07-16 22:47       ` Anh Vo
  2008-07-17 19:31         ` Simon Wright
  0 siblings, 1 reply; 13+ messages in thread
From: Anh Vo @ 2008-07-16 22:47 UTC (permalink / raw)


On Jul 16, 2:38 pm, Simon Wright <simon.j.wri...@mac.com> wrote:
> Anh Vo <anhvofrc...@gmail.com> writes:
> > It is even better to use periodic timers built on top
> > Ada.Real_Time.Timing_Events. Then, explicit tasks are not needed.
>
> Only 'better' if that solution meets a need that's not met by the
> straightforward approach.
>
> I see that Timing Event Handlers are meant to be executed directly by
> the protected handler operation
> (http://www.adaic.com/standards/05rm/html/RM-D-15.html25/2), so
> clearly the intent is that some task should be released by the action
> of the handler (similar to interrupts). So you still need explicit
> tasks! just replacing a delay with a blocking wait on the PO which
> will be triggered by the timing event -- a lot of complication.

Making two explicit tasks involves overhead for sure. It is true that
using PO construct is more complex than using two independent tasks.
Furthermore, an explicit task is not needed once the timer is started
initially.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-16 22:47       ` Anh Vo
@ 2008-07-17 19:31         ` Simon Wright
  2008-07-18 15:31           ` Anh Vo
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Wright @ 2008-07-17 19:31 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> writes:

> On Jul 16, 2:38�pm, Simon Wright <simon.j.wri...@mac.com> wrote:
>> Anh Vo <anhvofrc...@gmail.com> writes:
>> > It is even better to use periodic timers built on top
>> > Ada.Real_Time.Timing_Events. Then, explicit tasks are not needed.
>>
>> Only 'better' if that solution meets a need that's not met by the
>> straightforward approach.
>>
>> I see that Timing Event Handlers are meant to be executed directly by
>> the protected handler operation
>> (http://www.adaic.com/standards/05rm/html/RM-D-15.html25/2), so
>> clearly the intent is that some task should be released by the action
>> of the handler (similar to interrupts). So you still need explicit
>> tasks! just replacing a delay with a blocking wait on the PO which
>> will be triggered by the timing event -- a lot of complication.
>
> Making two explicit tasks involves overhead for sure. It is true that
> using PO construct is more complex than using two independent tasks.
> Furthermore, an explicit task is not needed once the timer is started
> initially.

But there are limits on what is permissible within a protected
procedure, are there not?

Not sure what you mean by "once the timer is started initially",
timing events are one-shot (once the event fires, it's cleared).

In the code below (my first try, excuse any stupidities & the need for
'Unresricted_Access) I reckon there are 11 extra logical LOC ...

with Ada.Real_Time.Timing_Events;
with Ada.Text_IO; use Ada.Text_IO;

procedure Periodic is
      
   protected Po is 
      procedure Handler (E : in out Ada.Real_Time.Timing_Events.Timing_Event);
      entry Wait;
   private
      Released : Boolean := False;
   end Po;
   protected body Po is
      procedure Handler (E : in out Ada.Real_Time.Timing_Events.Timing_Event)
      is
      begin
	 Released := True;
      end Handler;
      entry Wait when Released is
      begin
	 Released := False;
      end Wait;
   end Po;
      
   Ev : Ada.Real_Time.Timing_Events.Timing_Event;
   
   task T is end T;
   task body T is
   begin
      Put_Line ("setting the Event");
      New_Line;
      Ada.Real_Time.Timing_Events.Set_Handler 
	(Ev,
	 In_Time => Ada.Real_Time.To_Time_Span (1.0),
	 Handler => Po.Handler'Unrestricted_Access);
      Po.Wait;
      Put_Line ("t released.");
   end T;
   
begin
   null;
end Periodic;



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-17 19:31         ` Simon Wright
@ 2008-07-18 15:31           ` Anh Vo
  2008-07-18 16:22             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 13+ messages in thread
From: Anh Vo @ 2008-07-18 15:31 UTC (permalink / raw)


On Jul 17, 12:31 pm, Simon Wright <simon.j.wri...@mac.com> wrote:
> Anh Vo <anhvofrc...@gmail.com> writes:
> > On Jul 16, 2:38 pm, Simon Wright <simon.j.wri...@mac.com> wrote:
> >> Anh Vo <anhvofrc...@gmail.com> writes:
> >> > It is even better to use periodic timers built on top
> >> > Ada.Real_Time.Timing_Events. Then, explicit tasks are not needed.
>
> >> Only 'better' if that solution meets a need that's not met by the
> >> straightforward approach.
>
> >> I see that Timing Event Handlers are meant to be executed directly by
> >> the protected handler operation
> >> (http://www.adaic.com/standards/05rm/html/RM-D-15.html25/2), so
> >> clearly the intent is that some task should be released by the action
> >> of the handler (similar to interrupts). So you still need explicit
> >> tasks! just replacing a delay with a blocking wait on the PO which
> >> will be triggered by the timing event -- a lot of complication.
>
> > Making two explicit tasks involves overhead for sure. It is true that
> > using PO construct is more complex than using two independent tasks.
> > Furthermore, an explicit task is not needed once the timer is started
> > initially.
>
> But there are limits on what is permissible within a protected
> procedure, are there not?
>
> Not sure what you mean by "once the timer is started initially",
> timing events are one-shot (once the event fires, it's cleared).
>
> In the code below (my first try, excuse any stupidities & the need for
> 'Unresricted_Access) I reckon there are 11 extra logical LOC ...
>
> with Ada.Real_Time.Timing_Events;
> with Ada.Text_IO; use Ada.Text_IO;
>
> procedure Periodic is
>
>    protected Po is
>       procedure Handler (E : in out Ada.Real_Time.Timing_Events.Timing_Event);
>       entry Wait;
>    private
>       Released : Boolean := False;
>    end Po;
>    protected body Po is
>       procedure Handler (E : in out Ada.Real_Time.Timing_Events.Timing_Event)
>       is
>       begin
>          Released := True;
>       end Handler;
>       entry Wait when Released is
>       begin
>          Released := False;
>       end Wait;
>    end Po;
>
>    Ev : Ada.Real_Time.Timing_Events.Timing_Event;
>
>    task T is end T;
>    task body T is
>    begin
>       Put_Line ("setting the Event");
>       New_Line;
>       Ada.Real_Time.Timing_Events.Set_Handler
>         (Ev,
>          In_Time => Ada.Real_Time.To_Time_Span (1.0),
>          Handler => Po.Handler'Unrestricted_Access);
>       Po.Wait;
>       Put_Line ("t released.");
>    end T;
>
> begin
>    null;
> end Periodic;- Hide quoted text -
>
> - Show quoted text -

My design is completely different from yours. Indeed, an explicit task
is not needed. See Gem #15, Timers, for details.
http://www.adacore.com/2007/10/29/ada-gem-15/

A. Vo



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-18 15:31           ` Anh Vo
@ 2008-07-18 16:22             ` Dmitry A. Kazakov
  2008-07-19  1:37               ` Anh Vo
  2008-07-20  9:46               ` Simon Wright
  0 siblings, 2 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2008-07-18 16:22 UTC (permalink / raw)


On Fri, 18 Jul 2008 08:31:29 -0700 (PDT), Anh Vo wrote:

> On Jul 17, 12:31�pm, Simon Wright <simon.j.wri...@mac.com> wrote:

>> But there are limits on what is permissible within a protected
>> procedure, are there not?

[...]

> My design is completely different from yours. Indeed, an explicit task
> is not needed. See Gem #15, Timers, for details.
> http://www.adacore.com/2007/10/29/ada-gem-15/

Hmm, but it is exactly the design presented by Simon. The problem with it
is that the action fired upon a timer event is called from a protected
procedure.

This is IMO not what Maciej wanted, because as Simon has pointed out
protected procedures are very limited in what they allowed do and in how
they do it.

Another point is that even if that were the context of a task (which is
not), it still would be an unsatisfactory design, because simultaneously
triggered actions would block each other when overlapping.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-18 16:22             ` Dmitry A. Kazakov
@ 2008-07-19  1:37               ` Anh Vo
  2008-07-19 10:22                 ` Dmitry A. Kazakov
  2008-07-20  9:46               ` Simon Wright
  1 sibling, 1 reply; 13+ messages in thread
From: Anh Vo @ 2008-07-19  1:37 UTC (permalink / raw)


On Jul 18, 9:22 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Fri, 18 Jul 2008 08:31:29 -0700 (PDT), Anh Vo wrote:
> > On Jul 17, 12:31�pm, Simon Wright <simon.j.wri...@mac.com> wrote:
> >> But there are limits on what is permissible within a protected
> >> procedure, are there not?
>
> [...]
>
> > My design is completely different from yours. Indeed, an explicit task
> > is not needed. See Gem #15, Timers, for details.
> >http://www.adacore.com/2007/10/29/ada-gem-15/
>
> Hmm, but it is exactly the design presented by Simon. The problem with it
> is that the action fired upon a timer event is called from a protected
> procedure.

I hope you already looked at ada-gem-15 and see the difference.

> This is IMO not what Maciej wanted, because as Simon has pointed out
> protected procedures are very limited in what they allowed do and in how
> they do it.

Why is Protected Procedure limited for this purpose?

> Another point is that even if that were the context of a task (which is
> not), it still would be an unsatisfactory design, because simultaneously
> triggered actions would block each other when overlapping.

Again, look at the full code in Ada-Gem-15. There is no overlap action
at all.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-19  1:37               ` Anh Vo
@ 2008-07-19 10:22                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2008-07-19 10:22 UTC (permalink / raw)


On Fri, 18 Jul 2008 18:37:23 -0700 (PDT), Anh Vo wrote:

> On Jul 18, 9:22�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:

>> This is IMO not what Maciej wanted, because as Simon has pointed out
>> protected procedures are very limited in what they allowed do and in how
>> they do it.
> 
> Why is Protected Procedure limited for this purpose?

Because it is executed inside a protected action, see RM 9.5.1.

In particular, ada-gem-15 is a bounded error, because it calls to Put_Line
from a declared protected action. Note that Put_Line is potentially
blocking.

Even if Put_Line does not block, its execution time is unacceptable for a
protected action. Protected actions are thought having *semantically* zero
execution time.

[Yes, GNAT allows Put_Line in protected actions for debugging purpose, but
to do it in production code would be a very bad idea.]

>> Another point is that even if that were the context of a task (which is
>> not), it still would be an unsatisfactory design, because simultaneously
>> triggered actions would block each other when overlapping.
> 
> Again, look at the full code in Ada-Gem-15. There is no overlap action
> at all.

It would be if there *officially* existed a task doing the notification
callbacks.

*Unofficially*, depending on the implementation, the compiler might use one
task for all instances of Timing_Event or system services (like waitable
timers). In both cases you would have one system thread servicing all
callbacks one after another. Certainly, an implementation could choose to
use one task per each Timing_Event instance, but it would rather be
surprising, because there is no reason to do that, as the callback is
declared to fit into a protected action. Well, having said that, on a
multi-core CPU it could make sense to start one timer task for each core,
but I doubt that any Ada vendor would really care. There seems to be little
use in Ada.Real_Time.Timing_Events except for bare boards with hardware
timer interrupts mapped directly to Timing_Events.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Periodic tasks - organization
  2008-07-18 16:22             ` Dmitry A. Kazakov
  2008-07-19  1:37               ` Anh Vo
@ 2008-07-20  9:46               ` Simon Wright
  1 sibling, 0 replies; 13+ messages in thread
From: Simon Wright @ 2008-07-20  9:46 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Fri, 18 Jul 2008 08:31:29 -0700 (PDT), Anh Vo wrote:
>
>> On Jul 17, 12:31�pm, Simon Wright <simon.j.wri...@mac.com> wrote:
>
>>> But there are limits on what is permissible within a protected
>>> procedure, are there not?
>
> [...]
>
>> My design is completely different from yours. Indeed, an explicit
>> task is not needed. See Gem #15, Timers, for details.
>> http://www.adacore.com/2007/10/29/ada-gem-15/
>
> Hmm, but it is exactly the design presented by Simon. The problem with
> it is that the action fired upon a timer event is called from a
> protected procedure.
>
> This is IMO not what Maciej wanted, because as Simon has pointed out
> protected procedures are very limited in what they allowed do and in
> how they do it.

And further, they are called at interrupt priority (I haven't read up
enough to understand D-15 14/2, but see 25/2: 'executed directly by the
real-time clock interrupt mechanism'), so there are going to be
interesting issues related to shared variable access.

If you aren't running on an RTOS, why are you bothering with the added
complexity? and if you are, won't the standard Ada mechanisms (delay
until, etc) do the trick? (they do for us with VxWorks). I don't quite
buy the notion that RTOS => use timers (at least, not without supporting
them as a variation on the general notion of event, so that some events
can be scheduled to happen in the furure). Some thoughts on this here --
http://coldframe.sourceforge.net/coldframe/event-modelling.html



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2008-07-20  9:46 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-13 21:47 Periodic tasks - organization Maciej Sobczak
2008-07-13 23:35 ` tmoran
2008-07-14  3:52 ` george.priv
2008-07-14  9:08 ` Alex R. Mosteo
2008-07-14 15:31   ` Anh Vo
2008-07-16 21:38     ` Simon Wright
2008-07-16 22:47       ` Anh Vo
2008-07-17 19:31         ` Simon Wright
2008-07-18 15:31           ` Anh Vo
2008-07-18 16:22             ` Dmitry A. Kazakov
2008-07-19  1:37               ` Anh Vo
2008-07-19 10:22                 ` Dmitry A. Kazakov
2008-07-20  9:46               ` Simon Wright

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