comp.lang.ada
 help / color / mirror / Atom feed
* Protected entries requeueing themselves
@ 2001-05-04 20:31 adam
  2001-05-05 20:32 ` Jeffrey Carter
  2001-05-08 19:35 ` Wilhelm Spickermann
  0 siblings, 2 replies; 3+ messages in thread
From: adam @ 2001-05-04 20:31 UTC (permalink / raw)


My second question about protected objects and requeueing:

9.5.2(31) says that although you can't use a formal parameter in an
entry barrier, but need to look at the parameters before deciding
whether to handle it, "the entry_barrier can be 'when True' and the
caller can be requeued (on some private entry) when its parameters
indicate that it cannot be handled immediately."  

Although this makes sense intuitively, I'm having trouble figuring out
how it would work in a seemingly simple case.  Suppose I have a
protected object that looks like this:

    protected PR is
        entry E1 (Min_Count : in integer;  Result : out integer);
        procedure PROC1;
    private
        Count : integer := 0;
    end PR;

Suppose PROC1 increments Count.  The intent of E1 is for each calling
task to wait until Count has been incremented past whichever point
that task desires.  This is illegal:

    entry E1 (Min_Count : in integer;  Result : out integer) 
                  when Min_Count >= Count is ...

Intuitively, it seems like this should work:

    entry E1 (Min_Count : in integer;  Result : out integer) when True is
    begin
        if Min_Count < Count then
            requeue E1;
        end if;
        Result := ...
   
with the intended effect being that after PROC1 is called, all the
entries on E1 will be executed to check their Min_Count, and those
that don't meet the requirement will requeue themselves, while those
that do will complete.

But I don't think it works.  As I read 9.5.3, it seems that when E1
requeues itself, the protected action continues, and this includes
servicing entry queues, and since "servicing of entry queues continues
until there are no open entries with queued calls" (9.5.3(18)), but
this entry will always be open and there will always be a queued call
on it, since the task keeps requeueing itself on the entry.  Thus, the
result of this is an infinite loop.

I recognize that 9.5.2(31) suggests using a private entry, but I'm not
sure how.  If the barrier on the private entry is "when True", the
same problem occurs; but I can't think what other barrier could be put
on the private entry to make things work.

Any suggestions?  How would you implement something like this to
achieve the intended effect?  Or is my understanding of 9.5.3
incorrect? 

(P.S. This example is hypothetical.  I'm trying to understand how
requeue works; the above problem isn't one I actually have to solve.)

                                -- thanks, Adam



 -----  Posted via NewsOne.Net: Free (anonymous) Usenet News via the Web  -----
  http://newsone.net/ -- Free reading and anonymous posting to 60,000+ groups
   NewsOne.Net prohibits users from posting spam.  If this or other posts
made through NewsOne.Net violate posting guidelines, email abuse@newsone.net



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Protected entries requeueing themselves
  2001-05-04 20:31 Protected entries requeueing themselves adam
@ 2001-05-05 20:32 ` Jeffrey Carter
  2001-05-08 19:35 ` Wilhelm Spickermann
  1 sibling, 0 replies; 3+ messages in thread
From: Jeffrey Carter @ 2001-05-05 20:32 UTC (permalink / raw)


adam@irvine.com wrote:
> 
>     protected PR is
>         entry E1 (Min_Count : in integer;  Result : out integer);
>         procedure PROC1;
>     private
>         Count : integer := 0;
>     end PR;
> 
> Suppose PROC1 increments Count.  The intent of E1 is for each calling
> task to wait until Count has been incremented past whichever point
> that task desires.  This is illegal:
> 
>     entry E1 (Min_Count : in integer;  Result : out integer)
>                   when Min_Count >= Count is ...
> 
> Intuitively, it seems like this should work:
> 
>     entry E1 (Min_Count : in integer;  Result : out integer) when True is
>     begin
>         if Min_Count < Count then
>             requeue E1;
>         end if;
>         Result := ...
> 
> with the intended effect being that after PROC1 is called, all the
> entries on E1 will be executed to check their Min_Count, and those
> that don't meet the requirement will requeue themselves, while those
> that do will complete.
> 
> But I don't think it works.  As I read 9.5.3, it seems that when E1
> requeues itself, the protected action continues, and this includes
> servicing entry queues, and since "servicing of entry queues continues
> until there are no open entries with queued calls" (9.5.3(18)), but
> this entry will always be open and there will always be a queued call
> on it, since the task keeps requeueing itself on the entry.  Thus, the
> result of this is an infinite loop.

That's correct. No one can get the protected object's lock to execute
Proc1, so Count will never change, and this is an infinite loop unless
there are other tasks queued on E1 and a task that is not requeued
changes Count.

> I recognize that 9.5.2(31) suggests using a private entry, but I'm not
> sure how.  If the barrier on the private entry is "when True", the
> same problem occurs; but I can't think what other barrier could be put
> on the private entry to make things work.
> 
> Any suggestions?  How would you implement something like this to
> achieve the intended effect?  Or is my understanding of 9.5.3
> incorrect?

You would use something like

   protected PR is
      entry E1 (Min_Count : in Natural;  Result : out integer);
      procedure Increment;
   private -- PR
      entry E2 (Min_Count : in Natural; Result : out Integer);

      Count             : Natural :=  0;
      Max_Desired_Count : Integer := -1;
   end PR;

   protected body PR is
      procedure Increment is
      begin -- Increment
         Count := Count + 1;
      end Increment;

      entry E1 (...) when True is
      begin -- E1
         if Min_Count < Count then
            Max_Desired_Count := Integer'Max (Max_Desired_Count,
Min_Count);

            requeue E2;
         end if;

         ...
      end E1;

      entry E2 (...) when Count <= Max_Desired_Count is
      begin -- E2
         ...
         if E2'Count <= 0 then
            Max_Desired_Count := -1;
         end if;
      end E2;
   end PR;

This stores up requests until it can Count is suitable for all stored
requests, which is not quite what you were discussing, but has a simpler
solution than your problem while still using requeue for preference
control. HTH.

-- 
Jeff Carter
"Son of a window-dresser."
Monty Python & the Holy Grail



^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: Protected entries requeueing themselves
  2001-05-04 20:31 Protected entries requeueing themselves adam
  2001-05-05 20:32 ` Jeffrey Carter
@ 2001-05-08 19:35 ` Wilhelm Spickermann
  1 sibling, 0 replies; 3+ messages in thread
From: Wilhelm Spickermann @ 2001-05-08 19:35 UTC (permalink / raw)
  To: comp.lang.ada

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=us-ascii, Size: 3294 bytes --]


On 04-May-01 adam@irvine.com wrote:
> My second question about protected objects and requeueing:
> 
> 9.5.2(31) says that although you can't use a formal parameter in an
> entry barrier, but need to look at the parameters before deciding

If the parameter to be put into the entry barrier has just a few different
values, a family entry would solve the problem. The family parameter may be
used in the barrier.

> whether to handle it, "the entry_barrier can be 'when True' and the
> caller can be requeued (on some private entry) when its parameters
> indicate that it cannot be handled immediately."  
> 
> Although this makes sense intuitively, I'm having trouble figuring out
> how it would work in a seemingly simple case.  Suppose I have a
> protected object that looks like this:
> 
>     protected PR is
>         entry E1 (Min_Count : in integer;  Result : out integer);
>         procedure PROC1;
>     private
>         Count : integer := 0;
>     end PR;
> 
> Suppose PROC1 increments Count.  The intent of E1 is for each calling
> task to wait until Count has been incremented past whichever point
> that task desires.  This is illegal:
> 
>     entry E1 (Min_Count : in integer;  Result : out integer) 
>                   when Min_Count >= Count is ...
> 
> Intuitively, it seems like this should work:
> 
>     entry E1 (Min_Count : in integer;  Result : out integer) when True is
>     begin
>         if Min_Count < Count then
>             requeue E1;
>         end if;
>         Result := ...
>    
> with the intended effect being that after PROC1 is called, all the
> entries on E1 will be executed to check their Min_Count, and those
> that don't meet the requirement will requeue themselves, while those
> that do will complete.
> 
> But I don't think it works.  As I read 9.5.3, it seems that when E1
> requeues itself, the protected action continues, and this includes
> servicing entry queues, and since "servicing of entry queues continues
> until there are no open entries with queued calls" (9.5.3(18)), but
> this entry will always be open and there will always be a queued call
> on it, since the task keeps requeueing itself on the entry.  Thus, the
> result of this is an infinite loop.
> 
> I recognize that 9.5.2(31) suggests using a private entry, but I'm not
> sure how.  If the barrier on the private entry is "when True", the
> same problem occurs; but I can't think what other barrier could be put
> on the private entry to make things work.

You could copy the attribute COUNT of the private entry to a variable
"How_Many_To_Go" of the protected type in PROC1 and use "How_Many_To_Go>0" as
the barrier of the private entry; it�s body should decrement the variable. But
using the COUNT attribute is like walking on thin ice. (Think about aborts and
timed entry calls.) _And_ You will need a "Pragma Queuing_Policy (FIFO_Queuing)"

I like it more to use two private entries which requeue to each other and open
alternating -- switching occurs every time PROC1 is called. As both of them have
the same code and switching reduces to setting a variable, a family of two
entries is handy. You can also use "requeue with abort" here without running
into problems.

(I hope someone will intervene, if I�m telling wrong or misleading things.)

Wilhelm





^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2001-05-08 19:35 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-05-04 20:31 Protected entries requeueing themselves adam
2001-05-05 20:32 ` Jeffrey Carter
2001-05-08 19:35 ` Wilhelm Spickermann

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