comp.lang.ada
 help / color / mirror / Atom feed
* 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