comp.lang.ada
 help / color / mirror / Atom feed
* Activating tasks at global scope
@ 1993-03-10  3:32 Scott Meyers
  1993-03-10 17:11 ` Robert I. Eachus
  1993-03-11  2:51 ` Michael Feldman
  0 siblings, 2 replies; 6+ messages in thread
From: Scott Meyers @ 1993-03-10  3:32 UTC (permalink / raw)


The code below implements a producer-consumer system containing one
producing task, two consuming tasks, and a bounded buffer task.  I am only
interested in the tasking interactions, so I've omitted the actual buffer
manipulations.  This code works fine under the Ada/ED compiler.  However, I
would prefer to put the tasks at global scope rather than nest them inside
the producer_consumer procedure.  I tried to do this by putting each task
inside a package, but then I couldn't figure out how to activate the tasks
when producer_consumer was invoked.  What I'd like is an architecture where
the tasks are automatically started before or at the same time the the main
subprogram is invoked.

If I've done anything particularly gross, feel free to comment
appropriately.  Nobody here knows Ada, so I put this together by copying
fairly liberally from Ben-Ari's book, "Principles of Concurrent and
Distributed Programming."

Thanks,

Scott


with Text_IO;
use Text_IO;

procedure producer_consumer is
  task Buffer is
    entry insert(item: in Integer);
    entry remove(item: out Integer);
  end Buffer;

  task body Buffer is
    count: Integer := 0;

    begin
      loop
        select when count < 10 =>
          accept insert(item: in Integer) do
            -- insert item into the buffer
            null;
          end insert;
          count := count + 1;

        or when count > 0 =>
          accept remove(item: out Integer) do
            -- remove an object from the buffer and assign it to item
            null;
          end remove;
          count := count - 1;
        end select;

      end loop;
    end Buffer;

  task Producer;
  task body Producer is
    n: integer;
    
    begin
      loop
        -- give n an appropriate value
        Buffer.insert(n);
      end loop;
  end Producer;

  task Consumer1;
  task body Consumer1 is
    n: integer;
    
    begin
      loop
        Buffer.remove(n);
        -- do something with n
      end loop;
  end Consumer1;

  task Consumer2;
  task body Consumer2 is
    n: integer;
    
    begin
      loop
        Buffer.remove(n);
        -- do something with n
      end loop;
  end Consumer2;


  begin
    null;
  end;

-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Activating tasks at global scope
  1993-03-10  3:32 Activating tasks at global scope Scott Meyers
@ 1993-03-10 17:11 ` Robert I. Eachus
  1993-03-11  3:56   ` Scott Meyers
  1993-03-11  2:51 ` Michael Feldman
  1 sibling, 1 reply; 6+ messages in thread
From: Robert I. Eachus @ 1993-03-10 17:11 UTC (permalink / raw)


In article <1993Mar10.033256.24718@cs.brown.edu> sdm@cs.brown.edu (Scott Meyers) writes:

  > The code below implements a producer-consumer system containing one
  > producing task, two consuming tasks, and a bounded buffer task.  I am only
  > interested in the tasking interactions, so I've omitted the actual buffer
  > manipulations.  This code works fine under the Ada/ED compiler.  However, I
  > would prefer to put the tasks at global scope rather than nest them inside
  > the producer_consumer procedure.  I tried to do this by putting each task
  > inside a package, but then I couldn't figure out how to activate the tasks
  > when producer_consumer was invoked.  What I'd like is an architecture where
  > the tasks are automatically started before or at the same time the the main
  > subprogram is invoked.

  You were doing fine, but got bitten by a very subtle feature of Ada.
The tasks were all created and elaborated before the main program
executed, but then the main program immediately exited.  The language
reference manual leaves it unspecifed what happens to library tasks in
such a situation, but most implementations now terminate them all if
they are quiescent.  So your tasks disappeared from view before they
could act.

   In any case try hanging your main program, either by putting in a
delay statement or by waiting for input...the elegent final version
should have a clean way of terminating the program, but this will do
for testing.

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Activating tasks at global scope
  1993-03-10  3:32 Activating tasks at global scope Scott Meyers
  1993-03-10 17:11 ` Robert I. Eachus
@ 1993-03-11  2:51 ` Michael Feldman
  1 sibling, 0 replies; 6+ messages in thread
From: Michael Feldman @ 1993-03-11  2:51 UTC (permalink / raw)


In article <1993Mar10.033256.24718@cs.brown.edu> sdm@cs.brown.edu (Scott Meyers) writes:
>The code below implements a producer-consumer system containing one
>producing task, two consuming tasks, and a bounded buffer task.  I am only
>interested in the tasking interactions, so I've omitted the actual buffer
>manipulations.  This code works fine under the Ada/ED compiler.  However, I
>would prefer to put the tasks at global scope rather than nest them inside
>the producer_consumer procedure.  I tried to do this by putting each task
>inside a package, but then I couldn't figure out how to activate the tasks
>when producer_consumer was invoked.  What I'd like is an architecture where
>the tasks are automatically started before or at the same time the the main
>subprogram is invoked.
>
Put the tasks in a package. Attached is a comparable example, though a bit
more involved than yours. It's a re-post of my Portable Diners Kit, which
is now being distributed as one of the Ada/Ed demos, and also appears in
the Ada Quality & Style Guide. Have a look and have fun.

The various compilation units can be separated or left in one file; they
appear in a correct compilation order, so one compiler invocation will do
it. Link and run "diners".

Mike Feldman
---- cut here ----
--::::::::::
--io_libs.ada
--::::::::::
-- Precompiled instantiations of Integer_IO and
-- Float_IO for the predefined Integer and Float types
 
WITH Text_IO;
PACKAGE My_Int_IO IS
  NEW Text_IO.Integer_IO (Num => Integer);
 
WITH Text_IO;
PACKAGE My_Flt_IO IS
  NEW Text_IO.Float_IO   (Num => Float);
--::::::::::
--random.ads
--::::::::::
PACKAGE Random IS
 
-- Simple pseudo-random number generator package.
-- Adapated from the Ada literature by
-- Michael B. Feldman, The George Washington University, November 1990.
 
  PROCEDURE Set_Seed (N : Positive);
 
  FUNCTION  Unit_Random RETURN Float;
 
    --returns a float >=0.0 and <1.0
 
  FUNCTION  Random_Int (N : Positive) RETURN Positive;
 
    --return a random integer in the range 1..N
 
END Random;
--::::::::::
--chop.ads
--::::::::::
PACKAGE Chop IS
 
  TASK TYPE Stick IS
    ENTRY Pick_Up;
    ENTRY Put_Down;
  END Stick;
 
END Chop;
--::::::::::
--phil.ads
--::::::::::
PACKAGE Phil IS
  
  TASK TYPE Philosopher IS
    
    ENTRY Come_To_Life (My_ID :      Positive; 
                        Chopstick1 : Positive;
                        Chopstick2 : Positive);
 
  END Philosopher;
 
  TYPE States IS (Breathing, Thinking, Eating, Done_Eating,
                    Got_One_Stick, Got_Other_Stick);
 
END Phil;
--::::::::::
--room.ads
--::::::::::
WITH Chop;
WITH Phil;
PACKAGE Room IS
 
  Table_Size: CONSTANT := 5;
  SUBTYPE Table_Type IS Positive RANGE 1..Table_Size;
 
  Sticks:     ARRAY(Table_Type) OF Chop.Stick;
 
  TASK Head_Waiter IS
    ENTRY Open_The_Room;
    ENTRY Report_State(Which_Phil: Table_Type;
                       State: Phil.States;
                       How_Long: Natural := 0);
  END Head_Waiter;
 
END Room;
--::::::::::
--diners.ada
--::::::::::
WITH Room;
PROCEDURE Diners IS
 
BEGIN
  Room.Head_Waiter.Open_The_Room;
  LOOP
    DELAY 20.0;
  END LOOP;
END Diners;
--::::::::::
--random.adb
--::::::::::
WITH Calendar;
USE  Calendar;
 
PACKAGE BODY Random IS
 
-- Body of random number generator package.
-- Adapted from the Ada literature by
-- Michael B. Feldman, The George Washington University, November 1990.
 
  Modulus      : CONSTANT := 9317;
 
  TYPE Int_16 IS RANGE - 2 ** 15 .. 2 ** 15 - 1;
 
  TYPE Int_32 IS RANGE - 2 ** 31 .. 2 ** 31 - 1;
 
  SUBTYPE Seed_Range IS Int_16 RANGE 0 .. (Modulus - 1);
 
  Seed,
  Default_Seed : Seed_Range;
 
  PROCEDURE Set_Seed (N : Positive) IS SEPARATE;
 
  FUNCTION  Unit_Random RETURN Float IS SEPARATE;
 
  FUNCTION  Random_Int (N : Positive) RETURN Positive IS SEPARATE;
BEGIN
  Default_Seed := Int_16 (Int_32 (Seconds (Clock)) MOD Modulus);
  Seed := Default_Seed;
END Random;
 
SEPARATE (Random)
 
PROCEDURE Set_Seed (N : Positive) IS
BEGIN
  Seed := Seed_Range (N);
END Set_Seed;
 
SEPARATE (Random)
 
FUNCTION  Unit_Random RETURN Float IS
  Multiplier : CONSTANT := 421;
  Increment  : CONSTANT := 2073;
  Result     : Float;
BEGIN
  Seed := (Multiplier * Seed + Increment) MOD Modulus;
  Result := Float (Seed) / Float (Modulus);
  RETURN Result;
EXCEPTION
  WHEN Constraint_Error | Numeric_Error =>
    Seed := Int_16 ((Multiplier * Int_32 (Seed) + Increment) MOD Modulus);
    Result := Float (Seed) / Float (Modulus);
    RETURN Result;
 
END Unit_Random;
 
SEPARATE (Random)
 
FUNCTION  Random_Int (N : Positive) RETURN Positive IS
  Result : Integer RANGE 1 .. N;
BEGIN
  Result := Integer (Float (N) * Unit_Random + 0.5);
  RETURN Result;
EXCEPTION
  WHEN Constraint_Error | Numeric_Error =>
    RETURN 1;
 
END Random_Int;
--::::::::::
--chop.adb
--::::::::::
PACKAGE BODY Chop IS
 
  TASK BODY Stick IS
 
  BEGIN
    
    LOOP
      SELECT
        ACCEPT Pick_Up;
        ACCEPT Put_Down;
      OR
        TERMINATE;
      END SELECT;
    END LOOP;
 
  END Stick;
 
END Chop;
--::::::::::
--phil.adb
--::::::::::
WITH Room;
WITH Random;
PACKAGE BODY Phil IS
  
  TASK BODY Philosopher IS
 
    Who_Am_I   : Positive;
    First_Grab : Positive;
    Second_Grab: Positive;
    Meal_Time  : Natural;
    Think_Time : Natural;
    
  BEGIN
    ACCEPT Come_To_Life (My_ID :     Positive; 
                        Chopstick1 : Positive;
                        Chopstick2 : Positive) DO
      Who_Am_I    := My_ID;
      First_Grab  := Chopstick1;
      Second_Grab := Chopstick2;
 
    END Come_To_Life;
 
    Room.Head_Waiter.Report_State(Who_Am_I, Breathing);
 
    LOOP
 
      Room.Sticks(First_Grab).Pick_Up;
      Room.Head_Waiter.Report_State(Who_Am_I, Got_One_Stick, First_Grab);
 
      Room.Sticks(Second_Grab).Pick_Up;
      Room.Head_Waiter.Report_State(Who_Am_I, Got_Other_Stick, Second_Grab);
 
      Meal_Time := Random.Random_Int(10);
      Room.Head_Waiter.Report_State(Who_Am_I, Eating, Meal_Time);
 
      DELAY Duration(Meal_Time);
      Room.Head_Waiter.Report_State(Who_Am_I, Done_Eating);
 
      Room.Sticks(First_Grab).Put_Down;
      Room.Sticks(Second_Grab).Put_Down;
 
      Think_Time := Random.Random_Int(10);
      Room.Head_Waiter.Report_State(Who_Am_I, Thinking, Think_Time);
      DELAY Duration(Think_Time);
 
    END LOOP;
 
  END Philosopher;
 
END Phil;
--::::::::::
--roomline.adb
--::::::::::
WITH Text_IO;
WITH Chop;
WITH Phil;
WITH Calendar;
PRAGMA Elaborate(Phil);
PACKAGE BODY Room IS
 
-- A line-oriented version of the Room package, for line-oriented
-- terminals like IBM 3270's where the user cannot do ASCII screen control.
-- This is the only file in the dining philosophers system that needs
-- changing to use in a line-oriented environment.
-- Michael B. Feldman, The George Washington University, November 1990.
 
 
  Phils:      ARRAY(Table_Type) OF Phil.Philosopher;
 
  TYPE Phil_Names IS (Dijkstra, Texel, Booch, Ichbiah, Stroustrup);
 
  TASK BODY Head_Waiter IS
 
    T : Integer;
    Start_Time: Calendar.Time;
    Phil_Names: CONSTANT ARRAY(1..5) OF String(1..18) :=
     ("Eddy Dijkstra     ",
      "Putnam Texel      ",
      "Grady Booch       ",
      "Jean Ichbiah      ",
      "Bjarne Stroustrup ");
    Blanks : CONSTANT String := "     ";
 
  BEGIN
 
    ACCEPT Open_The_Room;
    Start_Time := Calendar.Clock;
 
    Phils(1).Come_To_Life(1,1,2);
    Phils(3).Come_To_Life(3,3,4);
    Phils(2).Come_To_Life(2,2,3);
    Phils(5).Come_To_Life(5,1,5);
    Phils(4).Come_To_Life(4,4,5);
 
    LOOP
      SELECT
        ACCEPT Report_State(Which_Phil: Table_Type;
                         State: Phil.States;
                         How_Long: Natural := 0) DO
          T := Integer(Calendar."-"(Calendar.Clock,Start_Time));
          Text_IO.Put( "T=" & Integer'Image(T) & " "
            & Blanks(1..Which_Phil) & Phil_Names(Which_Phil));
 
          CASE State IS
 
            WHEN Phil.Breathing =>
              Text_IO.Put("Breathing");
            WHEN Phil.Thinking =>
              Text_IO.Put( "Thinking"
                         & Integer'Image(How_Long)
                         & " seconds.");
            WHEN Phil.Eating =>
              Text_IO.Put( "Eating"
                         & Integer'Image(How_Long)
                         & " seconds.");
            WHEN Phil.Done_Eating =>
              Text_IO.Put("Yum-yum (burp)");
            WHEN Phil.Got_One_Stick =>
              Text_IO.Put( "First chopstick"
                          & Integer'Image(How_Long));
            WHEN Phil.Got_Other_Stick =>
              Text_IO.Put( "Second chopstick"
                          & Integer'Image(How_Long));
 
          END CASE;
          Text_IO.New_Line;
 
         END Report_State;
        OR
          TERMINATE;
        END SELECT;
 
      END LOOP;
 
    END Head_Waiter;
 
END Room;



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Activating tasks at global scope
  1993-03-10 17:11 ` Robert I. Eachus
@ 1993-03-11  3:56   ` Scott Meyers
  1993-03-11 17:57     ` Dave Collard x7468
  0 siblings, 1 reply; 6+ messages in thread
From: Scott Meyers @ 1993-03-11  3:56 UTC (permalink / raw)


In article <EACHUS.93Mar10121115@goldfinger.mitre.org> eachus@goldfinger.mitre.org (Robert I. Eachus) writes:
|   You were doing fine, but got bitten by a very subtle feature of Ada.
| The tasks were all created and elaborated before the main program
| executed, but then the main program immediately exited.  The language
| reference manual leaves it unspecifed what happens to library tasks in
| such a situation, but most implementations now terminate them all if
| they are quiescent.  So your tasks disappeared from view before they
| could act.
| 
|    In any case try hanging your main program, either by putting in a
| delay statement or by waiting for input...the elegent final version
| should have a clean way of terminating the program, but this will do
| for testing.

I tried to follow this advice, but none of the tasks appears to run;
certainly the output statements in their initialization blocks are never
executed.  I've appended the full program below, and I'd appreciate it if
somebody could help me figure out what's wrong.  Trust me when I tell you
I've tried to solve this problem myself.  (I had quite a lovely time
determining that the behavior of the Ada/Ed compiler is dependent in part
on the name of the file containing the source, and I don't mean the file
extensions.  In particular, the compiler generates an internal error on a
whole host of file names.  Names containing numbers seem to be particularly
offensive to it...)

Thanks for your help,

Scott




with Text_IO;
use Text_IO;

package Buffer_Package is
  task Buffer is
    entry insert(item: in Integer);
    entry remove(item: out Integer);
  end Buffer;
end Buffer_Package;

package body Buffer_Package is
  task body Buffer is
    count: Integer := 0;

    begin
      loop
        select when count < 10 =>
          accept insert(item: in Integer) do
            -- insert item into the buffer
            PUT_LINE("ACCEPTING AN INSERTION");
            null;
          end insert;
          count := count + 1;

        or when count > 0 =>
          accept remove(item: out Integer) do
            -- remove an object from the buffer and assign it to item
            PUT_LINE("ACCEPTING A REMOVAL");
            null;
          end remove;
          count := count - 1;
        end select;

      end loop;
    end Buffer;
    
begin
  PUT_LINE("STARTING BUFFER_PACKAGE"); 
end Buffer_Package;

--------------------------------------------------------------------------

with Text_IO;
use Text_IO;
with Buffer_Package;
use Buffer_Package;

package Producer_Package is
  task Producer;
end Producer_Package;

package body Producer_Package is
  task body Producer is
    n: integer;
    
    begin
      loop
        -- give n an appropriate value
        PUT_LINE("INSERTING");
        Buffer.insert(n);
      end loop;
  end Producer;

begin
  PUT_LINE("STARTING PRODUCER_PACKAGE"); 
end Producer_Package;

--------------------------------------------------------------------------

with Text_IO;
use Text_IO;
with Buffer_Package;
use Buffer_Package;

package Consumer1_Package is
  task Consumer1;
end Consumer1_Package;

package body Consumer1_Package is
  task body Consumer1 is
    n: integer;
    
    begin
      loop
        PUT_LINE("REMOVING2");
        Buffer.remove(n);
        -- do something with n
      end loop;
  end Consumer1;

begin
  PUT_LINE("STARTING CONSUMER1_PACKAGE"); 
end Consumer1_Package;

--------------------------------------------------------------------------

with Text_IO;
use Text_IO;
with Buffer_Package;
use Buffer_Package;

package Consumer2_Package is
  task Consumer2;
end Consumer2_Package;

package body Consumer2_Package is
  task body Consumer2 is
    n: integer;
    
    begin
      loop
        PUT_LINE("REMOVING2");
        Buffer.remove(n);
        -- do something with n
      end loop;
  end Consumer2;

begin
  PUT_LINE("STARTING CONSUMER2_PACKAGE"); 
end Consumer2_Package;

--------------------------------------------------------------------------

with Text_IO;
use Text_IO;

procedure producer_consumer is
begin
  PUT_LINE("STARING DELAY...");
  delay 5.0;
  PUT_LINE("DONE.");
end producer_consumer;


-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Activating tasks at global scope
  1993-03-11  3:56   ` Scott Meyers
@ 1993-03-11 17:57     ` Dave Collard x7468
  0 siblings, 0 replies; 6+ messages in thread
From: Dave Collard x7468 @ 1993-03-11 17:57 UTC (permalink / raw)


>with Text_IO;
>use Text_IO;
>package Buffer_Package is
  ...
>end Buffer_Package;

>package body Buffer_Package is
>  task body Buffer is
>    end Buffer;
>    
>begin
>  PUT_LINE("STARTING BUFFER_PACKAGE"); 
>end Buffer_Package;

>with Text_IO;
>use Text_IO;
>with Buffer_Package;
>use Buffer_Package;
>package Producer_Package is
>  task Producer;
>end Producer_Package;

>package body Producer_Package is
>  task body Producer is
>  end Producer;

>begin
>  PUT_LINE("STARTING PRODUCER_PACKAGE"); 
>end Producer_Package;

>with Text_IO;
>use Text_IO;
>with Buffer_Package;
>use Buffer_Package;
>package Consumer1_Package is
>  task Consumer1;
>end Consumer1_Package;

>package body Consumer1_Package is
>  task body Consumer1 is
>  end Consumer1;

>begin
>  PUT_LINE("STARTING CONSUMER1_PACKAGE"); 
>end Consumer1_Package;

>with Text_IO;
>use Text_IO;
>with Buffer_Package;
>use Buffer_Package;
>package Consumer2_Package is
>  task Consumer2;
>end Consumer2_Package;

>package body Consumer2_Package is
>  task body Consumer2 is
>  end Consumer2;

>begin
>  PUT_LINE("STARTING CONSUMER2_PACKAGE"); 
>end Consumer2_Package;


>with Text_IO;
>use Text_IO;

-- Perhaps you need to add a few with statements here!  When
-- you link producer_consumer, the only thing you are linking
-- with is Text_IO!  Try adding:
with Buffer_Package;
with Producer_Package;
with Consumer1_Package;
with Consumer2_Package;
>procedure producer_consumer is
>begin
>  PUT_LINE("STARING DELAY...");
>  delay 5.0;
>  PUT_LINE("DONE.");
>end producer_consumer;

--Thor
dlc@ddsdx2.jhuapl.edu
collard@capsrv.jhuapl.edu



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re:  Activating tasks at Global Scope
@ 1993-03-15 14:58 Cheryl Marquis
  0 siblings, 0 replies; 6+ messages in thread
From: Cheryl Marquis @ 1993-03-15 14:58 UTC (permalink / raw)


>The code below implements a producer-consumer system containing one
>producing task, two consuming tasks, and a bounded buffer task.  I am only
>interested in the tasking interactions, so I've omitted the actual buffer
>manipulations.  This code works fine under the Ada/ED compiler.  However, I
>would prefer to put the tasks at global scope rather than nest them inside
>the producer_consumer procedure.  I tried to do this by putting each task
>inside a package, but then I couldn't figure out how to activate the tasks
>when producer_consumer was invoked.  What I'd like is an architecture where
>the tasks are automatically started before or at the same time the the main
>subprogram is invoked.

>If I've done anything particularly gross, feel free to comment
>appropriately.  Nobody here knows Ada, so I put this together by copying
>fairly liberally from Ben-Ari's book, "Principles of Concurrent and
>Distributed Programming."

>Thanks,

>Scott

Scott as I see it you have two package options that will allow you a more
elegant start up without using delays.

They look basically alike the only difference is where the starting up of
the task is done.  Below is some code that I hope will help you.


with Text_IO;
use Text_IO;

package My_Task_Stuff is
  task Buffer is
--**** This entry provides a means of controlled task 
--     start ups.  Look at body to see how this works
    entry Start_Up;       
--****
    entry insert(item: in Integer);
    entry remove(item: out Integer);
--**** This entry provides a means of controlled task 
--     shut downs.  Look at body to see how this works
    entry Shut_Down;       
--****
  end Buffer;


  task Producer is
--**** This entry provides a means of controlled task 
--     start ups.  Look at body to see how this works
    entry Start_Up;       
--****
--**** This entry provides a means of controlled task 
--     shut downs.  Look at body to see how this works
    entry Shut_Down;       
--****


  task Consumer1;
--**** This entry provides a means of controlled task 
--     start ups.  Look at body to see how this works
    entry Start_Up;       
--****
--**** This entry provides a means of controlled task 
--     shut downs.  Look at body to see how this works
    entry Shut_Down;       
--****

  task Consumer2;
--**** This entry provides a means of controlled task 
--     start ups.  Look at body to see how this works
    entry Start_Up;       
--****
--**** This entry provides a means of controlled task 
--     shut downs.  Look at body to see how this works
    entry Shut_Down;       
--****


end My_Task_Stuff;


package body My_Task_Stuff is

  task body Buffer is
    count: Integer := 0;

    begin
--**** put Start up before loop.  Task will have to
--     wait here until the start up is called.

      accept Start_Up;
      -- any initializing can be done here also

      loop
        select when count < 10 =>
          accept insert(item: in Integer) do
            -- insert item into the buffer
            null;
          end insert;
          count := count + 1;

        or when count > 0 =>
          accept remove(item: out Integer) do
            -- remove an object from the buffer and assign it to item
            null;
          end remove;
          count := count - 1;
        or 

--**** This will give you controlled task exits.  You decide
--     when the task should end
          accept Shut_Down;
          exit;

        end select;

      end loop;
    end Buffer;

  task body Producer is
    n: integer;
    
    begin
--**** put Start up before loop.  Task will have to
--     wait here until the start up is called.

      accept Start_Up;
      -- any initializing can be done here also

      loop
--**** This will give you controlled task exits.  You decide
--     when the task should end
        select
           accept Shut_Down;
           exit;

        else
           -- give n an appropriate value
           Buffer.insert(n);

        end select;
      end loop;
  end Producer;

  task body Consumer1 is
    n: integer;
    
    begin
--**** put Start up before loop.  Task will have to
--     wait here until the start up is called.

      accept Start_Up;
      -- any initializing can be done here also

      loop

--**** This will give you controlled task exits.  You decide
--     when the task should end.
        select 
           accept Shut_Down;
           exit;

        else
           Buffer.remove(n);
           -- do something with n
        end select;
      end loop;
  end Consumer1;

  task body Consumer2 is
    n: integer;
    
    begin
--**** put Start up before loop.  Task will have to
--     wait here until the start up is called.

      accept Start_Up;
      -- any initializing can be done here also

      loop
--**** This will give you controlled task exits.  You decide
--     when the task should end
        select
           accept Shut_Down;
           exit;

        else
           Buffer.remove(n);
           -- do something with n
        end select;
      end loop;
  end Consumer2;

--**** Now here you have a choice.  You can either start these tasks
--     in the elaboration area of this package... 

begin -- My_Task_Stuff

  Producer.Start_Up;
  Consumer1.Start_Up;
  Consumer2.Start_Up;

end My_Task_Stuff;


with My_Task_Stuff;
procedure producer_consumer is

begin
  null;   -- will not terminate until all dependent
          -- tasks terminate
end producer_consumer;


--**** ... or call the Start_Ups from the main procedure
end My_Task_Stuff

with My_Task_Stuff;
procedure producer_consumer is

begin

   Producer.Start_Up;
   Consumer1.Start_Up;
   Consumer2.Start_Up;

end producer_consumer;

--**** One last thing; you can have procedure calls to your tasks
--     and hide the task inside the body instead of having a direct
--     task call specified in the Package Spec.



I hope I have helped and not confused you too badly.  If you have
any questions feel free to email me.


Cheryl R.S. Marquis
cmarquis@unode1.nswc.navy.mil

<no clever quote to put here...............YET!>




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~1993-03-15 14:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1993-03-15 14:58 Activating tasks at Global Scope Cheryl Marquis
  -- strict thread matches above, loose matches on Subject: below --
1993-03-10  3:32 Activating tasks at global scope Scott Meyers
1993-03-10 17:11 ` Robert I. Eachus
1993-03-11  3:56   ` Scott Meyers
1993-03-11 17:57     ` Dave Collard x7468
1993-03-11  2:51 ` Michael Feldman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox