* How to transfer Class-Wide object to a Task ?
@ 2019-10-14 19:41 William FRANCK
2019-10-14 19:55 ` Shark8
` (2 more replies)
0 siblings, 3 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-14 19:41 UTC (permalink / raw)
Hey all !
Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
dispatching with streams in different tasks ...
Here it is :
I'd like to get from a task RdV (Entry-Access) an object which could be
any subclass of a root'Class, and pass it to another task
Context : read (Root'Class'Input() ) tagged records from an input
stream, and send them to anther task which will write
(Root'Class'Output() ) the given records to another output stream.
I'm stuck with task memory isolation with does NOT allow to pass any
access object to a Root'Class.
Should I try to use a protected object ?
(not shore this solves the passing of a Class-wide object ...)
Thanks for your feed-back,
William
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 19:41 How to transfer Class-Wide object to a Task ? William FRANCK
@ 2019-10-14 19:55 ` Shark8
2019-10-14 20:48 ` William FRANCK
2019-10-14 19:58 ` Dmitry A. Kazakov
2019-10-14 20:21 ` William FRANCK
2 siblings, 1 reply; 23+ messages in thread
From: Shark8 @ 2019-10-14 19:55 UTC (permalink / raw)
On Monday, October 14, 2019 at 1:41:55 PM UTC-6, William FRANCK wrote:
> Hey all !
> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
> dispatching with streams in different tasks ...
Generic_Dispatching_Constructor?
https://www.adaic.org/resources/add_content/standards/05rat/html/Rat-2-6.html
Can you give us the actual use-case you're trying to accomplish?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 19:41 How to transfer Class-Wide object to a Task ? William FRANCK
2019-10-14 19:55 ` Shark8
@ 2019-10-14 19:58 ` Dmitry A. Kazakov
2019-10-14 20:58 ` William FRANCK
2019-10-14 20:21 ` William FRANCK
2 siblings, 1 reply; 23+ messages in thread
From: Dmitry A. Kazakov @ 2019-10-14 19:58 UTC (permalink / raw)
On 2019-10-14 21:41, William FRANCK wrote:
> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
> dispatching with streams in different tasks ...
>
> Here it is :
> I'd like to get from a task RdV (Entry-Access) an object which could be
> any subclass of a root'Class, and pass it to another task
>
> Context : read (Root'Class'Input() ) tagged records from an input
> stream, and send them to anther task which will write
> (Root'Class'Output() ) the given records to another output stream.
Strange design, why not to pipe streams using a FIFO?
> I'm stuck with task memory isolation with does NOT allow to pass any
> access object to a Root'Class.
>
> Should I try to use a protected object ?
> (not shore this solves the passing of a Class-wide object ...)
Yes, if using FIFO, a protected object can be used to signal
non-empty/not-full events at the FIFO ends.
Otherwise, use a reference-counted handle or a plain access type to the
target object. The reader task allocates the object in the pool and
passes a handle or access to it to the writer. The writer task writes
the object and then disposes it.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 19:41 How to transfer Class-Wide object to a Task ? William FRANCK
2019-10-14 19:55 ` Shark8
2019-10-14 19:58 ` Dmitry A. Kazakov
@ 2019-10-14 20:21 ` William FRANCK
2019-10-14 20:32 ` Dmitry A. Kazakov
2019-10-14 21:57 ` Shark8
2 siblings, 2 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-14 20:21 UTC (permalink / raw)
On 2019-10-14 19:41:53 +0000, William FRANCK said:
> Hey all !
> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
> dispatching with streams in different tasks ...
>
> Here it is :
> I'd like to get from a task RdV (Entry-Access) an object which could be
> any subclass of a root'Class, and pass it to another task
>
> Context : read (Root'Class'Input() ) tagged records from an input
> stream, and send them to anther task which will write
> (Root'Class'Output() ) the given records to another output stream.
>
> I'm stuck with task memory isolation with does NOT allow to pass any
> access object to a Root'Class.
>
> Should I try to use a protected object ?
> (not shore this solves the passing of a Class-wide object ...)
>
> Thanks for your feed-back,
> William
Here is some code to illustrate
(code needs soem fixings)
with
Ada.Text_io;
procedure main_ClassWide_to_2Task is
type Geo2D is tagged record
Y, X : integer;
Name : String(1..6) := "Object";
end record;
type Circle is new Geo2D with record
Radius : integer;
end record;
myObject : access Geo2D'Class;
-- ==============================
task reading is
entry Object(This : in out Geo2D'Class);
entry Stop;
end reading;
task writing is
entry Object(This : in Geo2D'Class);
entry Stop;
end writing;
-- ==============================
task body reading is
O2D : access Geo2D'Class;
begin
loop
select
accept Object(This : in out Geo2D'Class);
declare
-- (shortcut to simulate real case) :: Object :
constant Geo2D'Class := Dispatching_Input (Ada.Tags.Internal_Tag
(External_Tag), Stream);
begin
O2D := new Circle'(0,0,"Cercle",10);
Ada.Text_io.Put_line("Reading 2D Object: " & O2D.Name);
-- debug trace
-- This.all := O2D.all; --Compiler error : "This" is undefined
end;
or
accept Stop;
exit;
end select;
end loop;
end reading;
-- ==============================
task body writing is
myObject : access Geo2D'Class;
begin
loop
select
accept Object(This : in Geo2D'Class) do
myObject := This'Access;
end Object;
Ada.Text_io.Put_line("Writing 2D Object: " & This.Name); --
debug trace
or
accept Stop;
exit;
end select;
end loop;
end writing;
-- ==============================
begin
reading.Object(myObject.all);
writing.Object(myObject.all);
reading.Stop;
writing.Stop;
end main_ClassWide_to_2Task;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 20:21 ` William FRANCK
@ 2019-10-14 20:32 ` Dmitry A. Kazakov
2019-10-14 21:04 ` William FRANCK
2019-10-14 21:57 ` Shark8
1 sibling, 1 reply; 23+ messages in thread
From: Dmitry A. Kazakov @ 2019-10-14 20:32 UTC (permalink / raw)
On 2019-10-14 22:21, William FRANCK wrote:
> Here is some code to illustrate
> (code needs soem fixings)
The exercise does not make sense. It is a classwork, BTW?
It does not make sense because it could only work if both tasks
exchanging the object would be in a rendezvous. This would defeat the
very purpose of doing things in parallel during a rendezvous tasks are
synchronized.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 19:55 ` Shark8
@ 2019-10-14 20:48 ` William FRANCK
2019-10-14 22:01 ` Shark8
0 siblings, 1 reply; 23+ messages in thread
From: William FRANCK @ 2019-10-14 20:48 UTC (permalink / raw)
On 2019-10-14 19:55:22 +0000, Shark8 said:
> On Monday, October 14, 2019 at 1:41:55 PM UTC-6, William FRANCK wrote:
>> Hey all !
>> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
>> dispatching with streams in different tasks ...
>
> Generic_Dispatching_Constructor?
> https://www.adaic.org/resources/add_content/standards/05rat/html/Rat-2-6.html
>
> Can you give us the actual use-case you're trying to accomplish?
Yes! That's precisly what I'm using to read an existing datafile
containing records of 10 different structure (and size), then write
each record back to another stream.
Purpose is to anonymize some of the fields of differently structured records.
Happilly first characters are containing the recordtype name, so I use
it as External_Tag and can use the OO dispatching of 'Input and
'Output; selecting the correct 'Read and 'Write.
Allin one program (no multitasking) is OK.
My issue, is that I wanted to gain some speed by having 2 (Ada) tasks :
one for reading, one for writing.
I did a simple Proof of Concept for the multitasking by transfering an
IntegerObject. This is OK.
When I replace my Integer by a class-Wide object, I do find the clue to
make it correct.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 19:58 ` Dmitry A. Kazakov
@ 2019-10-14 20:58 ` William FRANCK
2019-10-15 4:40 ` Per Sandberg
2019-10-15 7:21 ` Dmitry A. Kazakov
0 siblings, 2 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-14 20:58 UTC (permalink / raw)
On 2019-10-14 19:58:34 +0000, Dmitry A. Kazakov said:
> On 2019-10-14 21:41, William FRANCK wrote:
>
>> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
>> dispatching with streams in different tasks ...
>>
>> Here it is :
>> I'd like to get from a task RdV (Entry-Access) an object which could be
>> any subclass of a root'Class, and pass it to another task
>>
>> Context : read (Root'Class'Input() ) tagged records from an input
>> stream, and send them to anther task which will write
>> (Root'Class'Output() ) the given records to another output stream.
>
> Strange design, why not to pipe streams using a FIFO?
>
>> I'm stuck with task memory isolation with does NOT allow to pass any
>> access object to a Root'Class.
>>
>> Should I try to use a protected object ?
>> (not shore this solves the passing of a Class-wide object ...)
>
> Yes, if using FIFO, a protected object can be used to signal
> non-empty/not-full events at the FIFO ends.
>
> Otherwise, use a reference-counted handle or a plain access type to the
> target object. The reader task allocates the object in the pool and
> passes a handle or access to it to the writer. The writer task writes
> the object and then disposes it.
Thanks you Dimitry for your follow-up.
Here is the multitasking part (simplified) (working, no issue)
for reading the datafile, and writing it back (after some data-process)
My first intention was : while Writing.Bloc is busy writing on the
output file, Reading.Bloc can take 1 record in advance
Now I have to insert the class-wide object passing in the Bloc.
As You mentionned, should I use a protected type (FIFO) instead of 2
// tasks ?
--================
with Ada.Text_io;
procedure main_tasks is
task reading is
entry Open;
entry Bloc;
entry Stop;
end reading;
task writing is
entry Create;
entry Bloc;
entry Stop;
end writing;
task body reading is
begin
loop
select
accept Open;
Ada.Text_IO.put_line("Opening file ...");
or
accept Bloc do
Ada.Text_IO.put_line("Reading ...");
end Bloc;
or
accept Stop;
Ada.Text_IO.put_line("Reading Stopped !");
exit;
end select;
end loop;
end reading;
task body writing is
begin
loop
select
accept Create;
Ada.Text_IO.put_line("Creating file ...");
or
accept Bloc do
Ada.Text_IO.put_line("Got bloc !");
end Bloc;
Ada.Text_IO.put_line("Writing bloc ...");
or
accept Stop;
Ada.Text_IO.put_line("Writing Stopped !");
exit;
end select;
end loop;
end writing;
begin
Writing.Create;
Reading.Open;
for i in 1..10 loop -- While not end_of_file()
Reading.Bloc;
Writing.Bloc;
end loop;
Reading.Stop;
Writing.Stop;
end main_tasks;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 20:32 ` Dmitry A. Kazakov
@ 2019-10-14 21:04 ` William FRANCK
0 siblings, 0 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-14 21:04 UTC (permalink / raw)
On 2019-10-14 20:32:45 +0000, Dmitry A. Kazakov said:
> On 2019-10-14 22:21, William FRANCK wrote:
>
>> Here is some code to illustrate
>> (code needs soem fixings)
>
> The exercise does not make sense. It is a classwork, BTW?
>
> It does not make sense because it could only work if both tasks
> exchanging the object would be in a rendezvous. This would defeat the
> very purpose of doing things in parallel during a rendezvous tasks are
> synchronized.
No it's a real use case,
I did wantedto make it simple : one read, then one write. just both in //.
maybe I did the design the wrong way...
Datafile is about 6_000_000 records; 16 GB
Longest record is 1381 Bytes.
William
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 20:21 ` William FRANCK
2019-10-14 20:32 ` Dmitry A. Kazakov
@ 2019-10-14 21:57 ` Shark8
2019-10-15 5:43 ` William FRANCK
1 sibling, 1 reply; 23+ messages in thread
From: Shark8 @ 2019-10-14 21:57 UTC (permalink / raw)
On Monday, October 14, 2019 at 2:21:50 PM UTC-6, William FRANCK wrote:
> On 2019-10-14 19:41:53 +0000, William FRANCK said:
>
Maybe something like this:
procedure Example is
Package Types is
Subtype Params is Ada.Streams.Root_Stream_Type'Class;
Type Root is abstract tagged null record;
Function Create (Parameters : not null access Params) return Root is abstract;
Type Circle is new Root with record
Radius : Float;
end record;
Type Square is new Root with record
Side : Integer;
end record;
Private
Function Create (Parameters : not null access Params) return Square;
Function Create (Parameters : not null access Params) return Circle;
End Types;
Use Types;
Package Class_Holder is new Ada.Containers.Indefinite_Holders(Root'Class);
Task Type Producer( Stream : not null access Ada.Streams.Root_Stream_Type'Class ) is
Entry Get( Object: out Class_Holder.Holder );
End Producer;
Task body Producer is
Function MAKE is new Ada.Tags.Generic_Dispatching_Constructor(
T => Types.Root,
Parameters => Ada.Streams.Root_Stream_Type'Class,
Constructor => Types.Create
);
Function To_Tag return Ada.Tags.Tag is
Begin
Return Square'Tag;
-- (if Ch = 'C' then Circle'Tag
-- elsif Ch = 'S' then Square'Tag
-- else raise Constraint_Error with "Tag '"&Ch&"' is invalid.");
End;
Begin
accept Get (Object : out Class_Holder.Holder) do
Object:=
Class_Holder.To_Holder( MAKE(To_Tag, Stream) );
end Get;
end Producer;
Function Get(P : Producer) return Root'Class is
H : Class_Holder.Holder;
Begin
P.Get(H);
Return H.Element;
End Get;
Package Body Types is
Function Create(Parameters : not null access Params) return Square is
Begin
Return (Side => 3);
End;
Function Create(Parameters : not null access Params) return Circle is
Begin
Return (Radius => 2.2);
End;
End Types;
begin
Ada.Text_IO.Put_Line( "START EXAMPLE." );
declare
I : Ada.Text_IO.File_Type renames Ada.Text_IO.Standard_Input;
P : Producer( Ada.Text_IO.Text_Streams.Stream(I) );
O : Root'Class := Get(P);
begin
Ada.Text_IO.Put_Line( "Tag: " & Ada.Tags.Expanded_Name(O'Tag) );
end;
Ada.Text_IO.Put_Line( "STOP EXAMPLE." );
end Example;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 20:48 ` William FRANCK
@ 2019-10-14 22:01 ` Shark8
2019-10-15 5:13 ` William FRANCK
0 siblings, 1 reply; 23+ messages in thread
From: Shark8 @ 2019-10-14 22:01 UTC (permalink / raw)
On Monday, October 14, 2019 at 2:48:33 PM UTC-6, William FRANCK wrote:
>
> I did a simple Proof of Concept for the multitasking by transfering an
> IntegerObject. This is OK.
>
> When I replace my Integer by a class-Wide object, I do find the clue to
> make it correct.
Ok.
I think it might be due to the Class Read/Write attributes acting different than the Input/Output ones -- I always have to look them up, but one of them reads/writes the discriminants and/or bounds of the item and the other doesn't.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 20:58 ` William FRANCK
@ 2019-10-15 4:40 ` Per Sandberg
2019-10-15 5:40 ` William FRANCK
2019-10-16 20:04 ` William FRANCK
2019-10-15 7:21 ` Dmitry A. Kazakov
1 sibling, 2 replies; 23+ messages in thread
From: Per Sandberg @ 2019-10-15 4:40 UTC (permalink / raw)
Why not use Ada.Containers.Indefinite_holders to encapsulate the
Classwide type during store?
----------------
with ADA.Containers.Indefinite_Holders;
package Demo is
type T1 is interface;
package T1_Holders is new ADA.Containers.Indefinite_Holders (T1'Class);
task type Storage_Task is
entry Internal_Store (D : in T1_Holders.Holder);
entry Internal_Fetch (D : out T1_Holders.Holder);
end Storage_Task;
procedure Store (S : Storage_Task; Var : in Demo.T1'Class );
Function Fetch(S : Storage_Task) return Demo.T1'Class;
end Demo;
---------------------
package body Demo is
procedure Store (S : Storage_Task; Var : in Demo.T1'Class ) is
H : Demo.T1_Holders.Holder;
begin
H.Replace_Element (Var);
S.Internal_Store(H);
end Store;
Function Fetch(S : Storage_Task) return Demo.T1'Class is
H : Demo.T1_Holders.Holder;
begin
S.Internal_Fetch (H);
return H.Element;
end Fetch;
task body Storage_Task is
S : T1_Holders.Holder;
begin
loop
select
accept Internal_Fetch (D : out T1_Holders.Holder) do
D := S;
end Internal_Fetch;
or accept Internal_Store (D : in T1_Holders.Holder) do
S := D;
end Internal_Store;
or
terminate;
end select;
end loop;
end Storage_Task;
end Demo;
---------------------
/P
On 2019-10-14 22:58, William FRANCK wrote:
> On 2019-10-14 19:58:34 +0000, Dmitry A. Kazakov said:
>
>> On 2019-10-14 21:41, William FRANCK wrote:
>>
>>> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
>>> dispatching with streams in different tasks ...
>>>
>>> Here it is :
>>> I'd like to get from a task RdV (Entry-Access) an object which could
>>> be any subclass of a root'Class, and pass it to another task
>>>
>>> Context : read (Root'Class'Input() ) tagged records from an input
>>> stream, and send them to anther task which will write
>>> (Root'Class'Output() ) the given records to another output stream.
>>
>> Strange design, why not to pipe streams using a FIFO?
>>
>>> I'm stuck with task memory isolation with does NOT allow to pass any
>>> access object to a Root'Class.
>>>
>>> Should I try to use a protected object ?
>>> (not shore this solves the passing of a Class-wide object ...)
>>
>> Yes, if using FIFO, a protected object can be used to signal
>> non-empty/not-full events at the FIFO ends.
>>
>> Otherwise, use a reference-counted handle or a plain access type to
>> the target object. The reader task allocates the object in the pool
>> and passes a handle or access to it to the writer. The writer task
>> writes the object and then disposes it.
>
> Thanks you Dimitry for your follow-up.
>
> Here is the multitasking part (simplified) (working, no issue)
> for reading the datafile, and writing it back (after some data-process)
>
> My first intention was : while Writing.Bloc is busy writing on the
> output file, Reading.Bloc can take 1 record in advance
>
> Now I have to insert the class-wide object passing in the Bloc.
>
> As You mentionned, should I use a protected type (FIFO) instead of 2 //
> tasks ?
>
> --================
> with Ada.Text_io;
>
> procedure main_tasks is
>
> task reading is
> entry Open;
> entry Bloc;
> entry Stop;
> end reading;
>
> task writing is
> entry Create;
> entry Bloc;
> entry Stop;
> end writing;
>
> task body reading is
> begin
> loop
> select
> accept Open;
> Ada.Text_IO.put_line("Opening file ...");
> or
> accept Bloc do
> Ada.Text_IO.put_line("Reading ...");
> end Bloc;
> or
> accept Stop;
> Ada.Text_IO.put_line("Reading Stopped !");
> exit;
> end select;
> end loop;
> end reading;
>
> task body writing is
> begin
> loop
> select
> accept Create;
> Ada.Text_IO.put_line("Creating file ...");
> or
> accept Bloc do
> Ada.Text_IO.put_line("Got bloc !");
> end Bloc;
> Ada.Text_IO.put_line("Writing bloc ...");
> or
> accept Stop;
> Ada.Text_IO.put_line("Writing Stopped !");
> exit;
> end select;
> end loop;
> end writing;
>
> begin
>
> Writing.Create;
> Reading.Open;
> for i in 1..10 loop -- While not end_of_file()
> Reading.Bloc;
> Writing.Bloc;
> end loop;
>
> Reading.Stop;
> Writing.Stop;
>
> end main_tasks;
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 22:01 ` Shark8
@ 2019-10-15 5:13 ` William FRANCK
0 siblings, 0 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-15 5:13 UTC (permalink / raw)
On 2019-10-14 22:01:08 +0000, Shark8 said:
> On Monday, October 14, 2019 at 2:48:33 PM UTC-6, William FRANCK wrote:
>>
>> I did a simple Proof of Concept for the multitasking by transfering an
>> IntegerObject. This is OK.
>>
>> When I replace my Integer by a class-Wide object, I do find the clue to
>> make it correct.
>
> Ok.
> I think it might be due to the Class Read/Write attributes acting
> different than the Input/Output ones -- I always have to look them up,
> but one of them reads/writes the discriminants and/or bounds of the
> item and the other doesn't.
Sorry Shark , my last sentence is not correct ...
Should read :
'When I replace my Integer by a class-Wide object, I can not find a
simple way to
make it work.'
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-15 4:40 ` Per Sandberg
@ 2019-10-15 5:40 ` William FRANCK
2019-10-16 20:04 ` William FRANCK
1 sibling, 0 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-15 5:40 UTC (permalink / raw)
Thanks Per !
"Containers.Indefinite_holders" seems to be the way to go.
(I didn't used them yet)
I will give it a try :-)
William.
On 2019-10-15 04:40:33 +0000, Per Sandberg said:
> Why not use Ada.Containers.Indefinite_holders to encapsulate the
> Classwide type during store?
> ----------------
> with ADA.Containers.Indefinite_Holders;
> package Demo is
> type T1 is interface;
> package T1_Holders is new ADA.Containers.Indefinite_Holders (T1'Class);
>
> task type Storage_Task is
> entry Internal_Store (D : in T1_Holders.Holder);
> entry Internal_Fetch (D : out T1_Holders.Holder);
> end Storage_Task;
>
> procedure Store (S : Storage_Task; Var : in Demo.T1'Class );
> Function Fetch(S : Storage_Task) return Demo.T1'Class;
> end Demo;
> ---------------------
> package body Demo is
> procedure Store (S : Storage_Task; Var : in Demo.T1'Class ) is
> H : Demo.T1_Holders.Holder;
> begin
> H.Replace_Element (Var);
> S.Internal_Store(H);
> end Store;
> Function Fetch(S : Storage_Task) return Demo.T1'Class is
> H : Demo.T1_Holders.Holder;
> begin
> S.Internal_Fetch (H);
> return H.Element;
> end Fetch;
>
> task body Storage_Task is
> S : T1_Holders.Holder;
> begin
> loop
> select
> accept Internal_Fetch (D : out T1_Holders.Holder) do
> D := S;
> end Internal_Fetch;
> or accept Internal_Store (D : in T1_Holders.Holder) do
> S := D;
> end Internal_Store;
> or
> terminate;
> end select;
> end loop;
> end Storage_Task;
> end Demo;
> ---------------------
> /P
>
> On 2019-10-14 22:58, William FRANCK wrote:
>> On 2019-10-14 19:58:34 +0000, Dmitry A. Kazakov said:
>>
>>> On 2019-10-14 21:41, William FRANCK wrote:
>>>
>>>> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
>>>> dispatching with streams in different tasks ...
>>>>
>>>> Here it is :
>>>> I'd like to get from a task RdV (Entry-Access) an object which could be
>>>> any subclass of a root'Class, and pass it to another task
>>>>
>>>> Context : read (Root'Class'Input() ) tagged records from an input
>>>> stream, and send them to anther task which will write
>>>> (Root'Class'Output() ) the given records to another output stream.
>>>
>>> Strange design, why not to pipe streams using a FIFO?
>>>
>>>> I'm stuck with task memory isolation with does NOT allow to pass any
>>>> access object to a Root'Class.
>>>>
>>>> Should I try to use a protected object ?
>>>> (not shore this solves the passing of a Class-wide object ...)
>>>
>>> Yes, if using FIFO, a protected object can be used to signal
>>> non-empty/not-full events at the FIFO ends.
>>>
>>> Otherwise, use a reference-counted handle or a plain access type to the
>>> target object. The reader task allocates the object in the pool and
>>> passes a handle or access to it to the writer. The writer task writes
>>> the object and then disposes it.
>>
>> Thanks you Dimitry for your follow-up.
>>
>> Here is the multitasking part (simplified) (working, no issue)
>> for reading the datafile, and writing it back (after some data-process)
>>
>> My first intention was : while Writing.Bloc is busy writing on the
>> output file, Reading.Bloc can take 1 record in advance
>>
>> Now I have to insert the class-wide object passing in the Bloc.
>>
>> As You mentionned, should I use a protected type (FIFO) instead of 2
>> // tasks ?
>>
>> --================
>> with Ada.Text_io;
>>
>> procedure main_tasks is
>>
>> task reading is
>> entry Open;
>> entry Bloc;
>> entry Stop;
>> end reading;
>>
>> task writing is
>> entry Create;
>> entry Bloc;
>> entry Stop;
>> end writing;
>>
>> task body reading is
>> begin
>> loop
>> select
>> accept Open;
>> Ada.Text_IO.put_line("Opening file ...");
>> or
>> accept Bloc do
>> Ada.Text_IO.put_line("Reading ...");
>> end Bloc;
>> or
>> accept Stop;
>> Ada.Text_IO.put_line("Reading Stopped !");
>> exit;
>> end select;
>> end loop;
>> end reading;
>>
>> task body writing is
>> begin
>> loop
>> select
>> accept Create;
>> Ada.Text_IO.put_line("Creating file ...");
>> or
>> accept Bloc do
>> Ada.Text_IO.put_line("Got bloc !");
>> end Bloc;
>> Ada.Text_IO.put_line("Writing bloc ...");
>> or
>> accept Stop;
>> Ada.Text_IO.put_line("Writing Stopped !");
>> exit;
>> end select;
>> end loop;
>> end writing;
>>
>> begin
>>
>> Writing.Create;
>> Reading.Open;
>> for i in 1..10 loop -- While not end_of_file()
>> Reading.Bloc;
>> Writing.Bloc;
>> end loop;
>>
>> Reading.Stop;
>> Writing.Stop;
>>
>> end main_tasks;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 21:57 ` Shark8
@ 2019-10-15 5:43 ` William FRANCK
0 siblings, 0 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-15 5:43 UTC (permalink / raw)
Thank you Shark,
I'll give it a try too :-)
And send you all a more complete source code of my use case.
William
On 2019-10-14 21:57:57 +0000, Shark8 said:
> On Monday, October 14, 2019 at 2:21:50 PM UTC-6, William FRANCK wrote:
>> On 2019-10-14 19:41:53 +0000, William FRANCK said:
>>
> Maybe something like this:
>
> procedure Example is
> Package Types is
> Subtype Params is Ada.Streams.Root_Stream_Type'Class;
> Type Root is abstract tagged null record;
> Function Create (Parameters : not null access Params)
> return Root is abstract;
>
> Type Circle is new Root with record
> Radius : Float;
> end record;
>
> Type Square is new Root with record
> Side : Integer;
> end record;
> Private
>
> Function Create (Parameters : not null access Params)
> return Square;
> Function Create (Parameters : not null access Params)
> return Circle;
> End Types;
>
>
> Use Types;
> Package Class_Holder is new
> Ada.Containers.Indefinite_Holders(Root'Class);
> Task Type Producer( Stream : not null access
> Ada.Streams.Root_Stream_Type'Class ) is
> Entry Get( Object: out Class_Holder.Holder );
> End Producer;
>
> Task body Producer is
> Function MAKE is new Ada.Tags.Generic_Dispatching_Constructor(
> T => Types.Root,
> Parameters => Ada.Streams.Root_Stream_Type'Class,
> Constructor => Types.Create
> );
>
> Function To_Tag return Ada.Tags.Tag is
> Begin
> Return Square'Tag;
> -- (if Ch = 'C' then Circle'Tag
> -- elsif Ch = 'S' then Square'Tag
> -- else raise Constraint_Error with "Tag '"&Ch&"' is
> invalid.");
> End;
>
> Begin
> accept Get (Object : out Class_Holder.Holder) do
> Object:=
> Class_Holder.To_Holder( MAKE(To_Tag, Stream) );
> end Get;
> end Producer;
>
> Function Get(P : Producer) return Root'Class is
> H : Class_Holder.Holder;
> Begin
> P.Get(H);
> Return H.Element;
> End Get;
>
>
>
> Package Body Types is
> Function Create(Parameters : not null access Params) return
> Square is
> Begin
> Return (Side => 3);
> End;
>
> Function Create(Parameters : not null access Params) return
> Circle is
> Begin
> Return (Radius => 2.2);
> End;
> End Types;
>
> begin
> Ada.Text_IO.Put_Line( "START EXAMPLE." );
> declare
> I : Ada.Text_IO.File_Type renames Ada.Text_IO.Standard_Input;
> P : Producer( Ada.Text_IO.Text_Streams.Stream(I) );
> O : Root'Class := Get(P);
> begin
> Ada.Text_IO.Put_Line( "Tag: " & Ada.Tags.Expanded_Name(O'Tag) );
> end;
> Ada.Text_IO.Put_Line( "STOP EXAMPLE." );
> end Example;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-14 20:58 ` William FRANCK
2019-10-15 4:40 ` Per Sandberg
@ 2019-10-15 7:21 ` Dmitry A. Kazakov
2019-10-15 14:31 ` Optikos
1 sibling, 1 reply; 23+ messages in thread
From: Dmitry A. Kazakov @ 2019-10-15 7:21 UTC (permalink / raw)
On 2019-10-14 22:58, William FRANCK wrote:
> Here is the multitasking part (simplified) (working, no issue)
> for reading the datafile, and writing it back (after some data-process)
>
> My first intention was : while Writing.Bloc is busy writing on the
> output file, Reading.Bloc can take 1 record in advance
That is what OS asynchronous I/O does already. But that is aside.
> Now I have to insert the class-wide object passing in the Bloc.
Stream attributes 'Input and 'Output would do.
> As You mentionned, should I use a protected type (FIFO) instead of 2 //
> tasks ?
A protected object to synchronize two tasks:
Producer -> FIFO -> Consumer
Block put <- PO -> Block get
when full when empty
FIFO does not need interlocking in this scenario. Protected object is
only to prevent busy waiting at the ends.
Since you are working with streams you can use a storage stream instead
of raw FIFO:
Producer -> Storage stream -> Consumer
Block write when full Block read when empty
I still do not understand why you serialize and deserialize insted of
copying bytes as they are.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-15 7:21 ` Dmitry A. Kazakov
@ 2019-10-15 14:31 ` Optikos
2019-10-15 19:41 ` William FRANCK
0 siblings, 1 reply; 23+ messages in thread
From: Optikos @ 2019-10-15 14:31 UTC (permalink / raw)
On Tuesday, October 15, 2019 at 2:21:51 AM UTC-5, Dmitry A. Kazakov wrote:
> On 2019-10-14 22:58, William FRANCK wrote:
>
> > Here is the multitasking part (simplified) (working, no issue)
> > for reading the datafile, and writing it back (after some data-process)
> >
> > My first intention was : while Writing.Bloc is busy writing on the
> > output file, Reading.Bloc can take 1 record in advance
>
> That is what OS asynchronous I/O does already. But that is aside.
>
> > Now I have to insert the class-wide object passing in the Bloc.
>
> Stream attributes 'Input and 'Output would do.
>
> > As You mentionned, should I use a protected type (FIFO) instead of 2 //
> > tasks ?
>
> A protected object to synchronize two tasks:
>
> Producer -> FIFO -> Consumer
> Block put <- PO -> Block get
> when full when empty
>
> FIFO does not need interlocking in this scenario. Protected object is
> only to prevent busy waiting at the ends.
>
> Since you are working with streams you can use a storage stream instead
> of raw FIFO:
>
> Producer -> Storage stream -> Consumer
> Block write when full Block read when empty
>
> I still do not understand why you serialize and deserialize insted of
> copying bytes as they are.
Because OPer is apparently migrating code that was in 2 (UNIXesque) processes to instead be 2 threads in the same process.
William Franck, you really should rework your design to do as Dmitry advises: FIFO message queues between 2 otherwise asynchronous threads that work on their own slice of the problem (and have their own slice of the problem's data structures). Under that revised design, only the FIFO's internals need to worry about thread safety, because before posting and after retrieving from the queue the 2 threads run full tilt in their independent territory without interacting with each other. (This of course assumes that there exists some sort of slicing/partitioning of your problem-space, but there usually is if you look intensely enough for well-defined demarcations.)
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-15 14:31 ` Optikos
@ 2019-10-15 19:41 ` William FRANCK
2019-10-15 20:03 ` Shark8
0 siblings, 1 reply; 23+ messages in thread
From: William FRANCK @ 2019-10-15 19:41 UTC (permalink / raw)
Thank you Optikas for your feedback and advice :-)
Sure, the usual design of a multithreaded 'producer' and 'consumer'
takes advantage of a FIFO round.
I will considering and testing this as Dmitry outlined it for me.
In fact I may considering my design as a FIFO of one (1) (lol) ?
For now I'm implementing the 'Ada.Containers.Indefinite_Holders' in a
little PoC.
I'l will share this to the group.
As I mentionned, I do use the Stream attributes 'Input and 'Output, and
is OK in one single program. The challenge for me is to make it work
(and pass the objects) in a multi-tasking design.
Huh ?!? There is still something to learn about class-wide and
indefinite type usage :-)
By the way, I really appreciate the support of this group !
Kind regards,
William
On 2019-10-15 14:31:30 +0000, Optikos said:
> On Tuesday, October 15, 2019 at 2:21:51 AM UTC-5, Dmitry A. Kazakov wrote:
>> On 2019-10-14 22:58, William FRANCK wrote:
>>
>>> Here is the multitasking part (simplified) (working, no issue)
>>> for reading the datafile, and writing it back (after some data-process)
>>>
>>> My first intention was : while Writing.Bloc is busy writing on the> >
>>> output file, Reading.Bloc can take 1 record in advance
>>
>> That is what OS asynchronous I/O does already. But that is aside.
>>
>>> Now I have to insert the class-wide object passing in the Bloc.
>>
>> Stream attributes 'Input and 'Output would do.
>>
>>> As You mentionned, should I use a protected type (FIFO) instead of 2
>>> //> > tasks ?
>>
>> A protected object to synchronize two tasks:
>>
>> Producer -> FIFO -> Consumer
>> Block put <- PO -> Block get
>> when full when empty
>>
>> FIFO does not need interlocking in this scenario. Protected object is>
>> only to prevent busy waiting at the ends.
>>
>> Since you are working with streams you can use a storage stream
>> instead> of raw FIFO:
>>
>> Producer -> Storage stream -> Consumer
>> Block write when full Block read when empty
>>
>> I still do not understand why you serialize and deserialize insted of>
>> copying bytes as they are.
>
> Because OPer is apparently migrating code that was in 2 (UNIXesque)
> processes to instead be 2 threads in the same process.
>
> William Franck, you really should rework your design to do as Dmitry
> advises: FIFO message queues between 2 otherwise asynchronous threads
> that work on their own slice of the problem (and have their own slice
> of the problem's data structures). Under that revised design, only the
> FIFO's internals need to worry about thread safety, because before
> posting and after retrieving from the queue the 2 threads run full tilt
> in their independent territory without interacting with each other.
> (This of course assumes that there exists some sort of
> slicing/partitioning of your problem-space, but there usually is if you
> look intensely enough for well-defined demarcations.)
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-15 19:41 ` William FRANCK
@ 2019-10-15 20:03 ` Shark8
0 siblings, 0 replies; 23+ messages in thread
From: Shark8 @ 2019-10-15 20:03 UTC (permalink / raw)
One of the nice things about a stream-based design is that (at least theoretically) is that your source is abstracted away -- it doesn't matter if your source is keyboard or radio-receiver or disk or the destination is screen or radio-transmitter or disk.
So, with such a design you could have a system where items are stored in a cache which might be dumped-to/retrieved-from disk, as well as real-time item-generation, as a 'producer' and where the 'consumer' processes the items.
This sort of design could allow for a high-speed and low-speed channel [to the consumer], as well as a system where [work-]items could be saved -- say for a node restart in certain [distributed] cases.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-15 4:40 ` Per Sandberg
2019-10-15 5:40 ` William FRANCK
@ 2019-10-16 20:04 ` William FRANCK
2019-10-16 23:43 ` Anh Vo
2019-10-17 9:28 ` William FRANCK
1 sibling, 2 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-16 20:04 UTC (permalink / raw)
Hello Per,
Thaks for the tip !
It saved my life :-).
By using 'Ada.Containers.Indefinite_Holders'
it was possible to transfer the class-wide object from one task-entry
to another.
If some of you are interested by the 129 SLOC for the sake of sharing designs,
I will post it on this tread.
William.
PS : I didn't found any practical advantage to implement a design with
a regular FIFO as the queue will always be at it's max allocation,
waiting for writing on the file...
Thanks Dmitry for the tip!
On 2019-10-15 04:40:33 +0000, Per Sandberg said:
> Why not use Ada.Containers.Indefinite_holders to encapsulate the
> Classwide type during store?
> ----------------
> with ADA.Containers.Indefinite_Holders;
> package Demo is
> type T1 is interface;
> package T1_Holders is new ADA.Containers.Indefinite_Holders (T1'Class);
>
> task type Storage_Task is
> entry Internal_Store (D : in T1_Holders.Holder);
> entry Internal_Fetch (D : out T1_Holders.Holder);
> end Storage_Task;
>
> procedure Store (S : Storage_Task; Var : in Demo.T1'Class );
> Function Fetch(S : Storage_Task) return Demo.T1'Class;
> end Demo;
> ---------------------
> package body Demo is
> procedure Store (S : Storage_Task; Var : in Demo.T1'Class ) is
> H : Demo.T1_Holders.Holder;
> begin
> H.Replace_Element (Var);
> S.Internal_Store(H);
> end Store;
> Function Fetch(S : Storage_Task) return Demo.T1'Class is
> H : Demo.T1_Holders.Holder;
> begin
> S.Internal_Fetch (H);
> return H.Element;
> end Fetch;
>
> task body Storage_Task is
> S : T1_Holders.Holder;
> begin
> loop
> select
> accept Internal_Fetch (D : out T1_Holders.Holder) do
> D := S;
> end Internal_Fetch;
> or accept Internal_Store (D : in T1_Holders.Holder) do
> S := D;
> end Internal_Store;
> or
> terminate;
> end select;
> end loop;
> end Storage_Task;
> end Demo;
> ---------------------
> /P
>
> On 2019-10-14 22:58, William FRANCK wrote:
>> On 2019-10-14 19:58:34 +0000, Dmitry A. Kazakov said:
>>
>>> On 2019-10-14 21:41, William FRANCK wrote:
>>>
>>>> Here is a nice issue I have with Ada (GNAT 2012) when trying to do OO
>>>> dispatching with streams in different tasks ...
>>>>
>>>> Here it is :
>>>> I'd like to get from a task RdV (Entry-Access) an object which could be
>>>> any subclass of a root'Class, and pass it to another task
>>>>
>>>> Context : read (Root'Class'Input() ) tagged records from an input
>>>> stream, and send them to anther task which will write
>>>> (Root'Class'Output() ) the given records to another output stream.
>>>
>>> Strange design, why not to pipe streams using a FIFO?
>>>
>>>> I'm stuck with task memory isolation with does NOT allow to pass any
>>>> access object to a Root'Class.
>>>>
>>>> Should I try to use a protected object ?
>>>> (not shore this solves the passing of a Class-wide object ...)
>>>
>>> Yes, if using FIFO, a protected object can be used to signal
>>> non-empty/not-full events at the FIFO ends.
>>>
>>> Otherwise, use a reference-counted handle or a plain access type to the
>>> target object. The reader task allocates the object in the pool and
>>> passes a handle or access to it to the writer. The writer task writes
>>> the object and then disposes it.
>>
>> Thanks you Dimitry for your follow-up.
>>
>> Here is the multitasking part (simplified) (working, no issue)
>> for reading the datafile, and writing it back (after some data-process)
>>
>> My first intention was : while Writing.Bloc is busy writing on the
>> output file, Reading.Bloc can take 1 record in advance
>>
>> Now I have to insert the class-wide object passing in the Bloc.
>>
>> As You mentionned, should I use a protected type (FIFO) instead of 2
>> // tasks ?
>>
>> --================
>> with Ada.Text_io;
>>
>> procedure main_tasks is
>>
>> task reading is
>> entry Open;
>> entry Bloc;
>> entry Stop;
>> end reading;
>>
>> task writing is
>> entry Create;
>> entry Bloc;
>> entry Stop;
>> end writing;
>>
>> task body reading is
>> begin
>> loop
>> select
>> accept Open;
>> Ada.Text_IO.put_line("Opening file ...");
>> or
>> accept Bloc do
>> Ada.Text_IO.put_line("Reading ...");
>> end Bloc;
>> or
>> accept Stop;
>> Ada.Text_IO.put_line("Reading Stopped !");
>> exit;
>> end select;
>> end loop;
>> end reading;
>>
>> task body writing is
>> begin
>> loop
>> select
>> accept Create;
>> Ada.Text_IO.put_line("Creating file ...");
>> or
>> accept Bloc do
>> Ada.Text_IO.put_line("Got bloc !");
>> end Bloc;
>> Ada.Text_IO.put_line("Writing bloc ...");
>> or
>> accept Stop;
>> Ada.Text_IO.put_line("Writing Stopped !");
>> exit;
>> end select;
>> end loop;
>> end writing;
>>
>> begin
>>
>> Writing.Create;
>> Reading.Open;
>> for i in 1..10 loop -- While not end_of_file()
>> Reading.Bloc;
>> Writing.Bloc;
>> end loop;
>>
>> Reading.Stop;
>> Writing.Stop;
>>
>> end main_tasks;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-16 20:04 ` William FRANCK
@ 2019-10-16 23:43 ` Anh Vo
2019-10-17 9:28 ` William FRANCK
1 sibling, 0 replies; 23+ messages in thread
From: Anh Vo @ 2019-10-16 23:43 UTC (permalink / raw)
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-16 20:04 ` William FRANCK
2019-10-16 23:43 ` Anh Vo
@ 2019-10-17 9:28 ` William FRANCK
2019-10-17 10:00 ` Dmitry A. Kazakov
1 sibling, 1 reply; 23+ messages in thread
From: William FRANCK @ 2019-10-17 9:28 UTC (permalink / raw)
On 2019-10-16 20:04:41 +0000, William FRANCK said:
I've uploaded my PoC source file on the comp.lang.ada group.
main_ClassWide_to_2Task.adb
"Transfering Class-Wide Objects to task-entries, with
Ada.Containers.Indefinite_Holders."
-- ==== here it is as a copy =====
with Ada.Containers.Indefinite_Holders,
Ada.Text_IO;
use
Ada,
Ada.Text_IO;
procedure main_ClassWide_to_2Task is
-- ========================================================================
-- Demo program showing how to transfer Class-Wide objects to task-entries,
-- with Ada.Containers.Indefinite_Holders
-- ========================================================================
type Geo2D is tagged record
Y, X : Integer;
Name : String (1 .. 8) := "Object 0";
end record;
type Circle is new Geo2D with record
Radius : Integer;
end record;
package Geo2D_Holders is new Ada.Containers.Indefinite_Holders
(Geo2D'Class);
myDataStore : Geo2D_Holders.Holder;
-- ==========================================================
package Object_Reading is
task reading is
entry Open;
entry Object (DataStore : in out Geo2D_Holders.Holder);
entry Stop;
end reading;
end Object_Reading;
-- ==========================================================
package Object_Writing is
task writing is
entry Create;
entry Object (DataStore : in Geo2D_Holders.Holder);
entry Stop;
end writing;
end Object_Writing;
-- ==========================================================
package body Object_Reading is
task body reading is
LocalDataStore : Geo2D_Holders.Holder;
Nb_items : Natural := 0; -- for tracing
begin
accept Open do -- end go further only after open is complete
Text_IO.Put_Line (Standard_Error,"Opening file ...");
end Open;
Text_IO.Put_Line (Standard_Error,"Input file ready !");
loop
select
accept Object (DataStore : in out Geo2D_Holders.Holder) do
DataStore := Geo2D_Holders.Copy (Source => LocalDataStore);
end Object;
declare
-- (shortcut to simulate real case with Streams and
*'Class'Input dispatching) ::
--Object : constant Geo2D'Class := Dispatching_Input
(Ada.Tags.Internal_Tag (External_Tag), Stream);
O2D : Geo2D'Class := Circle'(0, 0, "Cercle 0", 10);
-- simulate object creation done by 'Dispatching_Input'
begin
NB_Items := NB_Items +1; -- for demo
O2D.Name(7..8) := Natural'Image(Nb_Items); -- for demo
Text_IO.Put_Line (Standard_Error,"Reading 2D Object
#"& Natural'Image(Nb_Items)&": " & O2D.Name); -- debug trace
Geo2D_Holders.Replace_Element (Container =>
LocalDataStore, New_Item => O2D);
end;
or
accept Stop do
Text_IO.Put_Line (Standard_Error,"Closing Input file...");
end Stop;
Text_IO.Put_Line (Standard_Error,"File cloded, Reading
Stopped !");
exit;
end select;
end loop;
end reading;
end Object_Reading;
-- ==========================================================
package body Object_Writing is
task body writing is
LocalDataStore : Geo2D_Holders.Holder;
Nb_items : Natural := 0;
begin
accept Create; -- and go ahead (with i.e. opening input file)
Text_IO.Put_Line (Standard_Error,"Creating file ...");
Text_IO.Put_Line (Standard_Error,"Output file ready !");
loop
select
accept Object (DataStore : in Geo2D_Holders.Holder) do
LocalDataStore := Geo2D_Holders.copy (DataStore );
end Object; -- go return to the main process, and go
ahead with reading next record
if not Geo2D_Holders.Is_Empty(Container => LocalDataStore)
then
declare
O2D : Geo2D'Class := Geo2D_Holders.Element
(Container => LocalDataStore);
begin
NB_Items := NB_Items +1; -- for demo
-- (shortcut to simulate real case with Streams
and *'Class'Output dispatching) ::
Text_IO.Put_Line (Standard_Error," Writing 2D
Object #"& Natural'Image(Nb_Items)&": " & O2D.Name); -- debug trace
end;
end if;
or
accept Stop do
Text_IO.Put_Line (Standard_Error,"Closing Output file...");
end Stop;
Text_IO.Put_Line (Standard_Error,"File Closed, Writing
Stopped ! ");
exit;
end select;
end loop;
end writing;
end Object_Writing;
-- ==========================================================
use Object_Reading;
use Object_Writing;
begin
Writing.Create;
Reading.Open;
for i in 1 .. 9 loop -- While not end_of_file()
Reading.Object (myDataStore);
Writing.Object (myDataStore);
end loop;
Reading.Stop;
Writing.Stop;
end main_ClassWide_to_2Task;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-17 9:28 ` William FRANCK
@ 2019-10-17 10:00 ` Dmitry A. Kazakov
2019-10-17 10:45 ` William FRANCK
0 siblings, 1 reply; 23+ messages in thread
From: Dmitry A. Kazakov @ 2019-10-17 10:00 UTC (permalink / raw)
On 2019-10-17 11:28, William FRANCK wrote:
> On 2019-10-16 20:04:41 +0000, William FRANCK said:
> I've uploaded my PoC source file on the comp.lang.ada group.
The code looks wrong. If you use holders it could be like this:
Reader:
loop
declare
read and create a local object
begin
accept entry call and in the rendezvous
copy object into holder passed to the entry
end;
end loop;
Writer:
loop
call to the reader entry passing local holder
write the object held by the holder
end loop;
P.S. Using an access type or reference-counted object would reduce copying.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to transfer Class-Wide object to a Task ?
2019-10-17 10:00 ` Dmitry A. Kazakov
@ 2019-10-17 10:45 ` William FRANCK
0 siblings, 0 replies; 23+ messages in thread
From: William FRANCK @ 2019-10-17 10:45 UTC (permalink / raw)
Ok, Dmitry, I'll investigate this!
btw, I know you're a senior and respectfull Ada developer :-)
William
On 2019-10-17 10:00:16 +0000, Dmitry A. Kazakov said:
> On 2019-10-17 11:28, William FRANCK wrote:
>> On 2019-10-16 20:04:41 +0000, William FRANCK said:
>> I've uploaded my PoC source file on the comp.lang.ada group.
>
> The code looks wrong. If you use holders it could be like this:
>
> Reader:
>
> loop
> declare
> read and create a local object
> begin
> accept entry call and in the rendezvous
> copy object into holder passed to the entry
> end;
> end loop;
>
> Writer:
>
> loop
> call to the reader entry passing local holder
> write the object held by the holder
> end loop;
>
> P.S. Using an access type or reference-counted object would reduce copying.
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2019-10-17 10:45 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-14 19:41 How to transfer Class-Wide object to a Task ? William FRANCK
2019-10-14 19:55 ` Shark8
2019-10-14 20:48 ` William FRANCK
2019-10-14 22:01 ` Shark8
2019-10-15 5:13 ` William FRANCK
2019-10-14 19:58 ` Dmitry A. Kazakov
2019-10-14 20:58 ` William FRANCK
2019-10-15 4:40 ` Per Sandberg
2019-10-15 5:40 ` William FRANCK
2019-10-16 20:04 ` William FRANCK
2019-10-16 23:43 ` Anh Vo
2019-10-17 9:28 ` William FRANCK
2019-10-17 10:00 ` Dmitry A. Kazakov
2019-10-17 10:45 ` William FRANCK
2019-10-15 7:21 ` Dmitry A. Kazakov
2019-10-15 14:31 ` Optikos
2019-10-15 19:41 ` William FRANCK
2019-10-15 20:03 ` Shark8
2019-10-14 20:21 ` William FRANCK
2019-10-14 20:32 ` Dmitry A. Kazakov
2019-10-14 21:04 ` William FRANCK
2019-10-14 21:57 ` Shark8
2019-10-15 5:43 ` William FRANCK
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox