* passing messages between the tasks @ 2014-10-14 1:17 compguy45 2014-10-14 1:49 ` Adam Beneschan 0 siblings, 1 reply; 18+ messages in thread From: compguy45 @ 2014-10-14 1:17 UTC (permalink / raw) I understand in this example that calling tasks(main or environmental task) is passing id value to 2 tasks...In regarding to code below I have 2 question and was hoping someone can answer.... 1 with Ada.Text_IO, Ada.Integer_Text_IO; 2 use Ada.Text_IO, Ada.Integer_Text_IO; 3 4 procedure SomeProcedure is 5 6 task type lamp is 7 entry reset(id : Integer); 8 end lamp; 9 10 lamps : array (1..6) of lamp; 11 12 task body lamp is 13 begin 14 Put_Line("Body of task lamp"); 15 accept reset(id : Integer) do 16 put("inside reset"); 17 put(id); 18 New_Line; 19 end reset; 20 delay 4.0; 21 put("after accept"); 22 end lamp; 23 24 begin 25 lamps(1).reset(id => 1); 26 lamps(2).reset(id => 2); 27 end SomeProcedure; 1. How would would these 2 tasks send message back to main? For example how would each of these two lamp tasks send "i received call to my acceptstatement"); 2. If there are some variables inside the body of the task to be saved and they might be different for each of these tasks how to save these values? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 1:17 passing messages between the tasks compguy45 @ 2014-10-14 1:49 ` Adam Beneschan 2014-10-14 1:55 ` compguy45 ` (2 more replies) 0 siblings, 3 replies; 18+ messages in thread From: Adam Beneschan @ 2014-10-14 1:49 UTC (permalink / raw) On Monday, October 13, 2014 6:17:29 PM UTC-7, comp...@gmail.com wrote: > I understand in this example that calling tasks(main or environmental task) is passing id value to 2 tasks...In regarding to code below I have 2 question and was hoping someone can answer.... > > 1 with Ada.Text_IO, Ada.Integer_Text_IO; > 2 use Ada.Text_IO, Ada.Integer_Text_IO; > 3 > 4 procedure SomeProcedure is > 5 > 6 task type lamp is > 7 entry reset(id : Integer); > 8 end lamp; > 9 > 10 lamps : array (1..6) of lamp; > 11 > 12 task body lamp is > 13 begin > 14 Put_Line("Body of task lamp"); > 15 accept reset(id : Integer) do > 16 put("inside reset"); > 17 put(id); > 18 New_Line; > 19 end reset; > 20 delay 4.0; > 21 put("after accept"); > 22 end lamp; > 23 > 24 begin > 25 lamps(1).reset(id => 1); > 26 lamps(2).reset(id => 2); > 27 end SomeProcedure; > > 1. How would would these 2 tasks send message back to main? For example how would each of these two lamp tasks send "i received call to my acceptstatement"); An entry can have OUT (or IN OUT) parameters. If you want the "accept" to send something back to the task that calls the entry, define the entry with an OUT parameter, and set this parameter inside the ACCEPT statement. For a String, the problems with using a String as an OUT parameter are the same as for procedures--you can't really return a variable-length string this way. However, you can use Ada.Strings.Unbounded.Unbounded_String: entry reset(id : Integer; message : out Unbounded_String); and then in the accept statement: message := To_Unbounded_String("I received my call"); and then in the main: lamps(1).reset(id=>1, message=>The_Message); where The_Message is a variable or whatever. > 2. If there are some variables inside the body of the task to be saved and they might be different for each of these tasks how to save these values? You'll have to be clearer on what you mean by this. -- Adam ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 1:49 ` Adam Beneschan @ 2014-10-14 1:55 ` compguy45 2014-10-14 2:09 ` compguy45 2014-10-14 19:43 ` Shark8 2 siblings, 0 replies; 18+ messages in thread From: compguy45 @ 2014-10-14 1:55 UTC (permalink / raw) Doesnt have to be string at all. Integer is actually fine. Also probably slightly related what happens if each tasks have some variables inside body but those variables might or might not exactly have same values for each task. How would you retrieve these? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 1:49 ` Adam Beneschan 2014-10-14 1:55 ` compguy45 @ 2014-10-14 2:09 ` compguy45 2014-10-14 2:14 ` Adam Beneschan 2014-10-14 19:43 ` Shark8 2 siblings, 1 reply; 18+ messages in thread From: compguy45 @ 2014-10-14 2:09 UTC (permalink / raw) What I mean for example..... task t body is begin some statements; accept reset do i : Integer := some calculation b : Inetegr := some calculation end reset; end t; If I have array of these tasks some tasks might have different i and b. How do i save thse values one tasks completes accept block? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 2:09 ` compguy45 @ 2014-10-14 2:14 ` Adam Beneschan 2014-10-14 2:15 ` compguy45 0 siblings, 1 reply; 18+ messages in thread From: Adam Beneschan @ 2014-10-14 2:14 UTC (permalink / raw) On Monday, October 13, 2014 7:09:42 PM UTC-7, comp...@gmail.com wrote: > What I mean for example..... > > > > task t body is > > begin > > some statements; > > accept reset do > > i : Integer := some calculation > > b : Inetegr := some calculation > > end reset; > > end t; > > > > If I have array of these tasks some tasks might have different i and b. How do i save thse values one tasks completes accept block? If "I" and "B" are declared outside the ACCEPT statement, such as between the "task body" and the "begin", then when the ACCEPT statement is done, the variables will still have the values you assigned to them. Since they're declared in the task body, each task will have its own versions of these variables. task body t is i : integer; b : boolean; begin ... accept reset do i := something; b := something; end reset; ... now you can use i and b end t; Is that all you need? -- Adam ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 2:14 ` Adam Beneschan @ 2014-10-14 2:15 ` compguy45 2014-10-14 7:36 ` mockturtle 0 siblings, 1 reply; 18+ messages in thread From: compguy45 @ 2014-10-14 2:15 UTC (permalink / raw) i think so....i am just way over my head with this homework i have thats all....i will try to play with this ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 2:15 ` compguy45 @ 2014-10-14 7:36 ` mockturtle 2014-10-14 15:30 ` compguy45 0 siblings, 1 reply; 18+ messages in thread From: mockturtle @ 2014-10-14 7:36 UTC (permalink / raw) On Tuesday, October 14, 2014 4:15:11 AM UTC+2, comp...@gmail.com wrote: > i think so....i am just way over my head with this homework i have thats all....i will try to play with this Since it is not clear your actual doubt, let me also add this: if I and B are between "task body" and "begin" (as in the example by Adam) every task of type lamp (e.g., all the task in the array Lamps) has *its own copy* of B and I so when, say, Lamp(1) changes the value of B, the value of B in, say, Lamp(2) remains unchanged. I am not an expert in compilers, but I guess that every time a new task is started, the runtime allocates a block of memory to be associated to the new task. That block of memory will be used, e.g., to keep some "internal data" (e.g., the stack of the task (I guess)) and the "local variables" of the task such as B and I. Therefore, depending on the task the "name" B refers to different memory areas. I do not know if this can help with your doubt. Riccardo ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 7:36 ` mockturtle @ 2014-10-14 15:30 ` compguy45 2014-10-14 16:25 ` mockturtle 2014-10-14 20:33 ` Shark8 0 siblings, 2 replies; 18+ messages in thread From: compguy45 @ 2014-10-14 15:30 UTC (permalink / raw) how would you be able to recal these values... say i want to print b of task 1 and I of task 2 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 15:30 ` compguy45 @ 2014-10-14 16:25 ` mockturtle 2014-10-14 20:33 ` Shark8 1 sibling, 0 replies; 18+ messages in thread From: mockturtle @ 2014-10-14 16:25 UTC (permalink / raw) On Tuesday, October 14, 2014 5:30:58 PM UTC+2, comp...@gmail.com wrote: > how would you be able to recal these values... > > say i want to print b of task 1 > and I of task 2 The first solution that comes to my mind (and maybe the only one) is to provide your task with two entries: one to read the value of B and the other to read the value of I. Those entries would have a OUT parameter where the task will write the desired values. The accept statement would look something like accept Get_I(Result: out Integer) do Result := I; end Get_I; and you could use something like Lamps(2).Get_I(V); put_line(Integer'Image(V)); Of course, the accept statement causes a "synchronization" between the "main task" and task Lamps(2), so that when the execution reaches "Lamps(2).Get_I(V)" the main task will stop until Lamps(2) reaches the "accept" statement. If this synchronized behavior is undesired (you want to query I and B at any time, "asynchronously") I guess that the only solution is using a protected object. In this case things get a bit more complicated, but a possible solution could be this (disclaimer: I did not check the code) 1. You declare a protected type (call it "Protected_Buffer") with procedures like "Set_I", "Get_I", ... In this case Get_I and Get_B can be functions 2. When the lamp task starts it allocates a Protected_Buffer with new 3. The lamp task updates the values of B and I by using the methods Set_I and Set_B of the protected object 4. In order to allow the "main task" to access the values stored in the protected object, the lamp task needs to "export" the access to the allocated buffer. This can be done by providing the task with an entry similar to type Buffer_Access is access to Protected_Buffer; entry Get_Buffer_Access(acc : out Buffer_Access); 5. The main task first gets the access to the protected buffer by calling something like Lamps(2).Get_Buffer_Access(acc); then it can print the value of, say, I by calling Put_Line(Integer'Image(acc.Get_I)); A problem with this solution is that the main task could write the values of I and B by calling, say, acc.Set_I(42). If this is a problem, I think you can "wrap" the protected object inside a tagged type, make "Get" functions "public" while "Set" procedures "private." Lots of details left to the reader... :-) Riccardo ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 15:30 ` compguy45 2014-10-14 16:25 ` mockturtle @ 2014-10-14 20:33 ` Shark8 1 sibling, 0 replies; 18+ messages in thread From: Shark8 @ 2014-10-14 20:33 UTC (permalink / raw) On 10/14/2014 9:30 AM, compguy45@gmail.com wrote: > how would you be able to recal these values... > > say i want to print b of task 1 > and I of task 2 > Make another task that "knows about" your multiple tasks? type Task_ID is range 1..6; task Master_Task is entry Reset( ID : Task_ID ); end Master_Task; task body Master_Task is lamps : array (Task_ID) of lamp; begin [...] end Master_Task; ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 1:49 ` Adam Beneschan 2014-10-14 1:55 ` compguy45 2014-10-14 2:09 ` compguy45 @ 2014-10-14 19:43 ` Shark8 2014-10-14 20:42 ` Jeffrey Carter 2 siblings, 1 reply; 18+ messages in thread From: Shark8 @ 2014-10-14 19:43 UTC (permalink / raw) On 10/13/2014 7:49 PM, Adam Beneschan wrote: > For a String, the problems with using a String as an OUT parameter > are the same as for procedures--you can't really return a variable- > length string this way. Yes, but you can have two-entries: one returning the length and the second returning the data, so you could do something like: Function Get_String( X : The_Task ) return String is Length : Natural; begin X.Get_Length( Length ); Return Result : String(1..Length) do X.Get_Data( Result ); end return; end; ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 19:43 ` Shark8 @ 2014-10-14 20:42 ` Jeffrey Carter 2014-10-14 21:08 ` compguy45 0 siblings, 1 reply; 18+ messages in thread From: Jeffrey Carter @ 2014-10-14 20:42 UTC (permalink / raw) On 10/14/2014 12:43 PM, Shark8 wrote: > > Yes, but you can have two-entries: one returning the length and the second > returning the data, so you could do something like: > > Function Get_String( X : The_Task ) return String is > Length : Natural; > begin > X.Get_Length( Length ); > Return Result : String(1..Length) do > X.Get_Data( Result ); > end return; > end; Or do the Get_Line route, with 2 out parameters. At least familiar, if not great. -- Jeff Carter "If you think you got a nasty taunting this time, you ain't heard nothing yet!" Monty Python and the Holy Grail 23 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 20:42 ` Jeffrey Carter @ 2014-10-14 21:08 ` compguy45 2014-10-14 21:58 ` compguy45 ` (3 more replies) 0 siblings, 4 replies; 18+ messages in thread From: compguy45 @ 2014-10-14 21:08 UTC (permalink / raw) What i am trying to do is something like this....code from above... 3 4 procedure SomeProcedure is 5 6 task type lamp is 7 entry reset(id : Integer); 8 end lamp; 9 10 lamps : array (1..6) of lamp; 11 12 task body lamp is 13 begin 14 Put_Line("Body of task lamp"); 15 accept reset(id : Integer) do 16 put("inside reset"); 17 put(id); 18 New_Line; 19 end reset; 20 delay 4.0; 21 put("after accept"); 22 end lamp; 23 24 begin 25 lamps(1).reset(id => 1); 26 lamps(2).reset(id => 2); 27 end SomeProcedure; I am trying to figure out how to do following....have say main tasks call reset on say lamps(3).reset.... Then lamp(3) would call reset on lamps(2) and lamps(1) and wait....then someone lamps(2) and lamps(1) when they done with reset would somehow let lamp(3) know about it....Is this possible to do...? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 21:08 ` compguy45 @ 2014-10-14 21:58 ` compguy45 2014-10-14 23:03 ` Jeffrey Carter 2014-10-14 22:22 ` Shark8 ` (2 subsequent siblings) 3 siblings, 1 reply; 18+ messages in thread From: compguy45 @ 2014-10-14 21:58 UTC (permalink / raw) all i can think about here is reset being called within the task body but that doesnt make much sense ?? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 21:58 ` compguy45 @ 2014-10-14 23:03 ` Jeffrey Carter 0 siblings, 0 replies; 18+ messages in thread From: Jeffrey Carter @ 2014-10-14 23:03 UTC (permalink / raw) On 10/14/2014 02:58 PM, compguy45@gmail.com wrote: > all i can think about here is reset being called within the task body but that doesnt make much sense ?? Lamps is declared before the body of Lamp, so Lamp's body can see Lamps, and so can call any entry of any of the Lamps tasks. -- Jeff Carter "Alms for an ex-leper!" Monty Python's Life of Brian 75 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 21:08 ` compguy45 2014-10-14 21:58 ` compguy45 @ 2014-10-14 22:22 ` Shark8 2014-10-14 23:49 ` Dennis Lee Bieber 2014-10-15 1:07 ` Dennis Lee Bieber 3 siblings, 0 replies; 18+ messages in thread From: Shark8 @ 2014-10-14 22:22 UTC (permalink / raw) On 10/14/2014 3:08 PM, compguy45@gmail.com wrote: > What i am trying to do is something like this....code from above... > > 3 > 4 procedure SomeProcedure is > 5 > 6 task type lamp is > 7 entry reset(id : Integer); > 8 end lamp; > 9 > 10 lamps : array (1..6) of lamp; > 11 > 12 task body lamp is > 13 begin > 14 Put_Line("Body of task lamp"); > 15 accept reset(id : Integer) do > 16 put("inside reset"); > 17 put(id); > 18 New_Line; > 19 end reset; > 20 delay 4.0; > 21 put("after accept"); > 22 end lamp; > 23 > 24 begin > 25 lamps(1).reset(id => 1); > 26 lamps(2).reset(id => 2); > 27 end SomeProcedure; > > I am trying to figure out how to do following.... > have say main tasks call reset on say lamps(3).reset.... > Then lamp(3) would call reset on lamps(2) and lamps(1) and wait > then someone lamps(2) and lamps(1) when they done with reset > would somehow let lamp(3) know about it.... > >Is this possible to do...? Hm, I think it is -- but it's a bit on the convoluted side; when I saw your first post asking the same question I wrote up some code as a bit of a proof of concept. It kind-of works, I could probably get it a lot better if (A) I had more time, and/or (B) I had more experience w/ tasks. {Tasks are a great feature; I just haven't had occasion to use them all that often.} Anyway; here's what I got for making a network of tasks -- which is, essentially, what you're asking about: ----------------- -- NODES.ADS -- ----------------- Package Nodes is type Node_Interface is task interface; type Node_Access is access all Node_Interface'Class; type Node_List is array(Positive range <>) of Node_Access; Function "XOR" (Left : Node_List; Right : Positive) return Node_List is ( Left(Left'First..Natural'Pred(Right)) & Left(Natural'Succ(Right)..Left'Last) ); Function "XOR" (Left : Node_List; Right : Positive) return not null access Node_List is ( New Node_List'(Left XOR Right) ); Function Null_List return not null access Node_List is ( New Node_List'(2..1 => <>) ); Function Make_Network(Size : Natural) return not null access Node_List; task type Node( Neighbors : not null access Node_List ) is new Node_Interface with end Node; End Nodes; ----------------- -- NODES.ADB -- ----------------- with Ada.Task_Identification, Unchecked_Conversion, System.Address_To_Access_Conversions, System.Address_Image, Ada.Text_IO; Package body Nodes is Package Node_Pointers is new System.Address_To_Access_Conversions(Object => Node); Function Convert is new Unchecked_Conversion (Source => Node_Pointers.Object_Pointer, Target => Node_Access); Function Convert( A : System.Address ) return Node_Access is ( Convert(Node_Pointers.To_Pointer( A )) ); task body Node is use Ada.Task_Identification, System; New_Line : Constant String:= ASCII.CR & ASCII.LF; Function Line_1 return String is ("Task " & Image(Current_Task) & ": " & Neighbors'Length'Img & ASCII.HT & Address_Image(Node'Access.All'Address) & New_Line ); Function Line_2( Input : Node_List ) return String is (if Input'Length = 0 then "" else ASCII.HT & Address_Image(Input(Input'First).All'Address) & New_Line & Line_2( Input(Input'First+1..Input'Last) ) ); Function Line_2 return String is ( Line_2(Node.Neighbors.All) ); Function Line_3 return String is ("Done."); begin Ada.Text_IO.Put_Line( Line_1 & Line_2 & Line_3 ); null; end Node; Function Make_Network(Size : Natural) return Node_List; Function Make_Network(Size : Natural) return not null access Node_List is ( New Node_List'(Make_Network(size)) ); Function Make_Network(Size : Natural) return Node_List is subtype Full_Range is Positive Range 1..Size; subtype Full_Node_List is Node_List(Full_Range); subtype Constrained_List is Node_List(1..Size-1); subtype Constrained_Node is Node( Neighbors => new Constrained_List ); Type Task_Array is array (Full_Range) of aliased Constrained_Node; Package TAP is new System.Address_To_Access_Conversions(Task_Array); Generic Package Incrementation is Procedure Increment; Function Increment return Full_Range; End Incrementation; Package body Incrementation is Index : Full_Range:= Full_Range'First; Function Increment return Full_Range is begin Return Result : constant Full_Range:= Index do Increment; end return; end Increment; Procedure Increment is begin Index:= (if Index = Full_Range'Last then Full_Range'First else Full_Range'Succ( Index )); end Increment; end Incrementation; Function Make_Nodes(Task_List : out Task_Array) return Node_List is Package Inc is new Incrementation; Use Inc; List : constant Full_Node_List:= ( others => Convert(Task_List(Increment)'Address) ); Function Get_List return Constrained_List is begin Return Result : Constrained_List:= List xor Increment; end; List_List : constant Array(Full_Range) of Constrained_List:= (others => Get_List); Function Make_Tasks( List : Full_Node_List ) return Task_Array is Subtype Actual_Node is Node(Neighbors => New Node_List'(List_List(Increment))); Type Task_Cluster is Array(Full_Range) of Actual_Node; Function Tasks return Task_Cluster is begin Return result: Task_Cluster; end; Function Convert is new Unchecked_Conversion (Source => Task_Cluster, Target => Task_Array); begin Return Convert( Tasks ); end Make_Tasks; Begin return Result : Full_Node_List := List do declare pragma Warnings( Off ); K : Task_Array:= Make_Tasks(result) with Address => Task_List'Address; pragma Warnings( On ); begin null; end; -- for Index in Full_Range loop -- declare -- N : Node renames Task_List(Index); -- A : constant System.Address := N'Address; -- pragma Warnings( Off ); -- T : Node(Neighbors => New Node_List'(List_List(Index))) -- with Address => A; -- pragma Warnings( On ); -- begin -- null; -- end; -- end loop; end return; End Make_Nodes; Tasks : aliased Task_Array with Import; begin Return Make_Nodes(Tasks); end Make_Network; End Nodes; ---------------- -- TEST.ADB -- ---------------- With Nodes; procedure Test is use all type Nodes.Node_List; Children_1 : not null access Nodes.Node_List:= Nodes.Make_Network(3); Master : Nodes.Node( Neighbors => Children_1 --Nodes.Null_List ); begin null; end Test; ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 21:08 ` compguy45 2014-10-14 21:58 ` compguy45 2014-10-14 22:22 ` Shark8 @ 2014-10-14 23:49 ` Dennis Lee Bieber 2014-10-15 1:07 ` Dennis Lee Bieber 3 siblings, 0 replies; 18+ messages in thread From: Dennis Lee Bieber @ 2014-10-14 23:49 UTC (permalink / raw) On Tue, 14 Oct 2014 14:08:08 -0700 (PDT), compguy45@gmail.com declaimed the following: > 15 accept reset(id : Integer) do > 23 > 24 begin > 25 lamps(1).reset(id => 1); Note that this scheme has nothing that prevents one doing lamps(1).reset(id => 3); You'd be better off with something where the tasks first wait for an initialization rendezvous. (PSEUDO_CODE) for i in lamps'range loop lamp(i).init(id => i); end loop; Then later you rendezvous on your reset with just lamp(1).reset; as the lamp(1) task already knows its id from the init() point. >I am trying to figure out how to do following....have say main tasks call reset on say lamps(3).reset.... >Then lamp(3) would call reset on lamps(2) and lamps(1) and wait....then someone lamps(2) and lamps(1) when they done with reset would somehow let lamp(3) know about it....Is this possible to do...? You need to develop a data structure of some sort in which you TELL each task which tasks are subordinate to it... Which likely means using access to task. And a rendezvous doesn't continue until the accept block exits, so if all action takes place in the accepts there is no explicit need to wait. accept reset do subordinate(1).reset; subordinate(2).reset; end reset; Whereas if you had accept reset do Null; end reset; subordinate(1).reset; subordinate(2).reset; the task would wait for a reset invocation, but the rendezvous would end, letting the invoker continue -- and then would do the subordinate task resets. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: passing messages between the tasks 2014-10-14 21:08 ` compguy45 ` (2 preceding siblings ...) 2014-10-14 23:49 ` Dennis Lee Bieber @ 2014-10-15 1:07 ` Dennis Lee Bieber 3 siblings, 0 replies; 18+ messages in thread From: Dennis Lee Bieber @ 2014-10-15 1:07 UTC (permalink / raw) On Tue, 14 Oct 2014 14:08:08 -0700 (PDT), compguy45@gmail.com declaimed the following: >I am trying to figure out how to do following....have say main tasks call reset on say lamps(3).reset.... >Then lamp(3) would call reset on lamps(2) and lamps(1) and wait....then someone lamps(2) and lamps(1) when they done with reset would somehow let lamp(3) know about it....Is this possible to do...? I do hate given (nearly) full solutions -- but this has gone on a few days too long... So I present... A Working Example (took about 20 minutes to write -- and maybe 10 more to refine the output to where it makes more sense) -=-=-=-=-=- with Ada.Text_IO; use Ada.Text_Io; procedure Taskchain is type Lamp_T; type Lamp_Access_T is access Lamp_T; task type Lamp_T is entry Init (Id : Integer; Left : Lamp_Access_T; Right : Lamp_Access_T); entry Toggle (Level : Integer); entry Shutdown; end Lamp_T; Lamps : array (1 .. 6) of Lamp_Access_T; task body Lamp_T is MyLeft : Lamp_Access_T := null; MyRight : Lamp_Access_T := null; MyId : Integer; State : Boolean := False; begin accept Init (Id : Integer; Left : Lamp_Access_T; Right : Lamp_Access_T) do MyId := Id; MyLeft := Left; MyRight := Right; end Init; Put_Line ("Init Level " & Integer'Image (0) & " Lamp " & Integer'Image (MyId) & " is now " & Boolean'Image (State)); loop select accept Toggle (Level : Integer) do State := not State; Put_Line ("Toggle Level " & Integer'Image (Level) & " Lamp " & Integer'Image (MyId) & " is now " & Boolean'Image (State)); if MyLeft /= null then MyLeft.all.Toggle (Level + 1); end if; if MyRight /= null then MyRight.all.Toggle (Level + 1); end if; end Toggle; or accept Shutdown do Put_Line ("Lamp " & Integer'Image (MyId) & " Shutting Down"); end Shutdown; exit; end select; end loop; end Lamp_T; begin Lamps (6) := new Lamp_T; Lamps (6).Init (Id => 6, Left => null, Right => null); Lamps (5) := new Lamp_T; Lamps (5).Init (Id => 5, Left => null, Right => null); Lamps (4) := new Lamp_T; Lamps (4).Init (Id => 4, Left => Lamps (5), Right => Lamps (6)); Lamps (3) := new Lamp_T; Lamps (3).Init (Id => 3, Left => Lamps (4), Right => null); Lamps (2) := new Lamp_T; Lamps (2).Init (Id => 2, Left => null, Right => null); Lamps (1) := new Lamp_T; Lamps (1).Init (Id => 1, Left => Lamps (2), Right => Lamps (3)); Lamps (6).all.Toggle (0); New_Line; Lamps (4).all.Toggle (0); New_Line; Lamps (2).all.Toggle (0); New_Line; Lamps (1).all.Toggle (0); New_Line; Lamps (1).all.Toggle (0); New_Line; Lamps (3).all.Toggle (0); New_Line; Lamps (1).all.Toggle (0); New_Line; for I in Lamps'Range loop Lamps (I).all.Shutdown; end loop; end Taskchain; -=-=-=-=-=- Init Level 0 Lamp 6 is now FALSE Init Level 0 Lamp 5 is now FALSE Init Level 0 Lamp 4 is now FALSE Init Level 0 Lamp 3 is now FALSE Init Level 0 Lamp 2 is now FALSE Init Level 0 Lamp 1 is now FALSE Toggle Level 0 Lamp 6 is now TRUE Toggle Level 0 Lamp 4 is now TRUE Toggle Level 1 Lamp 5 is now TRUE Toggle Level 1 Lamp 6 is now FALSE Toggle Level 0 Lamp 2 is now TRUE Toggle Level 0 Lamp 1 is now TRUE Toggle Level 1 Lamp 2 is now FALSE Toggle Level 1 Lamp 3 is now TRUE Toggle Level 2 Lamp 4 is now FALSE Toggle Level 3 Lamp 5 is now FALSE Toggle Level 3 Lamp 6 is now TRUE Toggle Level 0 Lamp 1 is now FALSE Toggle Level 1 Lamp 2 is now TRUE Toggle Level 1 Lamp 3 is now FALSE Toggle Level 2 Lamp 4 is now TRUE Toggle Level 3 Lamp 5 is now TRUE Toggle Level 3 Lamp 6 is now FALSE Toggle Level 0 Lamp 3 is now TRUE Toggle Level 1 Lamp 4 is now FALSE Toggle Level 2 Lamp 5 is now FALSE Toggle Level 2 Lamp 6 is now TRUE Toggle Level 0 Lamp 1 is now TRUE Toggle Level 1 Lamp 2 is now FALSE Toggle Level 1 Lamp 3 is now FALSE Toggle Level 2 Lamp 4 is now TRUE Toggle Level 3 Lamp 5 is now TRUE Toggle Level 3 Lamp 6 is now FALSE Lamp 1 Shutting Down Lamp 2 Shutting Down Lamp 3 Shutting Down Lamp 4 Shutting Down Lamp 5 Shutting Down Lamp 6 Shutting Down -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2014-10-15 1:07 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-10-14 1:17 passing messages between the tasks compguy45 2014-10-14 1:49 ` Adam Beneschan 2014-10-14 1:55 ` compguy45 2014-10-14 2:09 ` compguy45 2014-10-14 2:14 ` Adam Beneschan 2014-10-14 2:15 ` compguy45 2014-10-14 7:36 ` mockturtle 2014-10-14 15:30 ` compguy45 2014-10-14 16:25 ` mockturtle 2014-10-14 20:33 ` Shark8 2014-10-14 19:43 ` Shark8 2014-10-14 20:42 ` Jeffrey Carter 2014-10-14 21:08 ` compguy45 2014-10-14 21:58 ` compguy45 2014-10-14 23:03 ` Jeffrey Carter 2014-10-14 22:22 ` Shark8 2014-10-14 23:49 ` Dennis Lee Bieber 2014-10-15 1:07 ` Dennis Lee Bieber
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox