A simple way to avoid this program to hang?

Assume the following record defined with a “method k” in a package:

type rec1_type is record
  i : integer;
end record;
function k(rec1 : rec1_type) return Integer is (rec1.i + 1);
``
From "outside" this looks like a record with two components:
rec1.i and rec1.k   (where rec1.k = rec1.i + 1)

Then assume a protected object with a function f with argument of type rec1_type:

function f(rec1 : rec1_type) return Integer is (2*rec1.k);

Hence f makes a call to k outside the protected object and the program "hangs".
Did I understand correctly?  If so, have you any good advice what 
I should do to avoid the progamme to hang?

reinert

Please, post complete code. There is no reason why the program you described should hang.

Obs, the function k (in my real situation) calls back again to the protected object which is then blocked :slight_smile:
reinert
(department of impulsive posting - but your response helped)

So, you have: protected X.F that calls unprotected K which then calls protected X.S?

You can move K into the protected type. Call X.K from X.F. Call X.K from K. This would make X.S an internal call.

I think Ada forbids calling a potentially blocking call inside a protected operation, so if K blocks, then you can’t call it in F.

It’s hard to gen up a solution without a more complete example. In the above example you gave K doesn’t call back to the protected object. Can you flesh out the example a bit. In your example, K only pulls from the non protected rec1_type and we don’t know what the protected object looks like (or what the other function k calls looks like).

My first thought is that you shouldn’t need function F in the same protected object as the one K calls a function from. If you need another value via F then I would just add another function to the protected object and have k call those two functions separately and do the math unprotected. If instead you need access to rec1_type protected, I would create a separate mutex like protected object and protect rec1_type that way (otherwise you have the protected object of f doing two different jobs).

The relevant ARM section is 9.5 (41/5).

The background is that a protected action implementation may use a simple spin lock. If a call is not recognised as internal the implementation would try to lock again which would deadlock.

Given your definitions of Rec1_Type, function K, and

Rec1 : Rec1_Type;

then

Rec1.K

is illegal.

Why this hangs:

with Ada.Text_IO;
use  Ada.Text_IO;
procedure Rktest1 is

   function f_outside1 (i : Integer) return Integer;

   protected po1 is
      function f_inside1 (i : Integer) return Integer;
      function f_inside2 (i : Integer) return Integer;
   end po1;

   protected body po1 is
      function f_inside1 (i : Integer) return Integer is (f_outside1 (i));
      function f_inside2 (i : Integer) return Integer is (i + 10);
   end po1;

   function f_outside1 (i : Integer) return Integer is (po1.f_inside2 (i));

begin
   Put_Line ("Start");
   Put_Line (po1.f_inside1 (5)'Image);
   Put_Line ("Stop");
end Rktest1;

reinert

It hangs because f_outside1 makes an external call to po1.f_inside2 during a protected action initiated by po1.f_inside1.

ARM 9.5.1:

During a protected action, it is a bounded error to invoke an operation that is potentially blocking . The following are defined to be potentially blocking operations:

  • an external call on a protected subprogram (or an external requeue) with the same target object as that of the protected action;
1 Like