简体   繁体   中英

Ada - try to call entry of element of array of protected type, if busy - try next element

I'm working on a multithreading project and i have one array of tasks, let's call it A and one array of protected, let's call it B.

Now every element of A at some point will want to access entry from one of the elements of B. Is there a way to iterate quickly through B's and find accesible one?

I was browsing some resources avalaible online and found only

select
    call entry;
or 
    delay;

which won't do the job.

Is there a way to do that that i'm not aware of?

Thanks in advance!

EDIT

So i got really excited about that select else statements and tried it out, unfortunately it still doesnt work, if I try it this way - using Mr. Simon Wright's code sample to simulate effect i need, the

else

part of code never gets executed, they (the taskArray elements) all think they can acces Call_Me and get stuck in the queue.

How can i solve this issue? I also tried using 'Count thing, but it somehow always ended up being 0.

with Ada.Text_IO; use Ada.Text_IO;

procedure Array_Of_POs is

   protected type PO is
      entry Call_Me;
   private
      Callable : Boolean := True; --changed
   end PO;

   protected body PO is
      entry Call_Me when Callable is
      begin
         Callable := False; --added
         Put_Line("Doin stuff");
         delay 1.0;
         Callable := True;

      end Call_Me;
   end PO;

   POs : array (1 .. 3) of PO;

   Success : Boolean := False;


   task type Test; --added
   task body Test is
   begin
   for J in POs'Range loop                                                              -- '
      select
         POs (J).Call_Me;
         Success := True;
      else
         Put_Line("I never get displayed!"); --added
      end select;
   end loop;

   Put_Line ((if Success
              then "succeeded, oh dear"
              else "didn't succeed, good"));
   end Test;

   testArray : array (1..3) of Test;

end Array_Of_POs;

You could try finding an entry E whose Count attribute ( E'Count , ARM 9.9(5) ) is zero; but this is going to result in race conditions, since another task could sneak in between your checking the count and your making the call. And see the note at (7), ibid.

You need a conditional entry call, as in ARM 9.7.3 .

It would look something like

with Ada.Text_IO; use Ada.Text_IO;

procedure Array_Of_POs is

   protected type PO is
      entry Call_Me;
   private
      Callable : Boolean := False;
   end PO;

   protected body PO is
      entry Call_Me when Callable is
      begin
         null;
      end Call_Me;
   end PO;

   POs : array (1 .. 3) of PO;

   Success : Boolean := False;

begin

   for J in POs'Range loop                                                              -- '
      select
         POs (J).Call_Me;
         Success := True;
      else
         null;
      end select;
   end loop;

   Put_Line ((if Success
              then "succeeded, oh dear"
              else "didn't succeed, good"));

end Array_Of_POs;

In your case, I suspect this construct would be in an outer loop, so you'd need to do something to avoid busy-waiting (on the lines of putting in a delay if not Success , perhaps).

EDIT

This is a response to your edited question.

ARM 9.5.1(8) states that your PO.Call_Me contains a bounded error . In the next paragraph,

If the bounded error is detected, Program_Error is raised. If not detected, the bounded error might result in deadlock or a (nested) protected action on the same target object.

At least GNAT hasn't done either of those.

The issue is that the body of the entry is executed in the context (thread) of the caller . So what happens is

Test calls POs(1).Call_Me
The call is accepted
Callable is set False
Put_Line and delay are called ( still in the context of Test )
Callable is set True
POs(1).Call_Me returns to Test
...

The approach you've adopted might work if instead of using an array of POs you used an array of tasks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM