AI22-0129-1
!standard 9.5(9) 26-03-12 AI22-0129-1/06
!class presentation 25-01-28
!status Revision-202Y 25-10-08
!status ARG Approved 13-0-0 25-10-08
!status work item 25-01-28
!status received 25-01-28
!assigned author Christoph Grein and Tucker Taft
!submitter Christoph Grein
!priority Low
!difficulty Easy
!subject Usage example for Protected Type with Dynamic Predicate
Since it’s not obvious how to define a dynamic predicate for a protected type so that it is evaluated as an external call, it’s recommended to add a Usage example.
AI22-0121-1 forbids internal calls for Dynamic_Predicates of protected types. External calls are still allowed for this usage. It is felt that a Usage example is needed.
(See summary.)
Add after 9.5(9):
Usage
Given the legality rule above disallowing internal calls in a Dynamic_Predicate for a protected type, it is best to specify the Dynamic_Predicate on a separate subtype, as illustrated below:
protected type T
-- with Dynamic_Predicate => Get_X in 1..100
-- -- illegal because Get_X would be an internal call
is
procedure Set_X (New_X : Integer);
function Get_X return Integer;
private
X : Integer := 0;
end T;
subtype Bounded_T is T
with Dynamic_Predicate => Bounded_T.Get_X in 1..100; -- OK.
This example illustrates how to apply a Dynamic_Predicate to a protected type, by defining a subtype and then applying the Dynamic_Predicate to that subtype. Applying a Dynamic_Predicate directly on a type is legal in most cases, but is not generally recommended because of the frequent need to have a name for a subtype to which the predicate does not apply. Additionally, for a protected type, applying a predicate directly on the type is illegal if the predicate is based on the result of a call on some protected function, since making an internal call is not permitted, and any call on a protected operation of the type from an aspect specification on the type declaration itself will be an internal call.[a][b][c][d][e][f]
This is a follow-up of AI22-0121-1, which forbids internal calls for Dynamic_Predicates of protected types. External calls are still allowed for such Dynamic_Predicates. An external call might cause a race condition in some uses (because the check is not indivisible with later operations on the type), so it might not be a particularly useful construct, but at least it makes sense.
Writing an external call in a Dynamic_Predicate without defining a separate subtype would require using a wrapper, because just adding a prefix does not change a call inside of the type declaration into an external call (that is, T1.Get_X is still considered an internal call since T1.Get_X is simply an expanded name for Get_X). One needs a helper function to turn this into an external call:
protected type T1 with Dynamic_Predicate => T1.Obj_Get_X
in 1..100 is
procedure Set_X (New_X : Integer);
function Get_X return Integer;
private
X : Integer := 0;
end T1;
function Obj_Get_X (Obj : in T1) return Integer is (Obj.Get_X);
The need to apply a predicate directly to the type definition (which defines the first subtype) is not considered to be very likely. Most Dynamic_Predicates are written on separate subtypes, not the first subtype, and any protected call in a subtype declaration is necessarily an external call. Most users will not encounter this new rule (which only applies to first subtypes).
The following is the preferred way to write this predicate:
protected type T2
-- with Dynamic_Predicate => Get_X in 1..100 -- internal call
illegal
is
procedure Set_X (New_X : Integer);
function Get_X return Integer;
private
X : Integer := 0;
end T2;
subtype Bounded_T2 is T2
with Dynamic_Predicate => Bounded_T2.Get_X in 1..100; -- OK
(See Issue and Discussion.)
@dinsa
Any call on a protected procedure or entry of a target protected object is defined to be an update to the object, as is a requeue on such an entry.
@dinss
@s8{@i{Usage}}
Given the legality rule above disallowing internal calls in a Dynamic_Predicate for a protected type, it is best to specify the Dynamic_Predicate on a separate subtype, as illustrated below:
@xcode{@b{protected type} T
-- @b{with} Dynamic_Predicate => Get_X @b{in} 1..100
-- --@ft{@i{ illegal because Get_X would be an internal call}}
@b{is}
@b{procedure} Set_X (New_X : Integer);
@b{function} Get_X @b{return} Integer;
@b{private}
X : Integer := 0;
@b{end} T;
@b{subtype} Bounded_T @b{is} T
@b{with} Dynamic_Predicate => Bounded_T.Get_X @b{in} 1..100; --@ft{@i{ OK.}}}
This example illustrates how to apply a Dynamic_Predicate to a protected type, by defining a subtype and then applying the Dynamic_Predicate to that subtype. Applying a Dynamic_Predicate directly on a type is legal in most cases, but is not generally recommended because of the frequent need to have a name for a subtype to which the predicate does not apply. Additionally, for a protected type, applying a predicate directly on the type is illegal if the predicate is based on the result of a call on some protected function, since making an internal call is not permitted, and any call on a protected operation of the type from an aspect specification on the type declaration itself will be an internal call.
No ACATS test is needed since this is a presentation issue.
[a]I am not convinced we need this paragraph. We could delete it and rely on the introductory paragraph to be sufficient for most users. We could make this into an AARM note.
[b]I like this wording. I can only speak for myself, but this problem was beyond my horizon (and I think I know the RM quite well).
[c]It doesn't make much sense to put information intended for end users into the AARM (which is mainly intended for implementors and language lawyers). I think we should take Christoph's advice and keep it.
[d]Fine with me.
[e]_Marked as resolved_
[f]_Re-opened_
Unintentionally closed, and Google Docs is too stupid to let me undo that action; I have to leave a useless comment to do so. I hate GD.