comp.lang.ada
 help / color / mirror / Atom feed
* Re: "recursive" accept statement ??
  1998-12-15  0:00 ` Marc A. Criley
@ 1998-12-15  0:00   ` Matthew Heaney
  0 siblings, 0 replies; 8+ messages in thread
From: Matthew Heaney @ 1998-12-15  0:00 UTC (permalink / raw)


"Marc A. Criley" <marc.a.criley@lmco.com> writes:

> Also, as a matter of general principle, since a task rendezvous blocks
> both caller and callee while the accept block is executing, one usually
> tries to make that rendezvous as brief as possible.  

That's a fine guideline, but one that doesn't apply in this case.  

> Here's a way of doing that (which also eliminates the scoping/deadlock
> issue):
> 
> task body trace is
>    S : string(1..Max_String_Length);
>    L : Natural;  -- should be the 1..Max_String_Length subtype
> begin
>    accept Put (str : string) do
>       S(str'range) := Str;
>       L := S'Length;
>    end Put;
>    -- Caller is now released
> 
>    Ada.text_io.put(S(1..L));         -- works fine
>    Put(S(1..L));                     -- Now outside of Put entry's scope
>    New_Line;
> 
> end trace ;

This code is wrong.  If the first index of the input string is anything
other than 1, then the Put will print garbage.

It's also wrong because it will deadlock.  The Put that immediately
follows the call to Ada.Text_IO.Put is actually a call to the task
entry.

Here is the corrected version:

task body trace is
begin

   accept Put (str : string) do

       Ada.text_io.put(str);
       Ada.text_IO.put(Str);
       New_Line;

   end Put;

end trace ;


 




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

* Re: "recursive" accept statement ??
  1998-12-15  0:00 ` dennison
@ 1998-12-15  0:00   ` Matthew Heaney
  0 siblings, 0 replies; 8+ messages in thread
From: Matthew Heaney @ 1998-12-15  0:00 UTC (permalink / raw)


dennison@telepath.com writes:

> In article <1998Dec15.122957@lri.fr>,
>   fv@lri.fr (Frederic Voisin) wrote:
> > I have trouble understanding the behavior of the following program (or
> > the rationale
> > for allowing its behavior, if correct):
> > -------------------------------------
> > with Ada.text_io ; use Ada.text_io ;
> >
>           Ada.text_io.put(str);         -- works fine
> >           Put(Str);                     -- behave like trace.Put(str) ????
> >
> 
> > If allowed, what is the rationale behind, since such construct is much
> > error-proned
> 
> Some would say that doing a "use" is error prone, and that was the source of
> your problem. :-)

Using use is not the problem.  The problem is not understanding Ada's
scope rules.

I use use all the time.






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

* Re: "recursive" accept statement ??
  1998-12-15  0:00 "recursive" accept statement ?? Frederic Voisin
                   ` (2 preceding siblings ...)
  1998-12-15  0:00 ` David C. Hoos
@ 1998-12-15  0:00 ` Tucker Taft
  1998-12-23  0:00 ` Robert A Duff
  4 siblings, 0 replies; 8+ messages in thread
From: Tucker Taft @ 1998-12-15  0:00 UTC (permalink / raw)


Frederic Voisin (fv@lri.fr) wrote:

: ...
: If allowed, what is the rationale behind, since such construct is much
: error-proned
: (and I had a hard time finding it)
: Shouldn't it deserve a warning ?? 

As others have pointed out, the inner "Put" hides the one from Text_IO.

It would seem friendly to provide a warning when a task calls one
of its own entries, because it is certain to deadlock.
I suspect various compiler implementors are right now adding
this to their list of possible future "friendly warnings."

Unfortunately, it is not always trivial to create warnings which
are interpreted as "friendly" by all the recipients,
but this one looks like a good candidate...

: ... or a complain about ambiguity ?
: I did not find something really illuminating in the Reference Manual or
: Rationale...

As pointed out by others, entries are treated like procedures from the
point of view of hiding, and this is just like a procedure hiding
an outer definition with the same parameter profile.

: Thanks

--
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Intermetrics, Inc.  Burlington, MA  USA
An AverStar Company (www.averstar.com)




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

* "recursive" accept statement ??
@ 1998-12-15  0:00 Frederic Voisin
  1998-12-15  0:00 ` dennison
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Frederic Voisin @ 1998-12-15  0:00 UTC (permalink / raw)


I have trouble understanding the behavior of the following program (or
the rationale
for allowing its behavior, if correct):
-------------------------------------
with Ada.text_io ; use Ada.text_io ;

procedure Biz is

task trace is
     entry put(str : string) ;
end trace ;

task body trace is
begin
   accept Put (str : string) do
          Ada.text_io.put(str);         -- works fine
          Put(Str);                     -- behave like trace.Put(str) ????
          New_Line;
          end Put;
end trace ;

begin Trace.Put("Hello World");
end Biz;
---------------------------------------

When compiled with GNAT (gnat-3.10p on a Solaris machine) I get only the first
'Hello World" but not the second, while I would have expected the
Put(str) within
the "accept" statement to correspond to Ada.text_io.put and not to an
implicit
rendez-vous with the same task - as if I had written trace.put(str) -
that is sure
to deadlock !!

Is that the right behavior (omitting the name of the called task,
especially from
within itself !) or is it a bug (I cannot test it with another compiler)
?
If allowed, what is the rationale behind, since such construct is much
error-proned
(and I had a hard time finding it)
Shouldn't it deserve a warning ?? or a complain about ambiguity ?
I did not find something really illuminating in the Reference Manual or
Rationale...

Thanks




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

* Re: "recursive" accept statement ??
  1998-12-15  0:00 "recursive" accept statement ?? Frederic Voisin
  1998-12-15  0:00 ` dennison
@ 1998-12-15  0:00 ` Marc A. Criley
  1998-12-15  0:00   ` Matthew Heaney
  1998-12-15  0:00 ` David C. Hoos
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Marc A. Criley @ 1998-12-15  0:00 UTC (permalink / raw)


Frederic Voisin wrote:
> 
> I have trouble understanding the behavior of the following program (or
> the rationale
> for allowing its behavior, if correct):
> -------------------------------------
> with Ada.text_io ; use Ada.text_io ;
> 
> procedure Biz is
> 
> task trace is
>      entry put(str : string) ;
> end trace ;
> 
> task body trace is
> begin
>    accept Put (str : string) do
>           Ada.text_io.put(str);         -- works fine
>           Put(Str);                     -- behave like trace.Put(str) ????
>           New_Line;
>           end Put;
> end trace ;
> 
> begin Trace.Put("Hello World");
> end Biz;
> ---------------------------------------
> 
> When compiled with GNAT (gnat-3.10p on a Solaris machine) I get only the first
> 'Hello World" but not the second, while I would have expected the
> Put(str) within
> the "accept" statement to correspond to Ada.text_io.put and not to an
> implicit
> rendez-vous with the same task - as if I had written trace.put(str) -
> that is sure
> to deadlock !!

Deadlock is the expected behavior for this code.

> 
> Is that the right behavior (omitting the name of the called task,
> especially from
> within itself !) or is it a bug (I cannot test it with another compiler)
> ?
> If allowed, what is the rationale behind, since such construct is much
> error-proned
> (and I had a hard time finding it)
> Shouldn't it deserve a warning ?? or a complain about ambiguity ?

There's no ambiguity here.

This is simply a matter of scoping.  The entry declaration of Put:
   entry Put(str: String)
has a parameter profile identical to Text_IO's Put:
   procedure Put(Item : in  String)

Inside the accept block, the innermost entity having a name and
parameter profile matching "Put(str)" is the Put entry, therefore it
is recusively invoked and obviously deadlocks.

Identifiers in inner scopes hiding identical identifiers in outer
scopes is not uncommon, and issuing a warning whenever this occurs
would only rarely be of any utility.

Also, as a matter of general principle, since a task rendezvous blocks
both caller and callee while the accept block is executing, one usually
tries to make that rendezvous as brief as possible.  Here's a way of
doing that (which also eliminates the scoping/deadlock issue):

task body trace is
   S : string(1..Max_String_Length);
   L : Natural;  -- should be the 1..Max_String_Length subtype
begin
   accept Put (str : string) do
      S(str'range) := Str;
      L := S'Length;
   end Put;
   -- Caller is now released

   Ada.text_io.put(S(1..L));         -- works fine
   Put(S(1..L));                     -- Now outside of Put entry's scope
   New_Line;

end trace ;


> I did not find something really illuminating in the Reference Manual or
> Rationale...
> 
> Thanks

-- 
Marc A. Criley
Chief Software Architect
Lockheed Martin M&DS
marc.a.criley@lmco.com
Phone: (610) 354-7861
Fax  : (610) 354-7308




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

* Re: "recursive" accept statement ??
  1998-12-15  0:00 "recursive" accept statement ?? Frederic Voisin
  1998-12-15  0:00 ` dennison
  1998-12-15  0:00 ` Marc A. Criley
@ 1998-12-15  0:00 ` David C. Hoos
  1998-12-15  0:00 ` Tucker Taft
  1998-12-23  0:00 ` Robert A Duff
  4 siblings, 0 replies; 8+ messages in thread
From: David C. Hoos @ 1998-12-15  0:00 UTC (permalink / raw)



Frederic Voisin wrote in message <1998Dec15.122957@lri.fr>...
>I have trouble understanding the behavior of the following program (or
>the rationale
>for allowing its behavior, if correct):
The problem is that Trace.Put hides Ada.Text_IO.Put, so you need to use the
fully-qualified subprogram name.  This is also why many Ada coding standards
forbid the use of "use" clauses except to make infix operators visible.
>-------------------------------------
>with Ada.text_io ; use Ada.text_io ;
>
>procedure Biz is
>
>task trace is
>     entry put(str : string) ;
>end trace ;
>
>task body trace is
>begin
>   accept Put (str : string) do
>          Ada.text_io.put(str);         -- works fine
>          Put(Str);                     -- behave like trace.Put(str) ????
>          New_Line;
>          end Put;
>end trace ;
>
>begin Trace.Put("Hello World");
>end Biz;
>---------------------------------------
>
>When compiled with GNAT (gnat-3.10p on a Solaris machine) I get only the
first
>'Hello World" but not the second, while I would have expected the
>Put(str) within
>the "accept" statement to correspond to Ada.text_io.put and not to an
>implicit
>rendez-vous with the same task - as if I had written trace.put(str) -
>that is sure
>to deadlock !!
>
>Is that the right behavior (omitting the name of the called task,
>especially from
>within itself !) or is it a bug (I cannot test it with another compiler)
>?
>If allowed, what is the rationale behind, since such construct is much
>error-proned
>(and I had a hard time finding it)
>Shouldn't it deserve a warning ?? or a complain about ambiguity ?
>I did not find something really illuminating in the Reference Manual or
>Rationale...
>
>Thanks






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

* Re: "recursive" accept statement ??
  1998-12-15  0:00 "recursive" accept statement ?? Frederic Voisin
@ 1998-12-15  0:00 ` dennison
  1998-12-15  0:00   ` Matthew Heaney
  1998-12-15  0:00 ` Marc A. Criley
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: dennison @ 1998-12-15  0:00 UTC (permalink / raw)


In article <1998Dec15.122957@lri.fr>,
  fv@lri.fr (Frederic Voisin) wrote:
> I have trouble understanding the behavior of the following program (or
> the rationale
> for allowing its behavior, if correct):
> -------------------------------------
> with Ada.text_io ; use Ada.text_io ;
>
          Ada.text_io.put(str);         -- works fine
>           Put(Str);                     -- behave like trace.Put(str) ????
>

> If allowed, what is the rationale behind, since such construct is much
> error-proned

Some would say that doing a "use" is error prone, and that was the source of
your problem. :-)

--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: "recursive" accept statement ??
  1998-12-15  0:00 "recursive" accept statement ?? Frederic Voisin
                   ` (3 preceding siblings ...)
  1998-12-15  0:00 ` Tucker Taft
@ 1998-12-23  0:00 ` Robert A Duff
  4 siblings, 0 replies; 8+ messages in thread
From: Robert A Duff @ 1998-12-23  0:00 UTC (permalink / raw)


fv@lri.fr (Frederic Voisin) writes:

> with Ada.text_io ; use Ada.text_io ;
> 
> procedure Biz is
> 
> task trace is
>      entry put(str : string) ;
> end trace ;
> 
> task body trace is
> begin
>    accept Put (str : string) do
>           Ada.text_io.put(str);         -- works fine
>           Put(Str);                     -- behave like trace.Put(str) ????

The above "Put" refers to the entry, not to the procedure in Text_IO.
So it deadlocks.  The entry hides the other declaration of Put.

> When compiled with GNAT (gnat-3.10p on a Solaris machine) I get only the first
> 'Hello World" but not the second ...

And then it deadlocked, right?

> If allowed, what is the rationale behind, since such construct is much
> error-proned
> (and I had a hard time finding it)

Yes, I agree that hiding is error-prone.  I would prefer a rule that
made the above ambiguous (and therefore illegal).

The issue isn't accept statements, in particular.  You could have a
similar example with only procedures involved, and one procedure might
hide the one you *meant* to call.

Or something similar could happen with variable declarations,
or anything else.

Hiding causes something very similar to the "Beaujolais effect".
It is possible to insert a declaration into a working program, and have
it change its meaning, but still be legal.  That's a bad thing.
Hiding is really a "preference rule" -- inner things are preferred over
outer things and use-visible things.  And preference rules often cause
Beaujolais effects -- or in this case, something analogous.

> Shouldn't it deserve a warning ?? or a complain about ambiguity ?

The problem with warnings is that they're not standard.  It's not clear
(to the compiler writer, nor to the programmer) exactly which cases
should be warned about.

It *can* make sense to mention the name of an entry without the
task-name-dot prefix, at least in some unusual cases:

    task trace is
         entry put(str : string) ;
    end trace ;
    
    task body trace is

       task Nested;
       task body Nested is
       begin
	  Put("Hello, world."); -- No deadlock here.
       end Nested;

    begin
       accept Put (str : string) do
          declare
	     Y: String := Put.Str; -- No deadlock here.
	  begin
	     ...
          end;
       end Put:
    end Trace;

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




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

end of thread, other threads:[~1998-12-23  0:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-12-15  0:00 "recursive" accept statement ?? Frederic Voisin
1998-12-15  0:00 ` dennison
1998-12-15  0:00   ` Matthew Heaney
1998-12-15  0:00 ` Marc A. Criley
1998-12-15  0:00   ` Matthew Heaney
1998-12-15  0:00 ` David C. Hoos
1998-12-15  0:00 ` Tucker Taft
1998-12-23  0:00 ` Robert A Duff

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