!standard A.4.7(28) 10-10-21 AI05-0224-1/00 !standard A.4.8(28/2) !class binding interpretation 10-10-21 !status work item 10-10-21 !status received 10-06-07 !priority Low !difficulty Medium !qualifier Error !subject No_Task_Allocators and classwide returns !summary !question How does the No_Task_Allocators restriction interact with a function that returns Some_Limited_Type'Class, as in type Ref is access Some_Limited_Type'Class; type T is new Some_Limited_Type with record Tsk : Some_Task_Type; end record; function F return Some_Limited_Type'Class is begin return X : T; end F; Ptr : Ref := new Some_Limited_Type'Class'(F); !wording !discussion !ACATS Test !appendix From: Steve Baird Sent: Monday, June 7, 2010 2:20 PM How does the No_Task_Allocators restriction interact with a function that returns Some_Limited_Type'Class, as in type Ref is access Some_Limited_Type'Class; type T is new Some_Limited_Type with record Tsk : Some_Task_Type; end record; function F return Some_Limited_Type'Class is begin return X : T; end F; Ptr : Ref := new Some_Limited_Type'Class'(F); Does this restriction need a dynamic rule to deal with the cases like this? **************************************************************** From: Randy Brukardt Sent: Monday, June 7, 2010 2:34 PM I don't think it *has* to have a dynamic rule, since this clearly (!) can be checked at link-time, and restrictions are technically post-compilation checks anyway. The better question in my view is whether we intend implementations to do the link-time handstands this requires (and if so, why). (You need to do the check at link-time as the body of F probably is separately compiled from the allocator, and you need to know about both in order to show a problem.) **************************************************************** From: Gary Dismukes Sent: Monday, June 7, 2010 3:13 PM > I don't think it *has* to have a dynamic rule, since this clearly (!) > can be checked at link-time, and restrictions are technically > post-compilation checks anyway. But there are cases that might not be checkable at link time, such as when the function has multiple returns, only some of which have task parts. **************************************************************** From: Randy Brukardt Sent: Monday, June 7, 2010 3:30 PM > But there are cases that might not be checkable at link time, such as > when the function has multiple returns, only some of which have task > parts. I don't think that people who want to enforce this particular restriction (which is intended to simplify the runtime system) care whether there is *actually* a task allocator; I think they only care that there *might be* a task allocator. After all, you could put if False then around the allocator itself -- but that would still violate the restriction. So it makes sense to me that any possibility of returning a task from the function would be flagged if the function is subsequently used in an allocator. Specifically, I don't see much difference between: if False then Ptr := new Some_Type_Containing_a_Task; end if; and Ptr := new Root'Class (F); function F return Root'Class is begin if False then return Obj:T; else return Obj2:S; end if; end F; (where type T has a task and type S does not). And the point that I recalled above (that the restriction is intended to simplify the runtime system) implies that a runtime check is inappropriate. A more interesting question is what do implementations currently do in this case? We ought to follow practice if there is in fact any to follow. **************************************************************** From: Steve Baird Sent: Monday, June 7, 2010 3:34 PM > But there are cases that might not be checkable at link time, such as > when the function has multiple returns, only some of which have task parts. Right. Other cases include dispatching calls and calls through access-to-function values. This is not, in general, checkable at link time. **************************************************************** From: Steve Baird Sent: Monday, June 7, 2010 3:39 PM I think that if you want to check this restriction completely without runtime checks, then you would have to be conservative and reject some allocators (e.g., the one in my example) on the grounds that the type of the allocated object *might* have a task part. **************************************************************** From: Randy Brukardt Sent: Monday, June 7, 2010 6:51 PM Right. The current check is conservative anyway: there is no guarantee that the allocator of a task will be executed, but the program is rejected simply by its existence. The only question I would have is "how conservative"? I would think that banning allocators of all limited class-wide types would be going too far, so some sort of post-compilation check would be needed. Perhaps simply banning allocators of a limited class-wide type where any extension has a task component would be adequate (that would be somewhat easier to implement than trying to figure out for every function whether it could return a task). In any case, I think we'll need some additional wording for this rule (whatever we decide). **************************************************************** From: Steve Baird Sent: Thursday, October 21, 2010 4:47 PM Before trying to come up with wording for this recently-created AI, I need to know what rule we want to express. !question How does the No_Task_Allocators restriction interact with a function that returns Some_Limited_Type'Class, as in type Ref is access Some_Limited_Type'Class; type T is new Some_Limited_Type with record Tsk : Some_Task_Type; end record; function F return Some_Limited_Type'Class is begin return X : T; end F; Ptr : Ref := new Some_Limited_Type'Class'(F); Possible solutions include: 1) If the restriction is given, then conservatively reject all access-to-limited-classwide allocators on the grounds that they might violate the restriction. 2) A post-compilation check that if the restriction is given and an allocator exists which allocates an object of type Some_Limited_Type'Class, then there exist no extensions of Some_Limited_Type which have task subcomponents. Or something like that. 3) A runtime check that raises Program_Error if the restriction is in force and the program attempts to allocate a task (via some mechanism such as the given example which makes it past the static checks). I'd like to get a consensus on what we want here so that I can try to have wording for it before the Fairfax meeting. Opinions? P.S. My preference order is #2, #1, #3. **************************************************************** From: Bob Duff Sent: Thursday, October 21, 2010 5:13 PM > Before trying to come up with wording for this recently-created AI, It seems to be so recent that it's in the future. That is, I don't see it on the ada-auth web site. And I've never heard of it. So I'm kind of flying blind here, but... > P.S. My preference order is #2, #1, #3. Hmm. I think #3 is best. #1 is no good -- why should limited types be punished just because they MIGHT contain tasks? #2 is a big pain for implementers, for little gain. **************************************************************** From: Steve Baird Sent: Thursday, October 21, 2010 5:25 PM >> Before trying to come up with wording for this recently-created AI, > > It seems to be so recent that it's in the future. > That is, I don't see it on the ada-auth web site. > And I've never heard of it. > Yeah, this one just landed in my lap today, but if you've seen the !question section, then you've seen the whole AI at this point. > So I'm kind of flying blind here, but... > >> P.S. My preference order is #2, #1, #3. > > Hmm. I think #3 is best. Thanks for taking the time to reply. I don't feel strongly about it, but my idea was that implementors of a runtime system which is built for use with this restriction don't want to deal with this issue at all. They want to know statically that task allocation can't happen. **************************************************************** From: Bob Duff Sent: Thursday, October 21, 2010 5:40 PM > Thanks for taking the time to reply. You're welcome. > I don't feel strongly about it, but my idea was that implementors of a > runtime system which is built for use with this restriction don't want > to deal with this issue at all. They want to know statically that task > allocation can't happen. Yes, I agree with that. But replacing every "create some tasks" with "raise.." seems easy, and accomplishes that goal, while all kinds of link-time checks seems hard. **************************************************************** From: Randy Brukardt Sent: Thursday, October 21, 2010 5:58 PM ... > > Before trying to come up with wording for this recently-created AI, > > It seems to be so recent that it's in the future. > That is, I don't see it on the ada-auth web site. > And I've never heard of it. It was created out of mail from this list on June 7th. So you *ought* to have heard of it (but you didn't comment on it at the time). **************************************************************** From: Randy Brukardt Sent: Thursday, October 21, 2010 6:06 PM ... > > I don't feel strongly about it, but my idea was that implementors of > > a runtime system which is built for use with this restriction don't > > want to deal with this issue at all. They want to know statically > > that task allocation can't happen. > > Yes, I agree with that. But replacing every "create some tasks" > with "raise.." seems easy, and accomplishes that goal, while all kinds > of link-time checks seems hard. Humm. I guess I don't see this, as it seems unlikely to me that the check could be performed outside of the task supervisor. So quite a bit of the overhead of creating tasks would be present in the generated code, even if it wasn't used. That's not the point. Specifically, I don't see how the function F in Steve's example could be compiled without the overhead of being able to create tasks, because there is no way for it to know whether it is called from an allocator (which would raise an exception) or from an object initialization (which would work - at least in the absence of other restrictions). And that means that the call site would need at least some of the overhead of task creation in order to be able to meet the calling convention of the function (since it couldn't know if a task was actually created, and no exception could be raised if it was not). Indeed, that seems to be a problem for *any* version of this restriction other than the over-the-top #1. Not sure what to do here... ****************************************************************