* Termination of tasks waiting on a protected queue
@ 2014-05-18 7:32 Natasha Kerensikova
2014-05-18 9:24 ` anon
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Natasha Kerensikova @ 2014-05-18 7:32 UTC (permalink / raw)
Hello,
I have been having a task termination issue, and I'm wondering whether I
got my design wrong or whether I'm missing something, so I ask you to
help me on that.
The basic need is delegating potentially long jobs to a dedicated task
(or pool of tasks) so that the program flow generating the jobs and
continue quickly. I furthermore assume that the jobs are "fire and
forget", that there is no need to report anything about completion (or
lack of thereof) to the code that generated the jobs (or more
realistically, that reporting is performed through channels outside of
the scope of the problem).
So I went with the basic design below:
package Example is
type Job_Description is private;
function Create_Job (...) return Job_Description;
procedure Enqueue_Job (Job : in Job_Description);
private
package Job_Lists is new Ada.Containers.Doubly_Linked_Lists
(Job_Description);
protected Queue is
procedure Append (Job : in Job_Description);
entry Get_Next (Job : out Job_Description);
private
List : Job_Lists.List;
Has_Job : Boolean := False;
end Queue;
task Worker is
end Worker;
end Example;
package body Example is
procedure Enqueue_Job (Job : in Job_Description) is
begin
Queue.Append (Job);
end Enqueue_Job;
protected body Queue is
procedure Append (Job : in Job_Description) is
begin
List.Append (Job);
Has_Job := True;
end Append;
entry Get_Next (Job : out Job_Description)
when Has_Job is
begin
Job := List.First_Element;
List.Delete_First;
Has_Job := not List.Is_Empty;
end Get_Next;
end Queue;
task body Worker is
Job : Job_Description;
begin
loop
Queue.Get_Next (Job);
<actually to the job>
end loop;
end Worker;
end Example;
As you might have guessed, I have recently read a lot of material about
Ravenscar profile, and as far as I can tell this example does match the
profile, even though the original need happens in a much more relaxed
environment.
For example, without Ravenscar restrictions, the Worker task could
easily be turned into a task type, and use an array of them to
implement a pool of workers.
The problem is, how to terminate cleanly the worker tasks in a
non-Ravenscar environment when the main application is completed?
From my understanding of ARM 9.3, I need a terminate alternative in the
worker tasks. But those can only exist in selective accepts, so I have
to turn things around and make the task wait for one of its entries to
be called, rather than wait for an external protected entry.
But then, how can a worker task entry be used to solve my problem? A
protected operation cannot call a task entry, because it's potentially
blocking. The job generator cannot call the entry directly, because it
would block when the task is not ready, so I still need a queue between
the generator and the worker task.
Alternatively, I could use a special value for Job_Description (or a new
out parameter) to make the worker exit its infinite loop, and somehow
make the protect Queue object aware that the master is completed, so
that it can signal the worker task(s) to complete. But how can this be
implemented? Since the tasks block the finalization of the master, I
can't rely on a Finalize procedure to notify the protected object.
Thanks in advance for your help,
Natasha
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 7:32 Termination of tasks waiting on a protected queue Natasha Kerensikova
@ 2014-05-18 9:24 ` anon
2014-05-18 19:43 ` Natasha Kerensikova
2014-05-18 17:16 ` Jeffrey Carter
` (2 subsequent siblings)
3 siblings, 1 reply; 17+ messages in thread
From: anon @ 2014-05-18 9:24 UTC (permalink / raw)
try using a Select / terminate statements
task body Worker is
Job : Job_Description;
begin
loop
select
Queue.Get_Next (Job);
<actually to the job>
or
terminate ;
end select ;
end loop;
end Worker;
In <slrnlngofv.i0l.lithiumcat@nat.rebma.instinctive.eu>, Natasha Kerensikova <lithiumcat@instinctive.eu> writes:
>Hello,
>
>I have been having a task termination issue, and I'm wondering whether I
>got my design wrong or whether I'm missing something, so I ask you to
>help me on that.
>
>The basic need is delegating potentially long jobs to a dedicated task
>(or pool of tasks) so that the program flow generating the jobs and
>continue quickly. I furthermore assume that the jobs are "fire and
>forget", that there is no need to report anything about completion (or
>lack of thereof) to the code that generated the jobs (or more
>realistically, that reporting is performed through channels outside of
>the scope of the problem).
>
>So I went with the basic design below:
>
> package Example is
> type Job_Description is private;
>
> function Create_Job (...) return Job_Description;
> procedure Enqueue_Job (Job : in Job_Description);
>
> private
>
> package Job_Lists is new Ada.Containers.Doubly_Linked_Lists
> (Job_Description);
>
> protected Queue is
> procedure Append (Job : in Job_Description);
> entry Get_Next (Job : out Job_Description);
> private
> List : Job_Lists.List;
> Has_Job : Boolean := False;
> end Queue;
>
> task Worker is
> end Worker;
> end Example;
>
> package body Example is
> procedure Enqueue_Job (Job : in Job_Description) is
> begin
> Queue.Append (Job);
> end Enqueue_Job;
>
> protected body Queue is
> procedure Append (Job : in Job_Description) is
> begin
> List.Append (Job);
> Has_Job := True;
> end Append;
>
> entry Get_Next (Job : out Job_Description)
> when Has_Job is
> begin
> Job := List.First_Element;
> List.Delete_First;
> Has_Job := not List.Is_Empty;
> end Get_Next;
> end Queue;
>
> task body Worker is
> Job : Job_Description;
> begin
> loop
> Queue.Get_Next (Job);
> <actually to the job>
> end loop;
> end Worker;
> end Example;
>
>As you might have guessed, I have recently read a lot of material about
>Ravenscar profile, and as far as I can tell this example does match the
>profile, even though the original need happens in a much more relaxed
>environment.
>
>For example, without Ravenscar restrictions, the Worker task could
>easily be turned into a task type, and use an array of them to
>implement a pool of workers.
>
>The problem is, how to terminate cleanly the worker tasks in a
>non-Ravenscar environment when the main application is completed?
>
From my understanding of ARM 9.3, I need a terminate alternative in the
>worker tasks. But those can only exist in selective accepts, so I have
>to turn things around and make the task wait for one of its entries to
>be called, rather than wait for an external protected entry.
>
>But then, how can a worker task entry be used to solve my problem? A
>protected operation cannot call a task entry, because it's potentially
>blocking. The job generator cannot call the entry directly, because it
>would block when the task is not ready, so I still need a queue between
>the generator and the worker task.
>
>Alternatively, I could use a special value for Job_Description (or a new
>out parameter) to make the worker exit its infinite loop, and somehow
>make the protect Queue object aware that the master is completed, so
>that it can signal the worker task(s) to complete. But how can this be
>implemented? Since the tasks block the finalization of the master, I
>can't rely on a Finalize procedure to notify the protected object.
>
>
>Thanks in advance for your help,
>Natasha
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 9:24 ` anon
@ 2014-05-18 19:43 ` Natasha Kerensikova
0 siblings, 0 replies; 17+ messages in thread
From: Natasha Kerensikova @ 2014-05-18 19:43 UTC (permalink / raw)
Hello,
On 2014-05-18, anon@att.net <anon@att.net> wrote:
> try using a Select / terminate statements
It does not work. In the code below, "select" is immediately followed by
"Queue.Get_Next (Job)", which is an entry call,
so the "select" can be a timed entry call, a conditional entry call, or
an asynchronous transfer of control, but not a selective accept.
However, terminate alternatives can exist only in selective accepts.
> task body Worker is
> Job : Job_Description;
> begin
> loop
> select
> Queue.Get_Next (Job);
> <actually to the job>
> or
> terminate ;
> end select ;
> end loop;
> end Worker;
To put in GNAT's terms:
68. terminate ;
12
>>> statement expected
>>> only allowed alternative in timed entry call is delay
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 7:32 Termination of tasks waiting on a protected queue Natasha Kerensikova
2014-05-18 9:24 ` anon
@ 2014-05-18 17:16 ` Jeffrey Carter
2014-05-18 19:54 ` Natasha Kerensikova
2014-05-18 18:42 ` sbelmont700
2014-05-18 23:05 ` Brad Moore
3 siblings, 1 reply; 17+ messages in thread
From: Jeffrey Carter @ 2014-05-18 17:16 UTC (permalink / raw)
On 05/18/2014 12:32 AM, Natasha Kerensikova wrote:
>
> I have been having a task termination issue, and I'm wondering whether I
> got my design wrong or whether I'm missing something, so I ask you to
> help me on that.
>
> The basic need is delegating potentially long jobs to a dedicated task
> (or pool of tasks) so that the program flow generating the jobs and
> continue quickly. I furthermore assume that the jobs are "fire and
> forget", that there is no need to report anything about completion (or
> lack of thereof) to the code that generated the jobs (or more
> realistically, that reporting is performed through channels outside of
> the scope of the problem).
I have done something similar for pools of worker tasks. I used an instance of
PragmARC.Queue_Unbounded_Blocking to hold the job requests rather than rolling
my own for each task pool. The solution to termination was to use a timed entry
call to the queue, with another protected object with a function to indicate if
the pool tasks should end. The tasks looked like
Forever : loop
select
Job_Queue.Get (Item => Info);
Process (Info => Info);
or
delay Check_Interval;
exit Forever when Control.Finalizing;
end select;
end loop Forever;
Obviously not Ravenscar compliant.
Check_Interval was quite long, 2 seconds.
--
Jeff Carter
"If I could find a sheriff who so offends the citizens of Rock
Ridge that his very appearance would drive them out of town ...
but where would I find such a man? Why am I asking you?"
Blazing Saddles
37
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 17:16 ` Jeffrey Carter
@ 2014-05-18 19:54 ` Natasha Kerensikova
2014-05-18 21:54 ` Jeffrey Carter
0 siblings, 1 reply; 17+ messages in thread
From: Natasha Kerensikova @ 2014-05-18 19:54 UTC (permalink / raw)
Hello,
On 2014-05-18, Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> wrote:
> I have done something similar for pools of worker tasks. I used an
> instance of PragmARC.Queue_Unbounded_Blocking to hold the job requests
> rather than rolling my own for each task pool. The solution to
> termination was to use a timed entry call to the queue, with another
> protected object with a function to indicate if the pool tasks should
> end.
That's a solution I considered, along with the idea of outputing a
special value in the blocking protected entry to indicate that tasks
should end (choosing between both solutions depending on how unnatural
adding the shutdown order to the queue is, and how badly I want the
termination order to be immediate).
But I haven't managed to design a robust way of triggering the
indication that tasks should end.
This is a library-level queue and a library level task providing a
service to the whole application. So there is no object whose
finalization can be used as a trigger for the task shutdown order.
The only solution I see is to provide an explicit Shudown procedure that
sends the task shutdown signal, but it is fragile: what if the client
forgets to call it? or if an exception make control flow jump around it?
and what if the client calls it too early, and more jobs are added to
the queue?
> Obviously not Ravenscar compliant.
Well Ravenscar was only involved in my coming up with such a solution.
As soon as I'm thinking about task termination, I'm leaving Ravenscar
realm anyway.
Thanks for your help,
Natasha
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 19:54 ` Natasha Kerensikova
@ 2014-05-18 21:54 ` Jeffrey Carter
0 siblings, 0 replies; 17+ messages in thread
From: Jeffrey Carter @ 2014-05-18 21:54 UTC (permalink / raw)
On 05/18/2014 12:54 PM, Natasha Kerensikova wrote:
>
> This is a library-level queue and a library level task providing a
> service to the whole application. So there is no object whose
> finalization can be used as a trigger for the task shutdown order.
> The only solution I see is to provide an explicit Shudown procedure that
> sends the task shutdown signal, but it is fragile: what if the client
> forgets to call it? or if an exception make control flow jump around it?
> and what if the client calls it too early, and more jobs are added to
> the queue?
I had no access to the pool tasks once they were created, so calling a task
entry was not possible. The Control PO was library level, and was called so the
function returned True when the system was shutting down. There were
library-level tasks, too, so it wasn't the finalization of a controlled object
that made that call. The system knew when it was time to stop.
If you don't have that knowledge, then things get interesting. You may have to
accept the failings you discuss and push the responsibility off to the client.
--
Jeff Carter
"If I could find a sheriff who so offends the citizens of Rock
Ridge that his very appearance would drive them out of town ...
but where would I find such a man? Why am I asking you?"
Blazing Saddles
37
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 7:32 Termination of tasks waiting on a protected queue Natasha Kerensikova
2014-05-18 9:24 ` anon
2014-05-18 17:16 ` Jeffrey Carter
@ 2014-05-18 18:42 ` sbelmont700
2014-05-18 18:48 ` Jeffrey Carter
2014-05-19 21:49 ` Randy Brukardt
2014-05-18 23:05 ` Brad Moore
3 siblings, 2 replies; 17+ messages in thread
From: sbelmont700 @ 2014-05-18 18:42 UTC (permalink / raw)
My preferred method is to not queue the data type, per say, but a discriminated record that is either a 'data' or 'exit', with the former containing the item and the latter containing nothing. The producers then post an 'exit' item when it's time to shut down, that the consumers then use to exit the loop:
begin
loop
Blocking_Dequeue(x);
exit when x.type == Shutdown;
Do_Something (x.data);
end loop;
end;
The problem is making it exception proof, since finalization can't be used to do it automatically.
It has always seemed strange that Ada doesn't seem to have a way to block on multiple entries, in line with posix select() or waitformultipleobjects. I'd be happy with even just a function that can wait on an array of suspension objects.
-sb
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 18:42 ` sbelmont700
@ 2014-05-18 18:48 ` Jeffrey Carter
2014-05-18 20:51 ` sbelmont700
2014-05-19 21:49 ` Randy Brukardt
1 sibling, 1 reply; 17+ messages in thread
From: Jeffrey Carter @ 2014-05-18 18:48 UTC (permalink / raw)
On 05/18/2014 11:42 AM, sbelmont700@gmail.com wrote:
>
> It has always seemed strange that Ada doesn't seem to have a way to block on
> multiple entries, in line with posix select() or waitformultipleobjects. I'd
> be happy with even just a function that can wait on an array of suspension
> objects.
select
Entry1;
then abort
Entry2;
end select;
--
Jeff Carter
"If I could find a sheriff who so offends the citizens of Rock
Ridge that his very appearance would drive them out of town ...
but where would I find such a man? Why am I asking you?"
Blazing Saddles
37
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 18:48 ` Jeffrey Carter
@ 2014-05-18 20:51 ` sbelmont700
2014-05-18 21:44 ` Jeffrey Carter
0 siblings, 1 reply; 17+ messages in thread
From: sbelmont700 @ 2014-05-18 20:51 UTC (permalink / raw)
On Sunday, May 18, 2014 2:48:16 PM UTC-4, Jeffrey Carter wrote:
>
> select
>
> Entry1;
>
> then abort
>
> Entry2;
>
> end select;
>
It was my understanding that these would execute sequentially; that is, it would try Entry1 and, finding it closed, block on Entry2. I was referring to a "wait on all and select the first one to unblock" behavior.
-sb
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 20:51 ` sbelmont700
@ 2014-05-18 21:44 ` Jeffrey Carter
0 siblings, 0 replies; 17+ messages in thread
From: Jeffrey Carter @ 2014-05-18 21:44 UTC (permalink / raw)
On 05/18/2014 01:51 PM, sbelmont700@gmail.com wrote:
> On Sunday, May 18, 2014 2:48:16 PM UTC-4, Jeffrey Carter wrote:
>>
>> select
>>
>> Entry1;
>>
>> then abort
>>
>> Entry2;
>>
>> end select;
>>
>
> It was my understanding that these would execute sequentially; that is, it
> would try Entry1 and, finding it closed, block on Entry2. I was referring to
> a "wait on all and select the first one to unblock" behavior.
I don't think so. It will block on Entry1 while executing the code in the "then
abort" block, which will block on Entry2. If Entry1 completes before the block,
it will attempt to abort the execution of the block. If the block completes
before the trigger (Entry1), it will attempt to abort the call to the trigger.
Note that if an entry call has been accepted but not completed and not requeued
with abort, it's probably abort deferred, so the abort won't take place until
the entry call completes. So it's possible for both entry calls to complete.
I'm not saying this is a good solution, simply that there is a way to block on 2
entry calls at once.
--
Jeff Carter
"If I could find a sheriff who so offends the citizens of Rock
Ridge that his very appearance would drive them out of town ...
but where would I find such a man? Why am I asking you?"
Blazing Saddles
37
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 18:42 ` sbelmont700
2014-05-18 18:48 ` Jeffrey Carter
@ 2014-05-19 21:49 ` Randy Brukardt
2014-05-20 7:54 ` Dmitry A. Kazakov
1 sibling, 1 reply; 17+ messages in thread
From: Randy Brukardt @ 2014-05-19 21:49 UTC (permalink / raw)
<sbelmont700@gmail.com> wrote in message
news:3ab5fcf0-d2a8-4c82-ab51-02b829aebcaa@googlegroups.com...
> It has always seemed strange that Ada doesn't seem to have a way to block
> on
> multiple entries, in line with posix select() or waitformultipleobjects.
> I'd be happy
> with even just a function that can wait on an array of suspension objects.
There was such a proposal for Ada 9x. After much discussion, a report was
commissioned from the three user-implementor teams. All three reported that
the operation would be much more expensive to implement than it appears on
the surface. In particular, the people with hard real-time deadlines could
not use any imaginable implementation of the feature -- which would have
made it useless to the #1 constituency. The idea was dropped and never has
been raised since.
I've totally forgotten why that was, but if you (or someone else) could dig
up the reports, you could find out why it doesn't work in Ada. (I certainly
have a printed copy in a dusty box somewhere, but I'm not motivated to go
spelunking for it.)
[I wrote one of those three reports, but I have no idea where the original,
digital version of our report is. It's definitely not on my current
computer. If I could have found it, I could have told you the title of our
report, which might have helped you dig it up.]
Randy.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-19 21:49 ` Randy Brukardt
@ 2014-05-20 7:54 ` Dmitry A. Kazakov
2014-05-20 7:58 ` Dmitry A. Kazakov
0 siblings, 1 reply; 17+ messages in thread
From: Dmitry A. Kazakov @ 2014-05-20 7:54 UTC (permalink / raw)
On Mon, 19 May 2014 16:49:29 -0500, Randy Brukardt wrote:
> <sbelmont700@gmail.com> wrote in message
> news:3ab5fcf0-d2a8-4c82-ab51-02b829aebcaa@googlegroups.com...
>> It has always seemed strange that Ada doesn't seem to have a way to block
>> on multiple entries, in line with posix select() or waitformultipleobjects.
>> I'd be happy with even just a function that can wait on an array of suspension objects.
>
> There was such a proposal for Ada 9x. After much discussion, a report was
> commissioned from the three user-implementor teams. All three reported that
> the operation would be much more expensive to implement than it appears on
> the surface. In particular, the people with hard real-time deadlines could
> not use any imaginable implementation of the feature -- which would have
> made it useless to the #1 constituency. The idea was dropped and never has
> been raised since.
For the OP problem, which is quite common, it would be enough to allow
single terminate alternative in select. Then code could be written as:
task body Worker is
Job : Job_Description;
begin
loop
select
Queue.Get_Next (Job);
-- Do the job
or delay 1.0;
end select;
select -- This is not Ada!
terminate;
else
exit;
end select;
end loop;
end Worker;
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 7:32 Termination of tasks waiting on a protected queue Natasha Kerensikova
` (2 preceding siblings ...)
2014-05-18 18:42 ` sbelmont700
@ 2014-05-18 23:05 ` Brad Moore
2014-05-19 7:28 ` Natasha Kerensikova
2014-05-27 11:08 ` Alejandro R. Mosteo
3 siblings, 2 replies; 17+ messages in thread
From: Brad Moore @ 2014-05-18 23:05 UTC (permalink / raw)
On 14-05-18 01:32 AM, Natasha Kerensikova wrote:
> The problem is, how to terminate cleanly the worker tasks in a
> non-Ravenscar environment when the main application is completed?
>
> From my understanding of ARM 9.3, I need a terminate alternative in the
> worker tasks. But those can only exist in selective accepts, so I have
> to turn things around and make the task wait for one of its entries to
> be called, rather than wait for an external protected entry.
>
> But then, how can a worker task entry be used to solve my problem? A
> protected operation cannot call a task entry, because it's potentially
> blocking. The job generator cannot call the entry directly, because it
> would block when the task is not ready, so I still need a queue between
> the generator and the worker task.
A protected entry can however requeue to a task entry.
I was faced with a similar problem in the non-Ravenscar task pools in
Paraffin.
I did not want the programmer to have to call some protected subprogram
to trigger the task pool to terminate. I also did not want to have to
wait for a timeout to expire before the application could exit. I wanted
it to be immediate.
So in your example, it might look something like;
package body Example is
function Create_Job return Job_Description is
Result : Job_Description;
begin
return Result;
end Create_Job;
procedure Enqueue_Job (Job : in Job_Description) is
begin
Queue.Append (Job);
end Enqueue_Job;
protected body Queue is
entry Append (Job : in Job_Description) when True is
begin
if not Idle then
requeue Worker.Work_Queued;
else
List.Append (Job);
end if;
end Append;
procedure Get_Next (Job : out Job_Description) is
begin
Job := List.First_Element;
List.Delete_First;
end Get_Next;
function Is_Empty return Boolean is
begin
return List.Is_Empty;
end Is_Empty;
procedure Worker_Idle is
begin
Idle := True;
end Worker_Idle;
function Worker_Is_Idle return Boolean is
begin
return Idle;
end Worker_Is_Idle;
end Queue;
task body Worker is
Job : Job_Description;
begin
loop
begin
Queue.Worker_Idle;
if not Queue.Is_Empty then
Queue.Get_Next (Job);
else
select
accept Work_Queued (Next_Job : Job_Description) do
Job := Next_Job;
end Work_Queued;
or
terminate;
end select;
end if;
-- <actually to the job>
end;
end loop;
end Worker;
end Example;
Brad
> Thanks in advance for your help,
> Natasha
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 23:05 ` Brad Moore
@ 2014-05-19 7:28 ` Natasha Kerensikova
2014-05-27 11:08 ` Alejandro R. Mosteo
1 sibling, 0 replies; 17+ messages in thread
From: Natasha Kerensikova @ 2014-05-19 7:28 UTC (permalink / raw)
Hello,
On 2014-05-18, Brad Moore <brad.moore@shaw.ca> wrote:
> I was faced with a similar problem in the non-Ravenscar task pools in
> Paraffin.
>
> I did not want the programmer to have to call some protected subprogram
> to trigger the task pool to terminate. I also did not want to have to
> wait for a timeout to expire before the application could exit. I wanted
> it to be immediate.
That looks indeed very similar to what I had in mind.
> So in your example, it might look something like;
Your example is exactly what I was looking for when posting here.
Thanks a lot!
However I'm considering merging the functionalities of Worker_Idle,
Is_Empty and Get_Next into a single protected procedure. Something like
procedure Get_Next
(Job : out Job_Description;
Idle : out Boolean) is
begin
if List.Is_Empty then
Idle := True;
Queue.Idle := True;
else
Job := List.First_Element;
List.Delete_First;
end if;
end Get_Next;
But then the solution is a bit more difficult to scale to multiple
worker tasks. Maybe with an array of Boolean for Idle. Fortunately I
don't have to deal with that for now.
Thanks again for the solution,
Natasha
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-18 23:05 ` Brad Moore
2014-05-19 7:28 ` Natasha Kerensikova
@ 2014-05-27 11:08 ` Alejandro R. Mosteo
2014-05-28 1:04 ` Brad Moore
1 sibling, 1 reply; 17+ messages in thread
From: Alejandro R. Mosteo @ 2014-05-27 11:08 UTC (permalink / raw)
On Monday, May 19, 2014 1:05:59 AM UTC+2, Brad Moore wrote:
> On 14-05-18 01:32 AM, Natasha Kerensikova wrote:
>
> > The problem is, how to terminate cleanly the worker tasks in a
>
> > non-Ravenscar environment when the main application is completed?
>
> >
>
> > From my understanding of ARM 9.3, I need a terminate alternative in the
>
> > worker tasks. But those can only exist in selective accepts, so I have
>
> > to turn things around and make the task wait for one of its entries to
>
> > be called, rather than wait for an external protected entry.
>
> >
>
> > But then, how can a worker task entry be used to solve my problem? A
>
> > protected operation cannot call a task entry, because it's potentially
>
> > blocking. The job generator cannot call the entry directly, because it
>
> > would block when the task is not ready, so I still need a queue between
>
> > the generator and the worker task.
>
>
>
> A protected entry can however requeue to a task entry.
>
>
>
> I was faced with a similar problem in the non-Ravenscar task pools in
>
> Paraffin.
>
>
>
> I did not want the programmer to have to call some protected subprogram
>
> to trigger the task pool to terminate.
Could an atomic boolean be used to avoid a protected object? Given that after it being set it wouldn't be unset, and there's no race condition, I wonder.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Termination of tasks waiting on a protected queue
2014-05-27 11:08 ` Alejandro R. Mosteo
@ 2014-05-28 1:04 ` Brad Moore
0 siblings, 0 replies; 17+ messages in thread
From: Brad Moore @ 2014-05-28 1:04 UTC (permalink / raw)
On 14-05-27 05:08 AM, Alejandro R. Mosteo wrote:
> On Monday, May 19, 2014 1:05:59 AM UTC+2, Brad Moore wrote:
>> On 14-05-18 01:32 AM, Natasha Kerensikova wrote:
>>
>>> The problem is, how to terminate cleanly the worker tasks in a
>>
>>> non-Ravenscar environment when the main application is completed?
>>
>>>
>>
>>> From my understanding of ARM 9.3, I need a terminate alternative in the
>>
>>> worker tasks. But those can only exist in selective accepts, so I have
>>
>>> to turn things around and make the task wait for one of its entries to
>>
>>> be called, rather than wait for an external protected entry.
>>
>>>
>>
>>> But then, how can a worker task entry be used to solve my problem? A
>>
>>> protected operation cannot call a task entry, because it's potentially
>>
>>> blocking. The job generator cannot call the entry directly, because it
>>
>>> would block when the task is not ready, so I still need a queue between
>>
>>> the generator and the worker task.
>>
>>
>>
>> A protected entry can however requeue to a task entry.
>>
>>
>> I did not want the programmer to have to call some protected subprogram
>>
>> to trigger the task pool to terminate.
>
> Could an atomic boolean be used to avoid a protected object? Given that after it being set it wouldn't be unset, and there's no race condition, I wonder.
>
The problem is not the protected subprogram. It is having to force the
programmer to explicitly specify somewhere in the code a trigger to
initiate the destruction of the task pool, whether via a protected
object or setting an atomic boolean, or some other means.
Setting the trigger before the main task exits for instance, is error
prone because there may be other tasks executing that might still want
to use the task pool.
Using the mechanism I suggested means the task pool does not get
destroyed until all tasks have completed, since the main task wont exit
until all other tasks have either completed or are waiting on a select
statement with a Terminate alternative.
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2014-05-28 1:04 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-18 7:32 Termination of tasks waiting on a protected queue Natasha Kerensikova
2014-05-18 9:24 ` anon
2014-05-18 19:43 ` Natasha Kerensikova
2014-05-18 17:16 ` Jeffrey Carter
2014-05-18 19:54 ` Natasha Kerensikova
2014-05-18 21:54 ` Jeffrey Carter
2014-05-18 18:42 ` sbelmont700
2014-05-18 18:48 ` Jeffrey Carter
2014-05-18 20:51 ` sbelmont700
2014-05-18 21:44 ` Jeffrey Carter
2014-05-19 21:49 ` Randy Brukardt
2014-05-20 7:54 ` Dmitry A. Kazakov
2014-05-20 7:58 ` Dmitry A. Kazakov
2014-05-18 23:05 ` Brad Moore
2014-05-19 7:28 ` Natasha Kerensikova
2014-05-27 11:08 ` Alejandro R. Mosteo
2014-05-28 1:04 ` Brad Moore
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox