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: g2news1.google.com!news1.google.com!news4.google.com!feeder1-2.proxad.net!proxad.net!feeder2-2.proxad.net!newsfeed.arcor.de!newsspool3.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> <1w9y1ocmu2cm3$.724p6fohqdvy$.dlg@40tude.net> <259e95c5-92e6-4200-bc6e-5f35d99336a9@l64g2000hse.googlegroups.com> <11dyqk0lqb1je.ap31n7jjew7l.dlg@40tude.net> <1ey0wvc4tun7g$.15u4xyef05055$.dlg@40tude.net> <29fcd27f-aefd-4787-b8f6-5f8a04bd0f42@z72g2000hsb.googlegroups.com> Date: Mon, 22 Sep 2008 16:11:57 +0200 Message-ID: <1njy6zbrm8yv0.fmtwebrb08bq$.dlg@40tude.net> NNTP-Posting-Date: 22 Sep 2008 16:11:57 CEST NNTP-Posting-Host: 586ae561.newsspool2.arcor-online.net X-Trace: DXC=]A0N>7UJZJAI7\_^6>c20JA9EHlD;3YcB4Fo<]lROoRA8kFOhZ7mmKRmSNB X-Complaints-To: usenet-abuse@arcor.de Xref: g2news1.google.com comp.lang.ada:2065 Date: 2008-09-22T16:11:57+02:00 List-Id: On Mon, 22 Sep 2008 05:47:13 -0700 (PDT), Maciej Sobczak wrote: > On 22 Wrz, 10:12, "Dmitry A. Kazakov" > wrote: > >>> � � � entry Get_Job (J : out Job_Type; Finished : out Boolean); >> >> Which is a bad pattern because it propagates task termination requests to >> an entry point of some object (or another task) which usually have little >> or nothing to do with the task termination issue. > > How is the special job any different in this aspect? It has exactly > the same properties, just implicitly. It is not, as I said the pattern is same. >> I don't like an extra output parameter, it is error-prone. Therefore I used >> a special value of Job_Type. > > In what way is a special value less error-prone than a separate flag? Not a flag, it is a special value. I have used a discriminant, which would then control a variant record. >> There also exists a third variant with an >> exception propagation. > > This assumes rendezvous. Nope. An exception can be propagated from the entry body or rendezvous. Here is my example with exceptions (a complete program): with Ada.Text_IO; use Ada.Text_IO; procedure Test_Server is Time_To_Die : exception; type Job 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 for Times in 1..7 loop -- Get a job to do -- 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 begin accept Get (Work : out Job) do raise Time_To_Die; end Get; exception when Time_To_Die => null; end; end loop; end Server; task body Worker is Work : Job; begin loop Server.Get (Work); Put_Line ("Doing things"); end loop; exception when Time_To_Die => Put_Line ("I am done"); end Worker; begin null; end Test_Server; >> This all is a matter of taste, because the (poor) pattern is same: the >> knowledge about caller's termination is moved to the callee. > > In the version with protected objects the entity that triggers > termination might be different from the one that invents job. > In your version these different responsibilities are mixed. It does not work. You cannot selectively call to multiple entries of a protected object anyway. Then again, termination should be triggered by task finalization, this the only "right way." All others are more or less nasty workarounds. This is the point. So long it is not either a "terminate" alternative or else a "free" decision of the task to exit, all designs are equally bad. > There is a lot of sense. In particular, in my version the task that > invents jobs is never blocked on interactions with workers. This is a > big advantage, because such a blocking would disturb its own > interactions with the environment and reduce its responsiveness. This is a design fault. Under certain conditions it must either block or fail. > In your version with rendezvous the task that invents jobs has to > block and during that time it cannot react to the events that drive it > (keyboard input, network transmission, etc.). Wrong, see 9.7.1(16). >> A better design would be: >> >> � �Server --> Scheduler <-- Worker >> >> The jobs are queued to the scheduler. Workers ask it for jobs to do. >> Scheduler could be a protected object or a task. > > Isn't it what I have proposed? No. Decisive is who knows whom. Your design is when a multicasting publisher "knows" its peers. This is a bad idea, obviously. > Or the main task could promptly reject requests so that clients can > back off or try to find another, less busy server. >> Anyway it is no problem in my design. Use selective accept (RM 9.7.1): >> >> � �select >> � � � when not Empty (Queue) �=> accept Get (Work : out Job) do >> � � � � �... -- A worker is here to get a job from the FIFO >> � � � end Get; >> � �or when not Full (Queue) => accept Put (Work : out Job) do >> � � � � �... -- A new job is to queue into the FIFO >> � � � end Put; >> � �or when Full (Queue) => delay Time_Out; >> � � � ... -- Go to hell with your jobs! >> � �end select; > > But this looks like part of a separate task and the third branch still > causes someone else to block. No problem with that. There is "else part" of selective accept for this 9.7.1(19): � select � � when not Empty (Queue) �=> accept Get ... � or when not Full (Queue) => accept Put ... � else ... -- Go to hell at once! � �end select; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de