From: Jeffrey R. Carter on
Dmitry A. Kazakov wrote:
>
> If abort to happen after *completion* of the rendezvous then the above
> shall not deadlock. (I checked this under GNAT/Windows, it deadlocks
> there.)

Under Linux/GNAT-gcc 4.3, this deadlocks as given, but does not if a "delay
1.0;" is included in the task before the accept.

--
Jeff Carter
"From this day on, the official language of San Marcos will be Swedish."
Bananas
28
From: Adam Beneschan on
On Apr 28, 5:20 pm, "Jeffrey R. Carter"
<spam.jrcarter....(a)spam.acm.org> wrote:
> Dmitry A. Kazakov wrote:
>
> >    protected Event is
> >       procedure Signal;
> >       entry Wait;
> >    private
> >       Signaled : Boolean := False;
> >    end Event;
>
> >    protected body Event is
> >       procedure Signal is
> >       begin
> >          Signaled := True;
> >       end Signal;
> >       entry Wait when Signaled is
> >       begin
> >          Signaled := False;
> >       end;
> >    end Event;
>
> >    task PID is
> >       entry Call;
> >    end PID;
>
> >    task body PID is
> >    begin
> >       accept Call do Event.Wait; end;
> >    end PID;
>
> > begin
> >   select
> >      PID.Call;  -- Blocked in the rendezvous
> >   then abort
> >      delay 2.0;
> >      Event.Signal; -- Releases the rendezvous after 2s
> >   end select;
>
> > If abort to happen after *completion* of the rendezvous then the above
> > shall not deadlock. (I checked this under GNAT/Windows, it deadlocks
> > there.)
>
> Here the call to PID.Call is not queued, but is accepted immediately, and does
> not encounter an explicit requeue-with-abort.

Is that necessarily the case? Since there aren't any priorities
specified, I don't think it's defined whether the body of the main
procedure (assuming it's a procedure) starts running first, or the
body of PID (assuming a single processor). Which means that the entry
call could be queued. Actually, on second thought, I think that for
some dispatching policies the main procedure *will* be executed first,
which means that the SELECT is executed before the body of PID starts,
which means the call *is* queued. Of course, it will be accepted
"almost" immediately; but since the call is briefly queued, the
language of 9.7.4 means that the abortable part is started. Then,
during "delay 2.0", PID is started, the call is accepted, but it
doesn't complete. Then the delay finishes and the Signal occurs; an
attempt is made to cancel the entry call PID.Call, but that has no
effect since cancellation only works when the call is on a queue
(9.5.3(20)). Anyway, as soon as the Signal occurs, the Wait
completes, then the entry call to PID.Call completes, and then
everything is done. At least that's how I understand things, but I
could be wrong.

In any event, though, writing code like this has to be horrible since
you can't tell whether it will deadlock or not.

-- Adam
From: Jeffrey R. Carter on
Adam Beneschan wrote:
>
> Is that necessarily the case? Since there aren't any priorities
> specified, I don't think it's defined whether the body of the main
> procedure (assuming it's a procedure) starts running first, or the
> body of PID (assuming a single processor).

That's a big assumption, especially today. From pretty cheap systems on up,
almost everything has at least 2 processors these days. Certainly that's the
case for the system on which I tested it, and found that it deadlocks as
originally written, but doesn't if "delay 1.0;" is added to the task before the
accept.

--
Jeff Carter
"From this day on, the official language of San Marcos will be Swedish."
Bananas
28
From: Dmitry A. Kazakov on
On Wed, 28 Apr 2010 17:47:02 -0700, Jeffrey R. Carter wrote:

> Dmitry A. Kazakov wrote:
>>
>> If abort to happen after *completion* of the rendezvous then the above
>> shall not deadlock. (I checked this under GNAT/Windows, it deadlocks
>> there.)
>
> Under Linux/GNAT-gcc 4.3, this deadlocks as given, but does not if a "delay
> 1.0;" is included in the task before the accept.

You are right.

Much implementation burden just in order to achieve a race condition!

Luckily ATC is a no-no in my coding standard anyway.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Adam Beneschan on
On Apr 28, 9:25 pm, "Jeffrey R. Carter"
<spam.jrcarter....(a)spam.acm.org> wrote:
> Adam Beneschan wrote:
>
> > Is that necessarily the case?  Since there aren't any priorities
> > specified, I don't think it's defined whether the body of the main
> > procedure (assuming it's a procedure) starts running first, or the
> > body of PID (assuming a single processor).
>
> That's a big assumption, especially today. From pretty cheap systems on up,
> almost everything has at least 2 processors these days. Certainly that's the
> case for the system on which I tested it, and found that it deadlocks as
> originally written, but doesn't if "delay 1.0;" is added to the task before the
> accept.

Hmmm... I haven't studied the dispatching rules enough to know how
multiple processors affect things---that's why I assumed a single
processor, for simplicity. If there are more than one, however, and
if the body of PID will get assigned to run on a different processor
than the main thread, then I'd think that makes things worse---you
can't tell at all whether the SELECT or the ACCEPT will occur first,
and there isn't any reason that it should work the same every time you
run it. Again, I haven't thoroughly studied the new Ada 2005 language
dealing with dispatching, and I don't know what assumptions or
defaults GNAT uses, so perhaps there's some predictable reason why the
ACCEPT would occur first.

-- Adam