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.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,b59b337045eece60 X-Google-Attributes: gid103376,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII Path: g2news2.google.com!news3.google.com!feeder1-2.proxad.net!proxad.net!feeder2-2.proxad.net!newsfeed.arcor.de!newsspool2.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: Structure of the multitasking server Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <8b4d1170-22e6-40d3-8ed1-096dc0163491@m36g2000hse.googlegroups.com> Date: Fri, 19 Sep 2008 19:02:24 +0200 Message-ID: <1w9y1ocmu2cm3$.724p6fohqdvy$.dlg@40tude.net> NNTP-Posting-Date: 19 Sep 2008 19:02:26 CEST NNTP-Posting-Host: 7baf0555.newsspool2.arcor-online.net X-Trace: DXC==3=`J`S[6LHn;2LCV^[ On Fri, 19 Sep 2008 15:34:00 +0200, Jean-Pierre Rosen wrote: > Maciej Sobczak a �crit : >> >> Imagine a server with fixed number of worker tasks. There is no queue >> of jobs and jobs are immediately passed to one of the tasks that is >> currently idle. There is a separate task (or just the main one) that >> provides jobs for worker tasks. > [...] > > Why not simply use a rendezvous? > Each worker has an entry Get_Job: > > task body Worker_Task is > Job : Job_Type; > begin > loop > Get_Job (Job); You mean: accept Get_Job (Requested : Job_Type) do Job := Requested; end Get_Job; > end loop; > end Worker_Task; > > and the server is simply (assuming Servers is an array of Worker_Task): > > loop > Job := ... > > Found_Worker := False; > for I in Servers'Range loop > select > Server (I).Get_Job (Job); > Found_Worker := True; > exit; > else > -- This server is busy > null; > end select; > end loop; > > if not Found_Worker then > -- all pipelines are busy, > -- but the overflow handling is not shown... > end if; > end loop; This scheme requires some additional efforts in order to maintain the list of idle workers. I would use an inverse one, which is much simpler: with Ada.Text_IO; use Ada.Text_IO; type Job_Type is (Quit, Run); type Job (Kind : Job_Type := Quit) is null record; task type Worker; task Server is entry Get (Work : out Job); end Server; task body Server is Request : Job; Workers : array (1..5) of Worker; begin loop -- Get a job to do Request := (Kind => Run); -- Wait for a worker to come accept Get (Work : out Job) do Work := Request; end Get; end loop; -- Terminating workers for Index in Workers'Range loop Request := (Kind => Quit); accept Get (Work : out Job) do Work := Request; end Get; end loop; end Server; task body Worker is Work : Job; begin loop Server.Get (Work); case Work.Kind is when Quit => exit; when Run => Put_Line ("Doing things"); end case; end loop; Put_Line ("I am done"); end Worker; Note that task termination is usually a difficult problem in Ada. You should pay an attention to this early. (The "terminate" alternative is unusable in 80% cases.) In the solution above a special job type is used to kill the worker. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de