comp.lang.ada
 help / color / mirror / Atom feed
* Re: Streams and Concurrency
  1998-12-30  0:00 Streams and Concurrency James S. Rogers
@ 1998-12-29  0:00 ` David Botton
  1998-12-30  0:00   ` James S. Rogers
  1998-12-30  0:00   ` dennison
  1998-12-30  0:00 ` dennison
  1 sibling, 2 replies; 35+ messages in thread
From: David Botton @ 1998-12-29  0:00 UTC (permalink / raw)


Would you be able to post a small sample demonstrating this.

David Botton

James S. Rogers wrote in message <76c3tv$acs@bgtnsc02.worldnet.att.net>...
>A question was recently raised about task safe use of streams.

ETC....








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

* Re: Streams and Concurrency
  1998-12-30  0:00 Streams and Concurrency James S. Rogers
  1998-12-29  0:00 ` David Botton
@ 1998-12-30  0:00 ` dennison
  1998-12-30  0:00   ` Robert I. Eachus
  1999-01-11  0:00   ` Bulk synchronous model for IO (was Re: Streams and Concurrency) Kevin Rigotti
  1 sibling, 2 replies; 35+ messages in thread
From: dennison @ 1998-12-30  0:00 UTC (permalink / raw)


In article <76c3tv$acs@bgtnsc02.worldnet.att.net>,
  "James S. Rogers" <jimmaureenrogers@worldnet.att.net> wrote:
> would be the typical Ada 83 approach.  The more modern, and
> more efficient approach in Ada 95 is to have encapsulate the stream
> in a protected object.  All access will be correctly and effectively
> controlled by the protected object mechanism.

That's the first thing I thought of too. This solution protects the stream
itself from corruption just fine. The problem is that it provides absolutely
no protection for the *data* in the stream. If I do a 'Write of a record,
that gets translated into *several* "Write" calls to the stream, not just
one. There's nothing stopping another task from making a call to the stream's
Write subprogram in the middle of my record's 'Write. There's nothing
stopping the stream service task from calling the stream's Read procedure in
the middle of my 'Write either. Making the stream a proteced object does
nothing for me here.

The design of streams makes this problem basicly intractable at any level but
the client level. It can't be done just by adding code to the stream
implementation.

The sad thing is that this isn't even the biggest problem. The fun *really*
starts when you want to read the data back in safely without blocking...

--
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] 35+ messages in thread

* Re: Streams and Concurrency
  1998-12-29  0:00 ` David Botton
  1998-12-30  0:00   ` James S. Rogers
@ 1998-12-30  0:00   ` dennison
  1998-12-30  0:00     ` Tucker Taft
  1 sibling, 1 reply; 35+ messages in thread
From: dennison @ 1998-12-30  0:00 UTC (permalink / raw)


In article <76cat4$2ldc$1@news.gate.net>,
  "David Botton" <dbotton@hotmail.com> wrote:
> Would you be able to post a small sample demonstrating this.
>
> David Botton
>
> James S. Rogers wrote in message <76c3tv$acs@bgtnsc02.worldnet.att.net>...
> >A question was recently raised about task safe use of streams.
>
> ETC....
>
>

Actually, I already have code that does that and probably could post it if
you really want to see it. Unfortunately, it doesn't really solve the problem
unless don't mind interleaved data on your stream. Also, if your reader task
does any kind of extra blocking or protocol on the data, he could concievably
end up doing that on every single non-composite field that was in your
structure. (Ewww!)

--
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] 35+ messages in thread

* Re: Streams and Concurrency
  1998-12-29  0:00 ` David Botton
@ 1998-12-30  0:00   ` James S. Rogers
  1998-12-30  0:00     ` dennison
  1998-12-31  0:00     ` Jean-Pierre Rosen
  1998-12-30  0:00   ` dennison
  1 sibling, 2 replies; 35+ messages in thread
From: James S. Rogers @ 1998-12-30  0:00 UTC (permalink / raw)


Following is a modest example of what I mean about
encapsulating a stream in a protected object.

The example uses Ada.Streams.Stream_Io for simplicity.  You can
reasonably substitute your own stream implementation as needed.

Note that the file name for the log file is passed as a discriminant to
the protected type.

I believe this solution solves the interleaving problem.  The read and
write operations will be atomic.  The write operation will not complete
until all 'write operations for the tagged type complete.  The key is
that the task calling the protected write and read operations is
ignorant of the use of a stream.  No stream operations occur outside
the protection of the protected type.

--------------------------------------------------------------------------
-- Simple Example of using streams in a protected object for access by
-- multiple tasks.
--------------------------------------------------------------------------
   package Type_Hierarchy is
      type Base_Type is tagged private;

   -- Add dispatching operations to the Base_type

      type First_Child is new Base_Type with private;

   -- Add or override operations for First_Child

   private

      type Base_Type is tagged record
            Date : String(1..10);
            Time : String(1..8);
         end record;

      type First_Child is new Base_type with record
            Voltage : Float;
         end record;
   end Type_Hierarchy;


   with Type_Hierarchy;
   use Type_Hierarchy;
   with Ada.Steams.Stream_Io;

   package Multi_Task_Logging is

      protected type Log_Stream (Log_Name : String) is
         Procedure Write(Item : in Base_Type'Class);
         Entry Read(Item : out Base_Type'Class);
      private
         File : Ada.Streams.Stream_Io.File_Type;
         Log_Access : Ada.Streams.Stream_Io.Stream_Access :=
            Ada.Streams.Stream_Io.Stream(File => File);
      end Log_Stream;
   end Multi_Tasking_Logging;

   package body Multi_Tasking_Logging is

      protected body Log_Stream is
         Procedure Write(Item : in Base_Type'Class) is
         begin
            if not Ada.Streams.Stream_Io.Is_Open(File) then
               Ada.Streams.Stream_Io.Open(File => File,
                                          Name => Log_Name,
                                          Mode =>
Ada.Streams.Stream_Io.Append_File);
            else
               Ada.Streams.Stream_Io.Reset(File => File,
                                           Mode =>
Ada.Streams.Stream_Io.Append_File);
            end if;
            Base_Type'Class'Write(Stream => Log_Access, Item => Item);
         end Write;

         Entry Read(Item : out Base_Type'Class) when not
         Ada.Streams.Stream_Io.End_of_File(File) is
         begin
            if not Ada.Streams.Stream_Io.is_Open(File) then
               Ada.Streams.Stream_Io.Open(File => File,
                                          Name => Log_Name,
                                          Mode =>
Ada.Streams.Stream_Io.In_File);
            else
               Ada.Streams.Stream_Io.Reset(File => File,
                                           Mode =>
Ada.Streams.Stream_Io.In_File);
            end if;
            Base_Type'Class'Read( Stream => Log_Access, Item => Item);
         end Read;
      end Log_Stream;

   End Multi_Tasking_Logging;

-----------------------------------

Jim Rogers
Colorado Springs, Colorado USA






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

* Re: Streams and Concurrency
  1998-12-30  0:00   ` dennison
@ 1998-12-30  0:00     ` Tucker Taft
  1998-12-30  0:00       ` dennison
  1998-12-30  0:00       ` Robert I. Eachus
  0 siblings, 2 replies; 35+ messages in thread
From: Tucker Taft @ 1998-12-30  0:00 UTC (permalink / raw)


It seems clear that the stream attributes do not directly support the 
logging from multiple tasks, with interleaving occurring only
between "top-level" objects, as desired by this application.
Furthermore, they don't support reading without waiting.

However, it should be simple enough to build a generic package
which provides the desired functionality.

Each current "top-level" use of a stream attribute in the application
would be changed to be a call on a "read/write" or "input/output" routine of an 
appropriate instance of this generic package.  Such a routine would 
acquire a lock on the stream, invoke the corresponding stream attribute,
and release the lock.  

Furthermore, to support non-blocking read, you would need to add some 
kind of marker into the stream itself, I suspect, to be placed between 
"top-level" objects in the stream.  Then, when you call the non-blocking
"read" or "input" routine of the instance of this generic package,
it would call a routine of the underlying stream which would indicate
whether there is an "entire" top-level object already buffered up.
If not, the non-blocking read/input routine of the generic would
return a "not available" indicator.  If there is an entire top-level
object buffered up, the read/input routine would use the corresponding
stream attribute to read the data from the stream, confident that it
wouldn't block or get an end-of-file indication during the read.

--
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Re: Streams and Concurrency
  1998-12-30  0:00     ` Tucker Taft
@ 1998-12-30  0:00       ` dennison
  1998-12-31  0:00         ` robert_dewar
  1998-12-30  0:00       ` Robert I. Eachus
  1 sibling, 1 reply; 35+ messages in thread
From: dennison @ 1998-12-30  0:00 UTC (permalink / raw)


In article <F4sFr8.HHG.0.-s@inmet.camb.inmet.com>,
  stt@houdini.camb.inmet.com (Tucker Taft) wrote:
> It seems clear that the stream attributes do not directly support the
> logging from multiple tasks, with interleaving occurring only
> between "top-level" objects, as desired by this application.
> Furthermore, they don't support reading without waiting.
>
> However, it should be simple enough to build a generic package
> which provides the desired functionality.
>
> Each current "top-level" use of a stream attribute in the application
> would be changed to be a call on a "read/write" or "input/output" routine of
an
> appropriate instance of this generic package.  Such a routine would
> acquire a lock on the stream, invoke the corresponding stream attribute,
> and release the lock.

Ahhh. Now that might do the trick. Thanks a lot! It hadn't occurred to me
that generics can call the attributes too. Of course if your clients would
prefer the attribute interface this is a problem. But I don't see that being
too much of an issue.

> Furthermore, to support non-blocking read, you would need to add some
> kind of marker into the stream itself, I suspect, to be placed between
> "top-level" objects in the stream.  Then, when you call the non-blocking
> "read" or "input" routine of the instance of this generic package,

Yes, exactly. The problem is there's no way for the reader to know where
"between" is without first trying to read the entire object. Even within the
same data structure, the size could change depending on the value of a tag or
variant (or some other user-defined critera). The only way I could see to do
it is to have the writer put the length of the object in the stream *at the
front* of the object *after* the object is written. Doing this requires some
kind of direct access into the stream, and a way of blocking reads until the
whole object is written. Otherwise the reader could read that size data out
of the stream before the writer has a chance to fill it in.

My problem with doing the above was that it also requires the whole-object
locking of the stream (which you  have just explained one way to handle).

--
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] 35+ messages in thread

* Re: Streams and Concurrency
  1998-12-30  0:00   ` James S. Rogers
@ 1998-12-30  0:00     ` dennison
  1998-12-30  0:00       ` James S. Rogers
  1999-01-04  0:00       ` Robert I. Eachus
  1998-12-31  0:00     ` Jean-Pierre Rosen
  1 sibling, 2 replies; 35+ messages in thread
From: dennison @ 1998-12-30  0:00 UTC (permalink / raw)


In article <76dn7b$a35@bgtnsc03.worldnet.att.net>,
  "James S. Rogers" <jimmaureenrogers@worldnet.att.net> wrote:
> Following is a modest example of what I mean about
> encapsulating a stream in a protected object.
>
> I believe this solution solves the interleaving problem.  The read and
> write operations will be atomic.  The write operation will not complete
> until all 'write operations for the tagged type complete.  The key is
> that the task calling the protected write and read operations is
> ignorant of the use of a stream.  No stream operations occur outside
> the protection of the protected type.

I see. You (probably Robert too) were talking about wrapping the client's
'Read and 'Write calls themselves. So what you have here is a multi-taksing
logging package, rather than a multitasking stream. I was thinking about a
pure stream implementation. There appears to be no way to write the stream
itself to handle this. Perhaps that's not as bad as I first thought it was...

But this solution only works for objects that are part of the same class
hiearchy. That's too restrictive. I'd want to be able to use any type. It
sounds like Tuck's generic suggestion is the way to go.

--
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] 35+ messages in thread

* Re: Streams and Concurrency
  1998-12-30  0:00     ` dennison
@ 1998-12-30  0:00       ` James S. Rogers
  1999-01-04  0:00       ` Robert I. Eachus
  1 sibling, 0 replies; 35+ messages in thread
From: James S. Rogers @ 1998-12-30  0:00 UTC (permalink / raw)


dennison@telepath.com wrote in message <76e4rg$bsr$1@nnrp1.dejanews.com>...
>I see. You (probably Robert too) were talking about wrapping the client's
>'Read and 'Write calls themselves. So what you have here is a multi-taksing
>logging package, rather than a multitasking stream. I was thinking about a
>pure stream implementation. There appears to be no way to write the stream
>itself to handle this. Perhaps that's not as bad as I first thought it
was...
>
>But this solution only works for objects that are part of the same class
>hiearchy. That's too restrictive. I'd want to be able to use any type. It
>sounds like Tuck's generic suggestion is the way to go.


Yes, that is a distinct restriction.  On the other hand, if you adopted
a programming style from another language, such as Java, you could
have all your data types inherit from an abstract null tagged record.
The result would be some more overhead, but a very generally
useful approach to using streams with multiple tasks.  It would also
simplify the problem of reading and understanding the log file
contents.  The abstract base type could have a Print or Display
procedure which must be implemented for each type in the
hierarchy. Displaying the contents of the file would then rely on the
dispatching mechanism of tagged types.

Jim Rogers
Colorado Springs, Colorado USA






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

* Re: Streams and Concurrency
  1998-12-30  0:00 ` dennison
@ 1998-12-30  0:00   ` Robert I. Eachus
  1999-01-11  0:00   ` Bulk synchronous model for IO (was Re: Streams and Concurrency) Kevin Rigotti
  1 sibling, 0 replies; 35+ messages in thread
From: Robert I. Eachus @ 1998-12-30  0:00 UTC (permalink / raw)


In article <76dgdl$qle$1@nnrp1.dejanews.com> dennison@telepath.com writes:

 > That's the first thing I thought of too. This solution protects the
 > stream itself from corruption just fine. The problem is that it
 > provides absolutely no protection for the *data* in the stream. If
 > I do a 'Write of a record, that gets translated into *several*
 > "Write" calls to the stream, not just one. There's nothing stopping
 > another task from making a call to the stream's Write subprogram in
 > the middle of my record's 'Write. There's nothing stopping the
 > stream service task from calling the stream's Read procedure in the
 > middle of my 'Write either...

    This is wrong.  The encapsulation as illustrated by Jim Rogers
does it right.  The protected object doesn't wrap every call to 'Read
or 'Write, just the highest level calls.  Even if one of those calls
causes many lower level calls all happen inside a single call to the
protected object.

 > Making the stream a proteced object does nothing for me here.
    
    This is trying to solve the wrong problem.  Putting calls to the
protected action inside 'Read or 'Write can't work right.  You have to
have a single protected object which encapsulates the particular
stream.  If you need to read and write different types of values to
the same stream, you either have to derive them all from a single
tagged type, or have several sets of read and write entries to the
protected type, one set for each type of object.
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: Streams and Concurrency
  1998-12-30  0:00     ` Tucker Taft
  1998-12-30  0:00       ` dennison
@ 1998-12-30  0:00       ` Robert I. Eachus
  1998-12-30  0:00         ` Tucker Taft
  1998-12-31  0:00         ` dennison
  1 sibling, 2 replies; 35+ messages in thread
From: Robert I. Eachus @ 1998-12-30  0:00 UTC (permalink / raw)


In article <F4sFr8.HHG.0.-s@inmet.camb.inmet.com> stt@houdini.camb.inmet.com (Tucker Taft) writes:

 > Furthermore, to support non-blocking read, you would need to add some 
 > kind of marker into the stream itself, I suspect, to be placed between 
 > "top-level" objects in the stream.  Then, when you call the non-blocking
 > "read" or "input" routine of the instance of this generic package,
 > it would call a routine of the underlying stream which would indicate
 > whether there is an "entire" top-level object already buffered up.
 > If not, the non-blocking read/input routine of the generic would
 > return a "not available" indicator.  If there is an entire top-level
 > object buffered up, the read/input routine would use the corresponding
 > stream attribute to read the data from the stream, confident that it
 > wouldn't block or get an end-of-file indication during the read.

    Since the non-blocking read would have to do read ahead to find
the marker, the marker doesn't really add anything.  So you really
only need two sets of entries, one which does blocking read and
writes, and one set which is non-blocking.  HOWEVER, the routines
underlying the Read operations for interprocessor communication and
I/O streams will have to be defined in terms of Stream_Elements,
because you will have to not only do read ahead, but you will have to
save the read ahead material in another (in memory) stream.

    Note that this is an somewhat special pattern.  It is only of
interest in the presence of tasking and either multiple processors or
the like.  And while it can easily be written in portable Ada 95, it
is one where low-level implementation support can significantly
improve performance.
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: Streams and Concurrency
  1998-12-30  0:00       ` Robert I. Eachus
@ 1998-12-30  0:00         ` Tucker Taft
  1998-12-31  0:00         ` dennison
  1 sibling, 0 replies; 35+ messages in thread
From: Tucker Taft @ 1998-12-30  0:00 UTC (permalink / raw)


Robert I. Eachus (eachus@spectre.mitre.org) wrote:
: In article <F4sFr8.HHG.0.-s@inmet.camb.inmet.com> stt@houdini.camb.inmet.com (Tucker Taft) writes:

:  > Furthermore, to support non-blocking read, you would need to add some 
:  > kind of marker into the stream itself, I suspect, to be placed between 
:  > "top-level" objects in the stream.  Then, when you call the non-blocking
:  > "read" or "input" routine of the instance of this generic package,
:  > it would call a routine of the underlying stream which would indicate
:  > whether there is an "entire" top-level object already buffered up.
:  > If not, the non-blocking read/input routine of the generic would
:  > return a "not available" indicator.  If there is an entire top-level
:  > object buffered up, the read/input routine would use the corresponding
:  > stream attribute to read the data from the stream, confident that it
:  > wouldn't block or get an end-of-file indication during the read.

:     Since the non-blocking read would have to do read ahead to find
: the marker, the marker doesn't really add anything.  So you really
: only need two sets of entries, one which does blocking read and
: writes, and one set which is non-blocking.  

Perhaps I need to explain more.  There are *three* kinds of "read"s in
this picture:

   1) A "read" routine that is part of the generic package.
      This is the non-blocking one.  It reads "top-level" objects
      only.

   2) A "read" attribute of the (formal) type (plus all of the
       "read" attributes of the subcomponent types).

   3) The (dispatching) read procedure of the stream type.
      This reads stream element arrays.

A single call on (1) can result will result in a call of the
Read attribute (2), which will then result, at least implicitly,
in calls on the Read attributes of the subcomponents.  Ultimately,
one or more calls on (3) will occur.

To support non-blocking (1), the stream type will need to be 
augmented with the notion of a marker of some sort to delineate 
"top-level" objects, and a procedure (let's call it 
"Lock_If_OK_To_Read") which can check whether an entire top-level 
object has been read in, by seeing whether an end-object marker is in 
the buffer, and if so, lock the stream object (all in a non-blocking 
fashion) and return an indication of success.  

If this "Lock_If_OK_To_Read" indicates success, then the non-blocking
read (1) routine will turn around and call the read (2) attribute,
which will in turn result in one or more calls to the stream read (3) 
routine.

It is presumably possible for the lock-if-OK-to-read routine
to do non-blocking read-ahead, since it "knows" what kind of
stream device it is dealing with.  However, the read (2) attribute
cannot do non-blocking read-ahead, since it knows nothing about
the underlying stream type.  Furthermore, the expectation is that
the system-provided read attribute(s) is (are) being used.
Hence, before read (1) invokes read (2), it must use the
lock-if-OK-to-read routine.  The generic package routines would 
require a stream of a type that supports this additional procedure.

: ...
: 					Robert I. Eachus

--
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Streams and Concurrency
@ 1998-12-30  0:00 James S. Rogers
  1998-12-29  0:00 ` David Botton
  1998-12-30  0:00 ` dennison
  0 siblings, 2 replies; 35+ messages in thread
From: James S. Rogers @ 1998-12-30  0:00 UTC (permalink / raw)


A question was recently raised about task safe use of streams.
A stream is just as safe in a concurrent design as any other shared
resource.  That is, unless it is properly protected, it is not at all safe.
The same may be said of shared memory, or shared files.

There are two classical solutions to this problem.  The first is to
elminate the shared resource, and have a single, unshared resource
for each task.  The second is to protect the shared resource by having
only one task at a time access the resource.

Classical database engines control concurrent access to the
database by forcing all tasks to access the database through a
single database engine.  The same sort of thing can be achieved
in Ada in a couple of ways.  One way is to have all tasks send
messages to a single controlling task through a rendezvous.  This
would be the typical Ada 83 approach.  The more modern, and
more efficient approach in Ada 95 is to have encapsulate the stream
in a protected object.  All access will be correctly and effectively
controlled by the protected object mechanism.

When you use a protected object the "read" and "write" procedures
or entries must have a parameter of a class-wide type.  The
class-wide type parameter will allow the protected object to
read and write a wide range of otherwise heterogeneous data items
to and from the stream.  The stream may simply be an instance of
Ada.Streams.Stream_Io, or it may be a custom-made stream of
your own choosing.  The implementation will be irrelevant to the
tasks accessing the protected object.  It will also be irrelevant to the
protected object itself.

Jim Rogers
Colorado Springs, Colorado USA






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

* Re: Streams and Concurrency
  1998-12-30  0:00       ` dennison
@ 1998-12-31  0:00         ` robert_dewar
  0 siblings, 0 replies; 35+ messages in thread
From: robert_dewar @ 1998-12-31  0:00 UTC (permalink / raw)


Well I wrote my previous message before reading all the
followups, but I see they basically all agree with what
I suggested, namely that it makes more sense to create
the logging abstraction at a higher level.

Clearly there is no conceivable way for the implementation
of the streams themselves to provide automatic locking, so
the thought that they should seems fundamentally flawed.
The stream implementation *could* provide the primitives
so that attribute implementations could easily provide the
necessary locking, but I still think it makes sense to
abstract at a higher level.


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




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

* Re: Streams and Concurrency
  1998-12-30  0:00   ` James S. Rogers
  1998-12-30  0:00     ` dennison
@ 1998-12-31  0:00     ` Jean-Pierre Rosen
  1998-12-31  0:00       ` dewar
  1998-12-31  0:00       ` dewar
  1 sibling, 2 replies; 35+ messages in thread
From: Jean-Pierre Rosen @ 1998-12-31  0:00 UTC (permalink / raw)



James S. Rogers a �crit dans le message
<76dn7b$a35@bgtnsc03.worldnet.att.net>...
>Following is a modest example of what I mean about
>encapsulating a stream in a protected object.
>[snip]

Unfortunately, all IO operations are potentially blocking, and
therefore not allowed from within a protected operation.
To get the effect of mutual exclusion for procedures requiring
potentially blocking operations, have a look at package Protection
available from Adalog's components page
(http://perso.wanadoo.fr/adalog/compo2.htm)
---------------------------------------------------------
           J-P. Rosen (Rosen.Adalog@wanadoo.fr)
Visit Adalog's web site at http://perso.wanadoo.fr/adalog






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

* Re: Streams and Concurrency
  1998-12-30  0:00       ` Robert I. Eachus
  1998-12-30  0:00         ` Tucker Taft
@ 1998-12-31  0:00         ` dennison
  1998-12-31  0:00           ` robert_dewar
  1999-01-04  0:00           ` Robert I. Eachus
  1 sibling, 2 replies; 35+ messages in thread
From: dennison @ 1998-12-31  0:00 UTC (permalink / raw)


In article <EACHUS.98Dec30172549@spectre.mitre.org>,
  eachus@spectre.mitre.org (Robert I. Eachus) wrote:
> In article <F4sFr8.HHG.0.-s@inmet.camb.inmet.com> stt@houdini.camb.inmet.com
(Tucker Taft) writes:
>
>  > Furthermore, to support non-blocking read, you would need to add some
>  > kind of marker into the stream itself, I suspect, to be placed between
>  > "top-level" objects in the stream.  Then, when you call the non-blocking

>     Since the non-blocking read would have to do read ahead to find
> the marker, the marker doesn't really add anything.  So you really
> only need two sets of entries, one which does blocking read and
> writes, and one set which is non-blocking.  HOWEVER, the routines
> underlying the Read operations for interprocessor communication and
> I/O streams will have to be defined in terms of Stream_Elements,
> because you will have to not only do read ahead, but you will have to
> save the read ahead material in another (in memory) stream.

Ahhh. I had thought of that approach. I discarded it because I'm talking
real-time processes here. I don't have time to go copying large chuncks of
data around in the context of the real-time process. It does solve the
problem of handling objects w/ limited private fields, though.

>     Note that this is an somewhat special pattern.  It is only of
> interest in the presence of tasking and either multiple processors or
> the like.  And while it can easily be written in portable Ada 95, it
> is one where low-level implementation support can significantly
> improve performance.

"Special" perhaps, but not all that odd. It can occur in *any* tasking
program. In my 10 years of Ada use I've only worked on two programs that had
no tasks. It doesn't take a multiprocessor to cause a task switch in the
middle of a non-blocking operation. If you have tasks with different
priorites it can happen. If your scheduling policy supports any kind of time
slicing it can happen. Plus if the stream's Write procedure performs any I/O,
its possible that a 'Write itself is a blocking operation.


--
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] 35+ messages in thread

* Re: Streams and Concurrency
  1998-12-31  0:00     ` Jean-Pierre Rosen
  1998-12-31  0:00       ` dewar
@ 1998-12-31  0:00       ` dewar
  1998-12-31  0:00         ` Ada-G, was " Tom Moran
  1999-01-08  0:00         ` Mats Weber
  1 sibling, 2 replies; 35+ messages in thread
From: dewar @ 1998-12-31  0:00 UTC (permalink / raw)


In article <76fe92$46c$1@platane.wanadoo.fr>,
  "Jean-Pierre Rosen" <rosen.adalog@wanadoo.fr> wrote:
> Unfortunately, all IO operations are potentially
> blocking, and therefore not allowed from within a
> protected operation. To get the effect of mutual
> exclusion for procedures requiring potentially blocking
> operations, have a look at package Protection
> available from Adalog's components page
> (http://perso.wanadoo.fr/adalog/compo2.htm)


To me the abstraction violation that comes from the
restriction on blocking operations in protected objects
is an intolerable concession to one particular low level
model of implementation, which in fact as far as I know
virtually no Ada 95 compiler uses. I think that this
optimization should have been achieved with a restrictions
pragma

   pragma Restrictions (No_Blocking_Operations, type-name);

or some such,

In any case, GNAT guarantees that blocking operations CAN
be done within protected objects, of course you may get
deadlock if you do obviously bad things, but certainly
doing IO within a protected object is not such a bad thing,
and this will work fine. We have many customers who depend
on this guarantee.

Yes, yes, of course this is potentially non-portable, but
it makes protected objects enormously more useful. Remember
that there are two advantages of protected objects:

1) possibility of more efficient implementation (I say
possibility here because in fact there are many
complications which result in less efficiency than you
might have hoped for in the general case, and in any
case some cases of agent tasks can be optimized in a
corresponding efficient manner.

2) preferable abstraction to a task in some situations

For my taste 2) is much more important than 1), and the
restriction on blocking operations badly damages the use
of 2).

We have had more than one user who was plain incredulous
on being informed of this restriction, and indeed it was
in talking with one of these users that we decided to
guarantee that GNAT does NOT have this restriction.

If we ever find a real need to implement this restriction,
for efficiency purposes or for any other purpose, we can
add a restrictions identifier.

By the way, another way around this is to do the actual
IO with an interface to C. There is nothing in the RM that
says that a C routine doing I/O is potentially blocking in
the formal sense in the RM (remember that the notion of
potentially blocking is not isomorphic to actual blocking,
there can be blocking operations that are not potentially
blocking, and vice versa).

So an implementation is free to define whether interfacing
to C I/O routines is or is not blocking, and for sure a
compiler cannot in fact check, so this is likely to work
on most Ada 95 compilers.

Robert Dewar
Ada Core Technologies

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




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

* Re: Streams and Concurrency
  1998-12-31  0:00     ` Jean-Pierre Rosen
@ 1998-12-31  0:00       ` dewar
  1998-12-31  0:00         ` dennison
  1999-01-04  0:00         ` Jean-Pierre Rosen
  1998-12-31  0:00       ` dewar
  1 sibling, 2 replies; 35+ messages in thread
From: dewar @ 1998-12-31  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2393 bytes --]

In article <76fe92$46c$1@platane.wanadoo.fr>,
  "Jean-Pierre Rosen" <rosen.adalog@wanadoo.fr> wrote:
>
> James S. Rogers a �crit dans le message
> <76dn7b$a35@bgtnsc03.worldnet.att.net>...
> >Following is a modest example of what I mean about
> >encapsulating a stream in a protected object.
> >[snip]
>
> Unfortunately, all IO operations are potentially
> blocking, and therefore not allowed from within a
> protected operation.
> To get the effect of mutual exclusion for procedures
> requiring potentially blocking operations, have a look at
> package Protection available from Adalog's components
> page (http://perso.wanadoo.fr/adalog/compo2.htm)

By the way, JPR here seems to be making the mistake of
assuming that stream = stream_io, a common confusion. The
original question here related to a particular
implementation of streams that you have not seen, and you
do not know if it does any potentially blocking operations.

Yes, it had to do with file logging, but that does not
mean that it does I/O. For example, a perfectly reasonable
organization is to have a stream implementation that fills
a buffer that is part of a protected type, and a consumer
task that empties the buffer and does I/O on it. This
organization violates absolutely nothing with regards to
doing potentially blocking operations.

In Ada 95, if you are following the official design, every
single abstraction must be labeled in its spec as to
whether it does or does not do PB operations, so that you
know if it can be called from a protected operation. Yes,
that's frightful from an abstractrion point of view, but
that's the way the language is, due to the excessive
influence of one particular efficiency-obsessed specific
design for possible implementation of protected types.

A given implementation of streams (for logging or any
other purpose) may or may not do PB operations, and that
must be part of its spec.

As I commented before, we have essentially extended the
language for GNAT by defining that the implementation
dependent behavior for PB operations, i.e. the behavior
of the compiler for this bounded error, is NOT to reject
the PB operation, but to go ahead and do it, with the
expected consequences.

Robert Dewar
Ada Core Technologies

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




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

* Re: Streams and Concurrency
  1998-12-31  0:00         ` dennison
@ 1998-12-31  0:00           ` robert_dewar
  1998-12-31  0:00             ` dennison
  1999-01-04  0:00           ` Robert I. Eachus
  1 sibling, 1 reply; 35+ messages in thread
From: robert_dewar @ 1998-12-31  0:00 UTC (permalink / raw)


In article <76g0nu$nsq$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> "Special" perhaps, but not all that odd. It can occur in
> *any* tasking program. In my 10 years of Ada use I've
> only worked on two programs that had no tasks. It doesn't
> take a multiprocessor to cause a task switch in the
> middle of a non-blocking operation. If you have tasks
> with different priorites it can happen. If your
> scheduling policy supports any kind of time slicing it
> can happen. Plus if the stream's Write procedure performs
> any I/O, its possible that a 'Write itself is a blocking
> operation.

Note that of course if you have protected objects, it is
not generally possible for a higher priority task to
interrupt in a problematic way, that is what ceiling
priorities are all about. And of course with
FIFO_Within_Priorities, time slicing is forbidden for
very good reasons!

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




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

* Re: Streams and Concurrency
  1998-12-31  0:00       ` dewar
@ 1998-12-31  0:00         ` dennison
  1999-01-04  0:00         ` Jean-Pierre Rosen
  1 sibling, 0 replies; 35+ messages in thread
From: dennison @ 1998-12-31  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1412 bytes --]

In article <76g9ds$ura$1@nnrp1.dejanews.com>,
  dewar@gnat.com wrote:
> In article <76fe92$46c$1@platane.wanadoo.fr>,
>   "Jean-Pierre Rosen" <rosen.adalog@wanadoo.fr> wrote:
> >
> > James S. Rogers a �crit dans le message
> > <76dn7b$a35@bgtnsc03.worldnet.att.net>...
> > >Following is a modest example of what I mean about
> > >encapsulating a stream in a protected object.
> > >[snip]
> >
> > Unfortunately, all IO operations are potentially
> > blocking, and therefore not allowed from within a
> > protected operation.
> > To get the effect of mutual exclusion for procedures
> > requiring potentially blocking operations, have a look at
> > package Protection available from Adalog's components
> > page (http://perso.wanadoo.fr/adalog/compo2.htm)
>
> By the way, JPR here seems to be making the mistake of
> assuming that stream = stream_io, a common confusion. The
> original question here related to a particular
> implementation of streams that you have not seen, and you
> do not know if it does any potentially blocking operations.

Quite true. What started all this is that I was trying to use streams as a
typless buffer between two tasks. One of these tasks is Real-Time, and *can't*
wait for another task or I/O (thus the buffer).

--
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] 35+ messages in thread

* Re: Streams and Concurrency
  1998-12-31  0:00           ` robert_dewar
@ 1998-12-31  0:00             ` dennison
  1999-01-01  0:00               ` robert_dewar
  0 siblings, 1 reply; 35+ messages in thread
From: dennison @ 1998-12-31  0:00 UTC (permalink / raw)


In article <76g9jh$us1$1@nnrp1.dejanews.com>,
  robert_dewar@my-dejanews.com wrote:
> In article <76g0nu$nsq$1@nnrp1.dejanews.com>,
>   dennison@telepath.com wrote:
> > "Special" perhaps, but not all that odd. It can occur in
> > *any* tasking program. In my 10 years of Ada use I've
> > only worked on two programs that had no tasks. It doesn't
> > take a multiprocessor to cause a task switch in the
> > middle of a non-blocking operation. If you have tasks
> > with different priorites it can happen. If your
> > scheduling policy supports any kind of time slicing it
> > can happen. Plus if the stream's Write procedure performs
> > any I/O, its possible that a 'Write itself is a blocking
> > operation.
>
> Note that of course if you have protected objects, it is
> not generally possible for a higher priority task to
> interrupt in a problematic way, that is what ceiling
> priorities are all about. And of course with
> FIFO_Within_Priorities, time slicing is forbidden for
> very good reasons!

True. Of course if we move our system to a dual Pentium architecture, that
won't help. Folks here may want to dismiss that as an odball setup, but your
days of being able to do that are numbered.

--
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] 35+ messages in thread

* Ada-G, was Re: Streams and Concurrency
  1998-12-31  0:00       ` dewar
@ 1998-12-31  0:00         ` Tom Moran
  1999-01-01  0:00           ` dewar
  1999-01-01  0:00           ` Brian Rogoff
  1999-01-08  0:00         ` Mats Weber
  1 sibling, 2 replies; 35+ messages in thread
From: Tom Moran @ 1998-12-31  0:00 UTC (permalink / raw)


>In any case, GNAT guarantees that blocking operations CAN
>be done within protected objects, 
>...
>we decided to
>guarantee that GNAT does NOT have this restriction
"Many projects used their own languages or special variations of
existing languages.  This virtually locked the (DOD) into contracting
the original developers of a system for all maintenance work arising
during the life of that system."  Cohen, "Ada as a Second Language",
1986, p. 2 on the history of Ada.
   As a person who spends a fair amount of time testing portability of
new code, and working around the bugs and limitations of 5 different
"Ada 95" compilers, I'd suggest that anyone thinking of locking
themselves into a vendor-specific "special variations of existing
languages" look very carefully before they leap.




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

* Re: Streams and Concurrency
  1998-12-31  0:00             ` dennison
@ 1999-01-01  0:00               ` robert_dewar
  0 siblings, 0 replies; 35+ messages in thread
From: robert_dewar @ 1999-01-01  0:00 UTC (permalink / raw)


In article <76gecs$2sq$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> True. Of course if we move our system to a dual Pentium
> architecture, that won't help. Folks here may want to
> dismiss that as an odball setup, but your
> days of being able to do that are numbered.


This is a misunderstanding. Time slicing is STILL not
allowed in a multi-processor environment, and the ceiling
priority protocol guarantees that a protected operation
cannot be interrupted by another higher priority task
attempting to enter the protected region, even in the
multi-processing case.

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




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

* Re: Ada-G, was Re: Streams and Concurrency
  1999-01-01  0:00           ` dewar
@ 1999-01-01  0:00             ` Larry Kilgallen
  0 siblings, 0 replies; 35+ messages in thread
From: Larry Kilgallen @ 1999-01-01  0:00 UTC (permalink / raw)


In article <76hqhk$56h$1@nnrp1.dejanews.com>, dewar@gnat.com writes:

> However, many real world projects are in fact pretty much
> committed to a single compiler, and even those that don't
> think they are often are. Indeed, consider this case, the
> user in question might never have even realized they were
> doing something that was not legitimate if we had not
> pointed it out. A lot of code depends on erroneous or
> implementation dependent constructs without realizing it.

DEC Ada for VMS, at least on Alpha, produces a "non-portability"
summary at the end of the listing. I don't know if it gets down
to this level of detail, but that sounds like the right approach
for indicating dependence on a particular implementation.  Of
course this might be viewed by a compiler vendor as having some
negative business impact as well as some positive business impact,
and that probably moves it down a few notches on the priority
scale.

Larry Kilgallen




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

* Re: Ada-G, was Re: Streams and Concurrency
  1998-12-31  0:00         ` Ada-G, was " Tom Moran
  1999-01-01  0:00           ` dewar
@ 1999-01-01  0:00           ` Brian Rogoff
  1999-01-04  0:00             ` Robert I. Eachus
  1 sibling, 1 reply; 35+ messages in thread
From: Brian Rogoff @ 1999-01-01  0:00 UTC (permalink / raw)


On Thu, 31 Dec 1998, Tom Moran wrote:
>    As a person who spends a fair amount of time testing portability of
> new code, and working around the bugs and limitations of 5 different
> "Ada 95" compilers, I'd suggest that anyone thinking of locking
> themselves into a vendor-specific "special variations of existing
> languages" look very carefully before they leap.

I agree completely, but the message I get from this interesting discussion
is that vendors should agree on Ada fixes (based on customer input amongst 
other things) a bit faster than once a decade.

-- Brian






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

* Re: Ada-G, was Re: Streams and Concurrency
  1998-12-31  0:00         ` Ada-G, was " Tom Moran
@ 1999-01-01  0:00           ` dewar
  1999-01-01  0:00             ` Larry Kilgallen
  1999-01-01  0:00           ` Brian Rogoff
  1 sibling, 1 reply; 35+ messages in thread
From: dewar @ 1999-01-01  0:00 UTC (permalink / raw)


In article <368bdf3c.3097724@news.pacbell.net>,
  tmoran@bix.com (Tom Moran) wrote:
> As a person who spends a fair amount of time testing
> portability of new code, and working around the bugs and
> limitations of 5 different "Ada 95" compilers, I'd
> suggest that anyone thinking of locking themselves into a
> vendor-specific "special variations of existing
> languages" look very carefully before they leap.


That of course is good advice. It is worth emphasizing that
the particular case here was a matter of a large customer
insisting that

(a) they absolutely needed this feature
(b) all versions of GNAT seemed to work the way they
    expected.
(c) they would not be able to use any version of GNAT that
    did not work that way.

Most certainly, they realized that they were committing
themselves to compilers that worked this way, but they
took the position that any compiler not working this way
was broken and would not be acceptable for use.

Tom is in the business of writing portable library code
whose value depends on its being able to run with many
different Ada compilers, and there of course, portability
is paramount.

However, many real world projects are in fact pretty much
committed to a single compiler, and even those that don't
think they are often are. Indeed, consider this case, the
user in question might never have even realized they were
doing something that was not legitimate if we had not
pointed it out. A lot of code depends on erroneous or
implementation dependent constructs without realizing it.

Actually one of the most significant cases of dependence
on particular compilers arises with the use of specialized
library packages. Certainly it is a good thing for
compilers to provide useful stuff, but it can be a trap if
portability turns out to be important. Note that this is
particularly the case if the specs of the routines in
question are protected by copyright.

Robert Dewar
Ada Core Technologies

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




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

* Re: Streams and Concurrency
  1998-12-31  0:00       ` dewar
  1998-12-31  0:00         ` dennison
@ 1999-01-04  0:00         ` Jean-Pierre Rosen
  1999-01-04  0:00           ` robert_dewar
  1 sibling, 1 reply; 35+ messages in thread
From: Jean-Pierre Rosen @ 1999-01-04  0:00 UTC (permalink / raw)


dewar@gnat.com a �crit dans le message
<76g9ds$ura$1@nnrp1.dejanews.com>...
>In article <76fe92$46c$1@platane.wanadoo.fr>,
>  "Jean-Pierre Rosen" <rosen.adalog@wanadoo.fr> wrote:
>> Unfortunately, all IO operations are potentially
>> blocking, and therefore not allowed from within a
>> protected operation.
>> To get the effect of mutual exclusion for procedures
>> requiring potentially blocking operations, have a look at
>> package Protection available from Adalog's components
>> page (http://perso.wanadoo.fr/adalog/compo2.htm)
>
>By the way, JPR here seems to be making the mistake of
>assuming that stream = stream_io, a common confusion. The
>original question here related to a particular
>implementation of streams that you have not seen, and you
>do not know if it does any potentially blocking operations.
>
Of course not, but that particular exemple used Text_Streams and I
took this opportunity to remind people of this often overlooked
problem.
Why, if it works on most compilers ? Because I hate concealed design
decisions. Choosing between portability and efficiency (or in this
case, ease of programming) is a trade-off, and it is perfectly
acceptable to disregard portability as long as it is a concious design
decision. But as you noticed, often people make this choice without
being aware of it, and *this* is (IMHO) very bad.
---------------------------------------------------------
           J-P. Rosen (Rosen.Adalog@wanadoo.fr)
Visit Adalog's web site at http://perso.wanadoo.fr/adalog






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

* Re: Streams and Concurrency
  1999-01-04  0:00         ` Jean-Pierre Rosen
@ 1999-01-04  0:00           ` robert_dewar
  0 siblings, 0 replies; 35+ messages in thread
From: robert_dewar @ 1999-01-04  0:00 UTC (permalink / raw)


In article <76qb23$ba3$1@platane.wanadoo.fr>,
  "Jean-Pierre Rosen" <rosen.adalog@wanadoo.fr> wrote:
> Of course not, but that particular exemple used
> Text_Streams and I took this opportunity to remind people
> of this often overlooked problem. Why, if it works on
> most compilers ? Because I hate concealed design
> decisions. Choosing between portability and efficiency
> (or in this case, ease of programming) is a trade-off,
> and it is perfectly acceptable to disregard portability
> as long as it is a concious design decision. But as you
> noticed, often people make this choice without
> being aware of it, and *this* is (IMHO) very bad.

But of course when you call a foreign language routine of
any kind AT ALL, you are implementation dependent. This is
the only issue we are talking about here!

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




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

* Re: Streams and Concurrency
  1998-12-31  0:00         ` dennison
  1998-12-31  0:00           ` robert_dewar
@ 1999-01-04  0:00           ` Robert I. Eachus
  1 sibling, 0 replies; 35+ messages in thread
From: Robert I. Eachus @ 1999-01-04  0:00 UTC (permalink / raw)


In article <76g0nu$nsq$1@nnrp1.dejanews.com> dennison@telepath.com writes:

 > "Special" perhaps, but not all that odd. It can occur in *any* tasking
 > program. In my 10 years of Ada use I've only worked on two programs that had
 > no tasks.

   My use of special was referring to the fact that this pattern
requires either Unchecked_Conversion or its moral equivalent, but is
still completely portable!  You have to move the same data as both
records and as arrays of Storage_Elements, but the mapping between the
two does not affect the operation of the program. (At least as long as
it is reversible.)
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: Streams and Concurrency
  1998-12-30  0:00     ` dennison
  1998-12-30  0:00       ` James S. Rogers
@ 1999-01-04  0:00       ` Robert I. Eachus
  1 sibling, 0 replies; 35+ messages in thread
From: Robert I. Eachus @ 1999-01-04  0:00 UTC (permalink / raw)


In article <76e4rg$bsr$1@nnrp1.dejanews.com> dennison@telepath.com writes:

 > But this solution only works for objects that are part of the same class
 > hiearchy. That's too restrictive. I'd want to be able to use any type. It
 > sounds like Tuck's generic suggestion is the way to go.

   Wonderful opertunity for generic children. ;-)  Create a (generic)
package that encapsulates the stream and the locking mechanism.  This
package would then have a generic child package that you instantiate
once for each type you want to write to the stream.  (And now for the
really tricky part...)

   If you want to be able to read the mixed stream without knowing
what type of value appears next, you have to have a parent type in the
parent generic, or a parent access type, and a read operation declared
there which returns objects of the class rooted at this type.  You can
then use a fairly common Ada idiom (a declare block with a class-wide
object initialized by a function) to make the contents of the stream
available.

   The case where you know the structure of the stream, or as Tucker
suggested, have markers in the stream, is much easier to program.

      
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: Ada-G, was Re: Streams and Concurrency
  1999-01-01  0:00           ` Brian Rogoff
@ 1999-01-04  0:00             ` Robert I. Eachus
  1999-01-08  0:00               ` Mats Weber
  0 siblings, 1 reply; 35+ messages in thread
From: Robert I. Eachus @ 1999-01-04  0:00 UTC (permalink / raw)


In article <Pine.BSF.4.05.9901011003090.10526-100000@shell5.ba.best.com> Brian Rogoff <bpr@shell5.ba.best.com> writes:

 > I agree completely, but the message I get from this interesting discussion
 > is that vendors should agree on Ada fixes (based on customer input amongst 
 > other things) a bit faster than once a decade.

   They do, but the process is still slow and deliberate.  During the
(officially just over eleven years) between Ada 83 and Ada 95, there
were a half-dozen cases where the Ada Rapporteur Group issued Nonbinding
interpretations, one of them on raising Contstraint_Error instead of
Program_Error.  The goal of these NBIs was to allow implementors to
move in the direction that the new language revision would move
without forcing any particular schedule.  In cases where the language
was unclear but all compilers behaved consistantly, we enforced the de
facto standard with binding interpretations.

   The official process with Ada 95 may be somewhat different since we
intend to issue corrigenda consolidating the AIs, but the results
should be the same--a slow evolution in the definition of the
language.

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: Streams and Concurrency
  1998-12-31  0:00       ` dewar
  1998-12-31  0:00         ` Ada-G, was " Tom Moran
@ 1999-01-08  0:00         ` Mats Weber
  1999-01-08  0:00           ` Tucker Taft
  1 sibling, 1 reply; 35+ messages in thread
From: Mats Weber @ 1999-01-08  0:00 UTC (permalink / raw)


dewar@gnat.com wrote:

> In any case, GNAT guarantees that blocking operations CAN
> be done within protected objects, of course you may get
> deadlock if you do obviously bad things, but certainly
> doing IO within a protected object is not such a bad thing,
> and this will work fine. We have many customers who depend
> on this guarantee.

I agree totally.

> Yes, yes, of course this is potentially non-portable, but
> it makes protected objects enormously more useful. Remember
> that there are two advantages of protected objects:
> 
> 1) possibility of more efficient implementation (I say
> possibility here because in fact there are many
> complications which result in less efficiency than you
> might have hoped for in the general case, and in any
> case some cases of agent tasks can be optimized in a
> corresponding efficient manner.

Are you talking about what DEC Ada and Verdix call passive tasks ?

> 2) preferable abstraction to a task in some situations
> 
> For my taste 2) is much more important than 1), and the
> restriction on blocking operations badly damages the use
> of 2).

I also see other reasons:

3) In order to protect objects with potentially blocking operations (a
socket, a pipe, etc.), you must either use a semaphore implemented as a
protected object and call the semaphore _twice_, once for locking and
once for unlocking, or you must use a task. Thus the promised
performance gain with protected objects is lost.

4) It is another case where the standard enforces things that no
compiler can check, neither at compile time nor at run time. Ada 83 had
incorrect order dependences in this category, where it was allowed to
raise Program_Error if it found one. Fortunately, this was removed from
Ada 95 and I think the restriction on blocking protected operations
falls in the same category.




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

* Re: Ada-G, was Re: Streams and Concurrency
  1999-01-04  0:00             ` Robert I. Eachus
@ 1999-01-08  0:00               ` Mats Weber
  1999-01-08  0:00                 ` Robert I. Eachus
  0 siblings, 1 reply; 35+ messages in thread
From: Mats Weber @ 1999-01-08  0:00 UTC (permalink / raw)


"Robert I. Eachus" wrote:

>    They do, but the process is still slow and deliberate.  During the
> (officially just over eleven years) between Ada 83 and Ada 95, there
> were a half-dozen cases where the Ada Rapporteur Group issued Nonbinding
> interpretations, one of them on raising Contstraint_Error instead of
> Program_Error.
  ^^^^^^^^^^^^^
You mean Numeric_Error here, right ?




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

* Re: Streams and Concurrency
  1999-01-08  0:00         ` Mats Weber
@ 1999-01-08  0:00           ` Tucker Taft
  0 siblings, 0 replies; 35+ messages in thread
From: Tucker Taft @ 1999-01-08  0:00 UTC (permalink / raw)


Mats Weber (Mats.Weber@elca-matrix.ch) wrote:

.. [discussion of restriction against potentially-blocking operations
   in protected operations]
: ...
: 4) It is another case where the standard enforces things that no
: compiler can check, neither at compile time nor at run time. Ada 83 had
: incorrect order dependences in this category, where it was allowed to
: raise Program_Error if it found one. Fortunately, this was removed from
: Ada 95 and I think the restriction on blocking protected operations
: falls in the same category.

Checking for explicit use of entry calls or task activation "statically"
within the protected operation is not difficult.  Checking for
such uses outside the protected body is of course more difficult (though not
impossible if willing to do it at link-time).  Detecting incorrect order 
dependences, by contrast, involves solving the halting problem ;-).

The restriction against performing other *entry* calls (or activating
new tasks) while in a protected operation seems entirely appropriate, and 
I presume that GNAT does not support that.  I agree that things which
the programmer "knows" won't suspend the Ada task ("suspend" in the sense
of waiting indefinitely for some other Ada task of potentially lower 
priority to wake it up) are safe and generally portable to do, so in
this sense the standard was probably overly conservative.

--
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Re: Ada-G, was Re: Streams and Concurrency
  1999-01-08  0:00               ` Mats Weber
@ 1999-01-08  0:00                 ` Robert I. Eachus
  0 siblings, 0 replies; 35+ messages in thread
From: Robert I. Eachus @ 1999-01-08  0:00 UTC (permalink / raw)


In article <36962BBC.23B129F0@elca-matrix.ch> Mats Weber <Mats.Weber@elca-matrix.ch> writes:

 > >    They do, but the process is still slow and deliberate.  During the
 > > (officially just over eleven years) between Ada 83 and Ada 95, there
 > > were a half-dozen cases where the Ada Rapporteur Group issued Nonbinding
 > > interpretations, one of them on raising Contstraint_Error instead of
 > > Program_Error.
     ^^^^^^^^^^^^^
 >  You mean Numeric_Error here, right ?

   Oops!  You are right.  (And I mispelled Constraint_Error too.  I'll
have to take my fingers in for a 50,000 message checkup.)

   However...Note that in going from Ada 83 to Ada 95, several cases
where Constraint_Error or Program_Error error could be raised were
tightened up.  This is a good thing, but it may mean your code now
raises Program_Error where before you saw Constraint_Error.
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Bulk synchronous model for IO (was Re: Streams and Concurrency)
  1998-12-30  0:00 ` dennison
  1998-12-30  0:00   ` Robert I. Eachus
@ 1999-01-11  0:00   ` Kevin Rigotti
  1 sibling, 0 replies; 35+ messages in thread
From: Kevin Rigotti @ 1999-01-11  0:00 UTC (permalink / raw)


Interesting thread ...

In the more general case of lots of parallel activity requiring IO to happen
in a controlled way then it might be interesting to use Streams as the basis
for doing 'BSP'-like things in Ada, where IO is initially buffered locally
and only completed between tasks at the end of the next 'superstep'

The BSP home page has links to details of a C library (BSPlib) that provides
primitives for doing this, but it might be fun to see how the same thing
might be done in Ada.

Just a thought, maybe a nice little project for a student :-)

Kevin Rigotti
Senior Scientist, ATC Systems Group


begin 666 BSP Worldwide Home Page.url
M6TEN=&5R;F5T4VAO<G1C=71=#0I54DP]:'1T<#HO+W=W=RYB<W M=V]R;&1W
G:61E+F]R9R\-"DUO9&EF:65D/44P030P1C5".#$S1$)%,#$V0@T*
`
end





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

end of thread, other threads:[~1999-01-11  0:00 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-12-30  0:00 Streams and Concurrency James S. Rogers
1998-12-29  0:00 ` David Botton
1998-12-30  0:00   ` James S. Rogers
1998-12-30  0:00     ` dennison
1998-12-30  0:00       ` James S. Rogers
1999-01-04  0:00       ` Robert I. Eachus
1998-12-31  0:00     ` Jean-Pierre Rosen
1998-12-31  0:00       ` dewar
1998-12-31  0:00         ` dennison
1999-01-04  0:00         ` Jean-Pierre Rosen
1999-01-04  0:00           ` robert_dewar
1998-12-31  0:00       ` dewar
1998-12-31  0:00         ` Ada-G, was " Tom Moran
1999-01-01  0:00           ` dewar
1999-01-01  0:00             ` Larry Kilgallen
1999-01-01  0:00           ` Brian Rogoff
1999-01-04  0:00             ` Robert I. Eachus
1999-01-08  0:00               ` Mats Weber
1999-01-08  0:00                 ` Robert I. Eachus
1999-01-08  0:00         ` Mats Weber
1999-01-08  0:00           ` Tucker Taft
1998-12-30  0:00   ` dennison
1998-12-30  0:00     ` Tucker Taft
1998-12-30  0:00       ` dennison
1998-12-31  0:00         ` robert_dewar
1998-12-30  0:00       ` Robert I. Eachus
1998-12-30  0:00         ` Tucker Taft
1998-12-31  0:00         ` dennison
1998-12-31  0:00           ` robert_dewar
1998-12-31  0:00             ` dennison
1999-01-01  0:00               ` robert_dewar
1999-01-04  0:00           ` Robert I. Eachus
1998-12-30  0:00 ` dennison
1998-12-30  0:00   ` Robert I. Eachus
1999-01-11  0:00   ` Bulk synchronous model for IO (was Re: Streams and Concurrency) Kevin Rigotti

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