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