!standard E.2.2(9/1) 07-08-04 AI05-0060-1/00 !standard E.2.2(9.2/1) !class binding interpretation 07-08-04 !status work item 07-08-04 !status received 07-06-19 !priority Low !difficulty Hard !qualifier Omission !subject The definition of Remote access types is too limiting !summary ** TBD ** !question (1) E.2.2(9-9.2/1) define what a remote access type can designate. This does not include a class-wide interface. But an interface is very similar to an abstract tagged limited private type; neither can have visible components. A class-wide limited private type is allowed in a remote access type. Shouldn't a limited interface be allowed? (2) The definition of remote access types includes any anonymous access types that occur visibly in the remote types package. But such anonymous access types are necessarily part of another construct (access discriminants, access parameters, access components); they will not themselves be used remotely unless the containing construct is. But this rule makes significant restrictions on which anonymous access types can be used and how. For instance, an access-to-subprogram parameter is required by this rule to be passed only remote subprograms, even though the subprogram that is using the parameter is not itself a remote subprogram. Should this restriction be relaxed? (3) Should we formally say that Annex E pragmas have no effect on implementations that don't support Annex E? Doing so would allow us to declare additional packages to have Remote_Types pragmas, as we wouldn't have to worry about the effect on most implementations. !recommendation (See Summary.) !wording ** TBD ** !discussion The solution requires care, as a non-limited type can be derived from a limited interface type. That would violate the intent that a remote access type can only designate a limited object. Excluding anonymous access types also requires care: if one appears as a component of a remote type, the remote type ought to be required to have user-defined stream attributes (that is, any exclusion should not change the rules for external streaming). -- !corrigendum E.2.2(9/1) !ACATS Test !appendix From: Brad Moore Sent: Tuesday, June 19, 2007 2:29 AM I have come across a potential use for interface types that currently is not allowed in Ada 2005, yet seems like it would be a useful and natural extension to add to the language. At the very least, it seems worthy of discussion. It seems that this capability could be enabled by making only minor wording changes to Annex E to relax restrictions for remote access types. Specifically, it seems useful to be able to specify limited interfaces as remote access types. However E.2.2(9/1) states: (9/1) An access type declared in the visible part of a remote types or remote call interface library unit is called a remote access type. Such a type shall be (9.1/1) - an access-to-subprogram type, or (9.2/1) - a general access type that designates a class-wide limited private type or a class-wide private type extension all of whose ancestors are either private type extensions or limited private types. A limited interface cannot be used because of the restriction in (9.2/1) since an interface is not a private type, even though it would seem to be implicitly private since an interface type cannot have any visible record components. eg. The following code excerpt will compile if Client_Buffer_Type is declared as an abstract tagged limited private type. It does not compile if it declared as a limited interface type, due to the restriction stated in (9.2/1) above. package Buffer_Notifications is pragma Pure; -- type Client_Buffer_Type is abstract tagged limited private; type Client_Buffer_Type is limited interface; procedure Notify (Buffer_Client : access Client_Buffer_Type; Data : in String) is abstract; --private -- type Client_Buffer_Type is abstract tagged limited null record; end Buffer_Notifications; with Buffer_Notifications; use Buffer_Notifications; package Buffer_Server is pragma Remote_Call_Interface; type Buffer_Access is access all Client_Buffer_Type'Class; procedure Register (Buffer : Buffer_Access); procedure Send_To_Buffers(Data : String); No_More_IDs : exception; end Buffer_Server; It seems this could be allowed if E.2.2(9.2/1) were modified from; (9.2/1) - "a general access type that designates a class-wide limited private type or a class-wide private type extension all of whose ancestors are either private type extensions or limited private types." to state; (9.2/1) "a general access type that designates a class-wide limited interface type or a class-wide limited private type or a class-wide private type extension all of whose ancestors are private type extensions, interface types, or limited private types" Also E.2.2(14/2) would likely need to be modified from; "The primitive subprograms of the corresponding specific limited private type shall only have access parameters if they are controlling formal parameters; each non-controlling formal parameter shall support external streaming (see 13.13.2);" to something along the lines; "The primitive subprograms of the corresponding specific limited private type or limited interface type shall only have access parameters if they are controlling formal parameters; each non-controlling formal parameter shall support external streaming (see 13.13.2);" Hopefully the following questions could be considered in the discussion that might be generated; Would this be a change that would be relatively easy for vendors to implement? Is there a general feeling that this would be a useful capability? Are there reasons why limited interface types are restricted from being remote access types? Should an AI be created for this? **************************************************************** From: Tucker Taft Sent: Tuesday, June 19, 2007 1:32 PM I agree with your suggestion that we should probably allow access to class-wide limited interface as a remote access type. One niggling concern is that a non-limited type can be derived from a limited interface. I am feeling too slow-witted today to decide whether that is a real issue. **************************************************************** From: Brad Moore Sent: Wednesday, June 20, 2007 11:45 AM Thanks Tuck, for sharing your niggling concern. I share your concern, so I have revised my suggested wording changes, because it seems that the wording I originally suggested allows a private extention that is derived from a nonlimited interface. Also, just to clarify, the intent of my suggested revision to the wording is to not only allow class-wide limited interfaces as remote access types, but to also allow class-wide synchronized interfaces, class-wide protected interfaces, and class-wide task interfaces as remote access types. Since all of these are limited, I am hoping the wording is generic enough to include those others as well. Firstly, RM 7.3(6/2) defines the notion of a limited private extension, 7.3(6/2) "A private type is limited if its declaration includes the reserved word limited; a private extension is limited if its ancestor type is a limited type that is not an interface type, or if the reserved word limited or synchronized appears in its definition. If the partial view is nonlimited, then the full view shall be nonlimited. If a tagged partial view is limited, then the full view shall be limited. On the other hand, if an untagged partial view is limited, the full view may be limited or nonlimited." Also relevant is; 7.3 (8.1/2) "If the reserved word limited appears in a private_extension_declaration, the ancestor type shall be a limited type. If the reserved word synchronized appears in a private_extension_declaration, the ancestor type shall be a limited interface." It seems to help the wording if we speak of limited private extensions, rather than just private extensions, so I inserted "limited" before "private extension" in my revised suggested wording. Also, the RM defines "private extension", but does not define "private type extension", so I removed the word "type". There are many references to "private extension" throughout the RM, but "private type extension" only appears in this one paragraph. I presume that there might be value in making this minor editorial change regardless of whether any other wording changes are made to 9.2/1. New suggested wording for E.2.2 (9.2/1); E.2.2 (9.2/1) "a general access type that designates a class-wide limited interface type or a class-wide limited private type or a class-wide limited private extension." The phrase "all of whose ancestors are private type extensions, interface types, or limited private types" seems redundant to me. If the private extension is limited, all ancestor private type extensions and private types would also have to be limited. Is that correct? That is why I also removed that clause. The sentence is now simpler, but hopefully I haven't removed something that was needed. I would appreciate any feedback if anyone sees any problems or holes in the proposed wording. I realize I am probably getting ahead of myself with proposed wording changes, I am hoping only to suggest that any such wording changes needed for this change would likely be minimal. More important at this time, would be to get a sense for how others felt about the usefulness or need for being able to use class-wide limited interface types as remote access types. **************************************************************** From: Tucker Taft Sent: Wednesday, June 20, 2007 2:37 PM We cannot remove the part about: " ... all of whose ancestors are private [type] extensions, interface types, or limited private types" because we want to rule out the case where a private extension has a non-private record or record extension as an ancestor. I agree that removing "type" from "private type extension" would be more consistent. For what it's worth, my concern was that the *object* designated by the access-to-limited-interface'Class might be non-limited. I'm not sure that there is any problem with that, but it is something new. **************************************************************** From: Brad Moore Sent: Friday, June 22, 2007 1:54 AM > We cannot remove the part about: > > " ... all of whose ancestors are private [type] extensions, > interface types, or limited private types" > > because we want to rule out the case where a private extension > has a non-private record or record extension as an > ancestor. Of course you are right. I was focussing too much on the limitedness factor, at the expense of the privateness factor. Also, I now think it is better to move the word "limited" from where I originally suggested, before "private extension all of whose ancestors..." to before "interface types" in the clause that we cannot remove. ie., E.2.2 (9.2/1) "a general access type that designates a class-wide limited interface type or a class-wide limited private type or a class-wide private extension all of whose ancestors are private extensions, limited interface types, or limited private types." That seems to more neatly plug the hole in the wording I originally suggested that would allow a private extension derived from a non-limited interface to be used as a remote access type. > For what it's worth, my concern was that the *object* > designated by the access-to-limited-interface'Class > might be non-limited. I'm not sure that there is > any problem with that, but it is something new. That is something I hadn't thought of and didn't pick up from your original reply. I see that now. I also think I see why it's not easy to know offhand if there is an issue with this or not. It seems quite likely that there wouldn't be an issue, but requires some more deeper thought to think it through. On the surface this limitedness issue seems to be a similar issue to the corresponding privateness issue. That is, I believe it is possible to extend a private extension with a record extension, so that the *object* used in a remote access type could have visible components. I believe non-private object components would have been allowed in remote access type objects in Ada 95 also, and that part does not seem to have changed, so if it wasn't a problem in Ada95, it likely isn't a problem in Ada 2005 either. The new thing as a result of this suggested change would be that an object used as a class-wide remote access type could now be non-limited, in addition to possibly containing non-private components. The remote "view" of these objects would be that of a limited private type, but the local "view" could be not as restrictive. The ramification of this would mean that locally, the object could be copied, or assigned to. At this point, I don't see a problem with this, but cannot say for sure that there wouldn't be a problem with this either, or if there may be other issues that I may have overlooked. Hmmmmm. Any thoughts anyone might have on this are appreciated. **************************************************************** From: Tucker Taft Sent: Wednesday, August 1, 2007 11:37 AM Although it needs explicit clarification, I believe that access parameters and access discriminants should be permitted without restriction in Remote_Types packages. I believe "remote access types" are only the *named* access types declared in the visible part. Similarly, I believe our various additional sorts of anonymous access types should be permitted without restriction, except the existing restriction that all visible types that have streaming attributes must support external streaming. On the other hand, in RCI packages, access parameters have significant restrictions. It sounds like at a minimum we need an AI to clarify the rules for anonymous access types and Remote_Types packages. **************************************************************** From: Randy Brukardt Sent: Thursday, August 2, 2007 12:19 AM > Although it needs explicit clarification, I believe > that access parameters and access discriminants should be > permitted without restriction in Remote_Types packages. > I believe "remote access types" are only the *named* access > types declared in the visible part. Similarly, I believe > our various additional sorts of anonymous access types > should be permitted without restriction, except the > existing restriction that all visible types that have > streaming attributes must support external streaming. "without restriction" is clearly wrong. You surely want the basic restrictions on remote types to apply to anonymous types used as components/discriminants (not sure about parameters). In particular, you do not want to allow: type Something (D : access Integer) is record A : Character; end record; in a Remote_Types package unless this type has user-defined stream attributes; it isn't externally streamable without that. And I doubt very much that we want to repeal that requirement just because there is an access discriminant. > On the other hand, in RCI packages, access parameters > have significant restrictions. > > It sounds like at a minimum we need an AI to clarify > the rules for anonymous access types and Remote_Types > packages. I admit that I can't quite figure out what the purpose of Remote_Types packages are supposed to be. The description seems to imply that having subprograms in the package doesn't make sense, but that doesn't seem to be the case in practice. So I can't tell what the rules for anonymous access parameters ought to be. (Other than that they shouldn't exist in the first place, but that's a discussion best had over several bottles of wine or beer. :-) **************************************************************** From: Brad Moore Sent: Tuesday, January 15, 2008 12:14 PM I have been looking into the AI assigned to me regarding potentially allowing limited interfaces as remote types. One of the questions raised in the discussion for the AI was whether it made sense for synchronous interfaces (protected and task) to be allowed as remote access types. The overall sense so far is that this would not fly, due to difficulties in defining semantics and implementing those semantics, but it would be interesting to see what others thought. A couple of points to add to the discussion so far; E.4 (17) states "All forms of remote subprogram calls are potentially blocking operations (see 9.5.1)." If protected interfaces were to be allowed as remote access types it would seem to imply that all procedures of the interface would need to be implemented as entries to work with the model of the protected types. Also, this would seem to rule out functions since those are not supposed to be potentially blocking. Maybe functions and procedures could be implemented as regular subprograms, but those would be local calls that could call entries of the protected object which would be remote. Here are some relevant excerpts from private emails on this topic. --------------------------------------- From: Bob Duff Sent: Tuesday, Jan 08, 2008 7:11 PM Brad Moore wrote: > I am investigating AI05-0060. Do you think that Synchronized > interfaces should be allowed as remote types? Protected types were designed with tightly coupled, shared memory multiprocessing systems in mind. So no, I don't think it would be wise to support synchronized interfaces as remote types. I think it would be quite difficult to define the semantics of distributed entry and protected subprogram calls, and it would no doubt be quite difficult to implement. > synchronized capabilities considered farther in the future, > maybe Ada 2015? Well, that's up to ARG, but I doubt synchronized remote types would fly. --------------------------------------- From: Ed Schonberg Sent: Tuesday, Jan 15, 2008 3:00 PM I don't think this will fly. Protected types are intended for synchronization over shared data in a common memory space. Using them across partitions confuses distributed systems with shared memory systems. For the foreseable future heterogeneous systems are with us, and we need different mechanisms for different layers, no? **************************************************************** From: Jean-Pierre Rosen Sent: Tuesday, January 15, 2008 2:59 PM > The overall sense so far is that this would not fly, due to difficulties > in defining semantics and implementing those semantics, but it would be > interesting to see what others thought. Hmm.. Thinking about it... What about a remote requeue? **************************************************************** From: Tucker Taft Sent: Tuesday, January 15, 2008 3:39 PM > The overall sense so far is that this would not fly, due to difficulties > in defining semantics and implementing those semantics, but it would be > interesting to see what others thought. Based on my answers below, I don't see any insurmountable problems. Concocting "stub" protected/task types might be a bit tricky, but I suspect you could just make them very simple, with all of the interesting information accessible via an access discriminant. E.g. type Remote_Task is task interface; procedure Remote_Op_1(RT : Remote_Task; ...) is abstract; function Remote_Op_2(RT : Remote_Task; ...) return Integer is abstract; ... task type Stub_For_Remote(Comm_Info : access Comm_Info_Record) is new Remote_Task with entry Quit_Now; end Stub_For_Remote; -- body probably consists of a single selective_accept -- that waits to accept Quit_Now or terminate. procedure Remote_Op_1(SFR : Stub_For_Remote; ...); function Remote_Op_2(SFR : Stub_For_Remote; ...) return Integer; -- These calling stubs marshall the parameters -- and call the PCS, and then the receiving stubs -- call the corresponding operations of the "real" -- task type that implements Remote_Task. > A couple of points to add to the discussion so far; > > E.4 (17) states "All forms of remote subprogram calls are potentially > blocking operations (see 9.5.1)." > > If protected interfaces were to be allowed as remote access types it > would seem to imply that all procedures of the interface would need to > be implemented as entries to work with the model of the protected types. I don't see this. Remember that there are three possibilities with a primitive of a protected interface. It can be implemented directly as a protected subprogram, it can be implemented as an entry (presuming it is visibly declared as a procedure), and it can be implemented as a "regular" subprogram which turns around and calls one or more protected operations. The only one of these that is non-blocking is the one that is implemented directly as a protected subprogram. > Also, this would seem to rule out functions since those are not supposed > to be potentially blocking. Only if they are implemented directly as a protected subprogram. Not if they are implemented as a "normal" subprogram. > Maybe functions and procedures could be implemented as regular > subprograms, but those would be local calls that could call entries of > the protected object which would be remote. Sorry, I don't follow this. If it is an access-to-remote subprogram, then any dispatching call is a remote call. Once you get to the "other" side, then you would call the implementing subprogram/protected-operation. My conclusion is that using synchronized interfaces is not a big problem, but that the newly proposed pragma "Implemented" (or whatever it is called) could not specify "By_Entry" or "By_Protected_Procedure" for these, since trying to do a requeue on one of these or expecting non-blocking behavior would be too difficult to accomplish. > Here are some relevant excerpts from private emails on this topic. I don't fully agree with Bob and Ed. Synchronized interfaces guarantee multi-thread-safe access to the underlying data. They don't guarantee non-blocking behavior, even for protected interfaces. Protected interfaces pretty much guarantee that there is no separate thread associated with the object, whereas task interfaces guarantee that there is at least one thread associated with the object, but that is about it. None of these guarantees seem to be incompatible with remote execution. And in fact, it would seem highly desirable to use synchronized interfaces for remote interfaces, so they could support concurrent simultaneous access from multiple threads potentially spread across multiple partitions. One might even go so far as to recommend using synchronized interfaces when doing things remotely. ****************************************************************