* 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: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 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 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-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: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: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-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-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
* 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-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 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 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
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