comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Structure of the multitasking server
Date: Mon, 22 Sep 2008 16:11:57 +0200
Date: 2008-09-22T16:11:57+02:00	[thread overview]
Message-ID: <1njy6zbrm8yv0.fmtwebrb08bq$.dlg@40tude.net> (raw)
In-Reply-To: 29fcd27f-aefd-4787-b8f6-5f8a04bd0f42@z72g2000hsb.googlegroups.com

On Mon, 22 Sep 2008 05:47:13 -0700 (PDT), Maciej Sobczak wrote:

> On 22 Wrz, 10:12, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> 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



  reply	other threads:[~2008-09-22 14:11 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-19 12:21 Structure of the multitasking server Maciej Sobczak
2008-09-19 13:34 ` Jean-Pierre Rosen
2008-09-19 17:02   ` Dmitry A. Kazakov
2008-09-21 17:30     ` Maciej Sobczak
2008-09-21 19:24       ` Dmitry A. Kazakov
2008-09-21 21:27         ` Maciej Sobczak
2008-09-22  8:12           ` Dmitry A. Kazakov
2008-09-22 12:47             ` Maciej Sobczak
2008-09-22 14:11               ` Dmitry A. Kazakov [this message]
2008-09-23  8:07                 ` Maciej Sobczak
2008-09-23  9:37                   ` Dmitry A. Kazakov
2008-09-23 10:47                   ` Jean-Pierre Rosen
2008-09-21 17:23   ` Maciej Sobczak
2008-09-22  8:23     ` Jean-Pierre Rosen
2015-03-12 16:07   ` gautier_niouzes
2015-03-12 21:38     ` Jacob Sparre Andersen
2015-03-12 22:39       ` gautier_niouzes
2015-03-13  8:15         ` Dmitry A. Kazakov
2015-03-13 20:16           ` gautier_niouzes
2015-03-13 20:47             ` Dmitry A. Kazakov
2015-03-15  7:43               ` gautier_niouzes
2015-03-15  8:35                 ` Simon Wright
2015-03-15  8:52                 ` J-P. Rosen
2015-03-15  9:21                   ` Jacob Sparre Andersen
2015-03-15 16:04                     ` Brad Moore
2015-03-13 23:04             ` Randy Brukardt
2015-03-14  8:22               ` Simon Wright
2008-09-19 23:01 ` anon
2008-09-21 17:37   ` Maciej Sobczak
2008-09-22  2:32     ` anon
2008-09-22 13:05       ` Maciej Sobczak
2008-09-23  9:25         ` anon
replies disabled

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