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; 7+ 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] 7+ messages in thread
* Re:  Activating tasks at Global Scope
@ 1993-03-15 14:58 Cheryl Marquis
  0 siblings, 0 replies; 7+ 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] 7+ messages in thread

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

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
1993-03-11  2:54   ` second half of portable diners Michael Feldman
  -- strict thread matches above, loose matches on Subject: below --
1993-03-15 14:58 Activating tasks at Global Scope Cheryl Marquis

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