From: Hibou57 (Yannick Duchêne) on
On 5 fév, 22:40, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
wrote:
> This is illegal, because protected procedure shall not perform potentially
> blocking actions (like I/O.
As Jeffrey pointed out as well. I will check the RM about it (I have
to establish I've missed it).

> You do not need to worry about that. Unless you are using pointers, the
> task object's scope encloses any calls to its entries. Therefore it simply
> cannot terminate due to its finalization before any entry call.

**it simply cannot terminate due to its finalization before any entry
call**

That's clever to notice ! OK, I see. Now I understand Jeffrey's
doubts.

> If you want garbage collection because of pointers involved then just do
> it. Don't break the task interface, make a handle type pointing to the task
> object. When the last handle vanishes, deallocate the task. That is.
“ Deallocate the task ” ? If I want to deallocate, I have to request
it to completes, and for the latter, I need it to have a corresponding
request entry... which would need to be public (as private entry
accessible from implementation is not possible).

> Task component does not work in most real-life cases.
My words was wrong : I was not to talk about using task as record
components, I was to say task may be implementation details, just like
record components are.

> Yes, an entry call can be syntactically and semantically different than a
> call to a procedure.
Syntactically : can be wrapped in a procedure call.
Semantically : sure if protected objects are required to not invoke
blocking operations, this is semantically different.

> You can print from the rendezvous. That is not a problem. Some tight
> implementations would prefer buffering in the rendezvous in order to
> release the caller as soon as possible (minimizing the effect of priority
> inversion). I.e. Text is first copied into the task's buffer during the
> rendezvous and printed later outside the rendezvous before accepting the
> new one. Assuming that the callers run at a higher priority and do not
> print very often leaving the processor free most of the time, this would
> give better response times in the callers (at the cost of some overall
> performance hit).
I like this hint (have a taste of real-time design by the way).
From: sjw on
On Feb 5, 10:09 pm, Hibou57 (Yannick Duchêne)
<yannick_duch...(a)yahoo.fr> wrote:
> On 5 fév, 22:40, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>

> > If you want garbage collection because of pointers involved then just do
> > it. Don't break the task interface, make a handle type pointing to the task
> > object. When the last handle vanishes, deallocate the task. That is.
>
> “ Deallocate the task ” ? If I want to deallocate, I have to request
> it to completes, and for the latter, I need it to have a corresponding
> request entry... which would need to be public (as private entry
> accessible from implementation is not possible).

You could just abort the task before freeing it.

With GNAT (maybe just with older versions, maybe not on all
platforms), if you free a task before it has terminated it will
silently not do the deallocation. The trick is to loop until
'Terminated is True.

I had to create a scavenger task; tasks that had been aborted were
placed on a queue for the scavenger task to free when the task had
terminated. Fairly gruesome generics involved.
From: Hibou57 (Yannick Duchêne) on
On 5 fév, 22:38, "Jeffrey R. Carter" <spam.jrcarter....(a)spam.acm.org>
wrote:
> Technically this is a bounded error: Ada.Text_IO.Put* operations are potentially
> blocking, and should not be called from a protected operation.

On 5 fév, 22:40, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
wrote:
> This is illegal, because protected procedure shall not perform potentially
> blocking actions (like I/O.

Here is the reference (for any other peoples who read this thread) :
First occurrence of this requirement appears as an example in [ARM
9.5(4.e)] :

procedure Op2 is
begin
Op1; -- An internal call.
Pt.Op1; -- Another internal call.
PO.Op1; -- An external call. It the current instance is PO, then
-- this is a bounded error (see 9.5.1).
Other_Object.Some_Op; -- An external call.
end Op2;

Then formally stated at [ARM 9.5.1(8)] :
“ During a protected action, it is a bounded error to invoke an
operation that is potentially blocking. ” (follows a list of
operations defined to be potentially blocking)
And later in [ARM 9.5.1(17)] :
“ If the bounded error is detected, Program_Error is raised. If not
detected, the bounded error might result in deadlock or a (nested)
protected action on the same target object. ”

So it is not guaranteed to be a bounded error, as nested protected
action may succeed.

By as soon as it is said it is a potential error, ... all is said.
From: Hibou57 (Yannick Duchêne) on
On 6 fév, 03:20, Hibou57 (Yannick Duchêne) <yannick_duch...(a)yahoo.fr>
wrote:
> By as soon as it is said it is a potential error, ... all is said.
Tipo mistake : “ But as soon ” instead of “ By as soon ”
From: Jeffrey R. Carter on
Hibou57 (Yannick Duch�ne) wrote:
>
> � If the bounded error is detected, Program_Error is raised. If not
> detected, the bounded error might result in deadlock or a (nested)
> protected action on the same target object. �
>
> So it is not guaranteed to be a bounded error, as nested protected
> action may succeed.

No, it is a bounded error. A bounded error has a finite set of possible effects.
One of the possible effects of this particular bounded error is that the
operation will complete normally.

See also pragma Detect_Blocking (ARM H.5); without it an implementation may
choose to never detect potentially blocking operations and never raise
Program_Error. This seems to be the way GNAT handles these.

--
Jeff Carter
"He didn't get that nose from playing ping-pong."
Never Give a Sucker an Even Break
110