From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,99c27d6f54a8536b,start X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 1993-03-15 08:19:25 PST Newsgroups: comp.lang.ada Path: sparky!uunet!gatech!howland.reston.ans.net!zaphod.mps.ohio-state.edu!saimiri.primate.wisc.edu!relay!blackslacks.nswc.navy.mil!cmarquis From: cmarquis@blackslacks.nswc.navy.mil (Cheryl Marquis) Subject: Re: Activating tasks at Global Scope Message-ID: <1993Mar15.145833.18469@relay.nswc.navy.mil> Sender: news@relay.nswc.navy.mil Organization: NSWC Date: Mon, 15 Mar 1993 14:58:33 GMT Date: 1993-03-15T14:58:33+00:00 List-Id: >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