comp.lang.ada
 help / color / mirror / Atom feed
From: Brad Moore <brad.moore@shaw.ca>
Subject: Re: API design problem - buffer scatter I/O
Date: Mon, 24 Nov 2008 01:10:09 -0700
Date: 2008-11-24T01:10:09-07:00	[thread overview]
Message-ID: <CjtWk.14036$Dw1.11545@newsfe09.iad> (raw)
In-Reply-To: <wcczljrl39c.fsf@shell01.TheWorld.com>

Robert A Duff wrote:
> Maciej Sobczak <see.my.homepage@gmail.com> writes:
>> Still, in both of these solutions, there is a problem of scope - the
>> type of access value is defined by the library API (well, at the
>> library level), whereas user-provided buffers are likely to be defined
>> locally.
> 
> Right.  You have to use Local'Unchecked_Access, and take care to avoid
> dangling pointers.

I have been working on a set of general purpose buffers, and was
curious to see how I could incorporate a scatter buffer implementation
into my buffer framework. I ended up with a design that seems to satisfy 
the requirements stated in the original post. My experimentation led to 
some results that might be of interest, and I have a compiled test 
driver that reads and writes data to a scatter buffer.

1) The design I am using is an expansion of the idea discussed earlier 
in this thread. That is, a record type with a discriminant is used to
define the size of the array. In addition, the package is a generic
where the type of object to be stored in the buffer is passed in as a
generic formal parameter.

2) As part of the instantiation for a scatter buffer, I pass in the
array of buffers as a generic formal parameter. Passing in these
parameters has other benefits to my design, which I wont bother
trying to explain here.

generic

    type Scatterbuffer_Array_Type is
      array (Count_Type range <>) of access Buffer_Interface'Class;

    Scatter_Buffers : Scatterbuffer_Array_Type;

package Buffers.Scattered
    pragma Remote_Types;
...


3) Note that I am using anonymous access types in the generic formal
Scatterbuffer_Array_Type

I didn't have any issues with using anonymous access types. In my
main test procedure, I was able to use 'Access in a nested scope
without having to use 'Unchecked_Access. In fact, my implementation
requires anonymous access types, and I don't believe I could have
got this to work without using Ada 2005's anonymous access feature.
I actually tried, (after commenting out the pragma Remote_Types),
and using named access types, but the compiler wouldn't compile the code.
I suspect this is a compiler bug, but since I need the pragma 
Remote_Types, I didn't pursue that any further.

The need to use anonymous access types has more to do with the fact that 
I allow buffers to be accessed
remotely, but I need the buffers in the buffer list to be anonymous so 
that they are treated as local buffers, not remote ones.

The main test procedure looks like;

with Buffers.Simple_Bounded;
with Buffers.Simple_Unbounded;
with Buffers.Simple_Scattered;
with Buffers.Passive_Bounded;

procedure Main_Test is

    -- Create a root buffer framework for storing text (Character data)
    package My_Buffer is new Buffers
      (Element_Index_Type => Natural,
       Element_Type => Character,
       Element_Vector_Type => String);

    -- Instantiate some differing buffer types
    package My_Simple_Bounded_Buffer is new My_Buffer.Simple_Bounded;
    package My_Simple_Unbounded_Buffer is new My_Buffer.Simple_Unbounded;
    package My_Passive_Bounded_Buffer is new My_Buffer.Passive_Bounded;

   -- Declare buffers of different types and different sizes
   My_Bounded : aliased My_Simple_Bounded_Buffer.Buffer
      (Maximum_Capacity => 100);
   My_Unbounded : aliased My_Simple_Unbounded_Buffer.Buffer
      (Maximum_Capacity => 5000);
   My_Passive : aliased My_Passive_Bounded_Buffer
      (Maximum_Capacity => 33);

   -- Declare the type needed by Scatter Buffer
   type Scatterbuffer_Array
      is array (Ada.Containers.Count_Type range <>) of access
         My_Buffer.Buffer_Interface'Class;

    -- Declare the list of buffers to be used by the scatter buffer

    -- Note using the 'Access in a nested scope. Works fine.
    Scatterbuffers : constant Scatterbuffer_Array := Scatterbuffer_Array'
      (1 => My_Bounded'Access,
       2 => My_Unbounded'Access,
       3 => My_Passive'Access);  -- Synchronous Buffer based on Protected

    -- Instantiate the scatter buffer
    package My_Simple_Scatter_Buffer is new
      My_Buffer.Simple_Scattered
        (Scatterbuffer_List => Scatterbuffer_Array,
         Scatter_Buffers => Scatterbuffers);

    -- Declare the Scatter Buffer
    My_Scattered : My_Simple_Scatter_Buffer.Buffer
      (Maximum_Capacity => 5133);
begin
    -- Each write request typically gets written to a different buffer
    -- or can be split across buffers, if a targetted buffer does
    -- not have the available space
    My_Scattered.Write ("Hello World");

    -- Each read request reads from a separate buffer
    -- or can be split across buffers, if a buffer does not
    -- have the available data
    Put_Line ("Text Read=" & My_Scattered.Read (Maximum_Count => 5));
  -- Reads a string

end Main_Test;

The use of Ada 2005 interfaces is also helpful here.
Some of the buffers in the scatter list are synchronous buffer types,
based on a task or a protected type. Others are intended only for
non-synchronous use.

Scatter buffers can in fact appear in the list of buffers in another 
scatter buffer list.

If a scatter buffer is acting as a producer, then there can be separate 
consumers for each of the buffers in the buffer list.

Likewise, if a scatter buffer is acting as a consumer, then there can be 
separate producers for each of the buffers in the buffer list.

It is possible to have one scatter buffer instance as a producer, and 
another scatter buffer instance as a consumer, for the same list of buffers.

My framework also gives me synchronous scatter buffer forms where the
scatter buffer itself can be synchronized to allow multiple readers/writers.

I am thinking of releasing the source under some license similar to the 
GNAT license, but haven't sorted out the details of how to go about this 
yet.

- Brad

> 
>> This brings the old problem of having an access value of global type
>> pointing to local object (GNAT says: "non-local pointer cannot point
>> to local object").
>> Unrestricted_Access hides the issue,...
> 
> Don't use Unrestricted_Access here (which is not standard Ada).
> Use Unchecked_Access.  Yes, it's dangerous -- you need to ensure that
> Scatter_Input_Data doesn't save pointers to locals into globals,
> along with comments explaining what clients can do.
> There's no better solution.
> 
>> ... but I know from Rationale that
>> anonymous access types were supposed to solve some of that mess.
> 
> "Supposed to", maybe.  But they don't.  I suggest you stay away from
> them.  They are confusing, and don't help here.
> 
>> ...The
>> problem is that I cannot find any way to benefit from them.
> 
> Right.  Neither can I.
> [snipped discussion of failed attempts to use anonymous
> access types]
> 
> By the way, ARG is discussing some ideas for improving anonymous
> access types.  My own opinion is that this will not work out,
> but others do not agree with me.
> 
> - Bob



  reply	other threads:[~2008-11-24  8:10 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-22 16:05 API design problem - buffer scatter I/O Maciej Sobczak
2008-11-22 16:54 ` sjw
2008-11-22 19:43 ` george.priv
2008-11-22 22:16 ` Robert A Duff
2008-11-22 23:34   ` Maciej Sobczak
2008-11-23  0:01     ` Robert A Duff
2008-11-24  8:10       ` Brad Moore [this message]
2008-11-24  7:55   ` christoph.grein
2008-11-24 20:03     ` Robert A Duff
2008-11-25  5:59       ` christoph.grein
2008-11-25  8:34         ` Dmitry A. Kazakov
2008-11-25 14:25         ` Robert A Duff
2008-11-25 22:20       ` Randy Brukardt
2008-11-24 21:23     ` Robert A Duff
2008-11-22 23:01 ` Georg Bauhaus
2008-11-23  5:57 ` anon
2008-11-24 17:16 ` tmoran
2008-11-26  8:34   ` Maciej Sobczak
2008-11-26 20:39     ` sjw
replies disabled

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