!standard A(4) 08-05-21 AI05-0060-1/07 !standard E.2.2(9/1) !standard E.2.2(9.2/1) !standard E.2.2(14/2) !standard E.2.2(18) !class binding interpretation 07-08-04 !status ARG Approved 6-0-2 08-02-09 !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 The RM should formally state implementations may omit pragma Remote_Types in standard library library_unit_declarations if the implementation does not conform to Annex E. The definition of remote access types is clarified to apply only to named access types. Remote access types should be allowed to designate class-wide limited interface types (including synchronous, task, and protected interface types). The value of a remote access-to-class-wide limited interface type can designate an object of a nonlimited type derived from the interface type. !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 remote access type is allowed to designated a class-wide limited private type. Shouldn't a limited interface be allowed? (Yes.) (2) It is possible to derive a nonlimited type from a limited interface type. If remote access types are allowed to designate class-wide limited interface types, should we allow the value of a remote access-to-class-wide limited interface type to designate a nonlimited object? (Yes.) (3) E.2.2(16/1) states that remote access types cannot be dereferenced except through dispatching calls. This would be the rule that would allow the value of a remote access-to-class-wide limited interface type to be an object of a nonlimited type. This rule also enforces the object to be treated as though it is a private type, since it disallows accessing components directly. If this rule enforces that remote access is limited and private in nature, should we allow remote access types to designate all class-wide types? (No.) (4) 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? (Yes.) (5) Should we formally say that Remote_Types pragmas have no effect on implementations that don't support Annex E? (Yes.) 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 Add a new paragraph after A(4): An implementation may omit pragma Remote_Types (see E.2.2) in language-defined library units if the implementation does not conform to Annex E. Modify E.2.2(9/1) as follows: A[n] {named} 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: Modify E.2.2(9.2/1) as follows: * a general access type that designates a class-wide limited private type, {, a class-wide limited interface type,} or a class-wide private [type] extension all of whose ancestors are either private [type] extensions {, limited interface types,} or limited private types. Modify E.2.2(14/2) as follows: * 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); Add a new paragraph after E.2.2(14/2): [Note: This depends on pragma Implemented, which was added by AI05-0030-2.] * The corresponding specific type shall not have a primitive procedure to which a pragma Implemented applies unless the implementation_kind of the pragma is By_Any; Add two new paragraphs after E.2.2(18): 6 The value of a remote access-to-class-wide limited interface can designate an object of a nonlimited type derived from the interface. 7 A remote access type may designate a class-wide synchronized, protected, or task interface type. !discussion Ada 2005 introduces interfaces and expanded usage of anonymous access types to the language. Annex E appears to rule out the use of interfaces as remote access types and lacks clarity in defining how access discriminants, access parameters, and access components can be used in a remote types library unit. Ada 2005 also introduces new standard libraries such as the container libraries. Many of these library units appear to be good candidates to become remote type library units. AI05-0084-1 looks at how this could be done. However, not all implementations conform to Annex E, and making these library units remote type library units would place restrictions on the units that could cause an implementor to have to redesign the corresponding library_unit_body in many cases. Moreover, 1.1.3(17) requires an implementation to reject (or raise an exception) for the use of unsupported Annex features, and we surely want all Ada compilers to be able to compile language-defined units. An implementor should not have to comply with these restrictions if their implementation does not conform to Annex E. To minimally impact implementations that do not care about Annex E, an allowance is needed in the RM to relax the restrictions for those cases. Specifying that an implementor is allowed to omit the Remote_Types pragmas in standard libraries seems to be the best way to do this in a consistent manner. Such an approach would not involve any changes to the compiler, and makes it more clear that the implementor is not conforming to Remote_Types restrictions. The main focus of this AI is to clarify the definition of remote types and remote access types. The model of a remote access type is that of a remote handle to an object that can only be operated through the use of remote dispatching calls. Components of the object cannot be remotely accessed directly, only indirectly though the dispatching calls. This is why the existing rules restrict remote access types to designate only private tagged types that are limited in nature whereby all components of the type are private. A limited interface type mostly satisfies these basic constraints. A limited interface does not have any visible components and is a tagged type. One main difference is that it is possible to derive a nonlimited type from a limited interface while it is not possible to derive a nonlimited type from a limited type. If remote access types are allowed to designate class-wide limited interface types, then the value of a remote access to class-wide limited interface can be an object of a nonlimited type derived from the interface. The remote (client) view of the object would still be the equivalent of a limited view however, because of rule E 2.2(16/1) which states that a value of a remote access-to-class-wide type shall be dereferenced (or implicitly converted to an anonymous access type) only as part of a dispatching call where the value designates a controlling operand of the call. The local (server) view of the object could be a nonlimited view. This would mean it could be possible to assign the object locally to a local variable, and that the object could be assigned a new value locally. This capability seems to be potentially useful and no issues could be found with allowing such usage. Since we are now saying that a remote access type can designate a nonlimited object, we need to ask whether it makes sense for remote access types to designate class-wide nonlimited private types and nonlimited interface types, or even more generally, any class-wide types. It seems like this could be workable, so long as the E.2.2(16/1) rule is upheld. This rule would ensure that the object designated by the remote access type can only be accessed as though it were limited and private. That is, the object could not be assigned and its components cannot be directly accessed remotely. Such a change would be a bigger change to the language however, and there are no known use cases that demonstrate a need for this capability that could not be covered by using a remote access-to-class-wide limited interface type. Therefore, it has been concluded that the restrictions for remote access types should not be relaxed any further than to just allow remote access-to-class-wide limited interface types. The other main difference between a value of a limited interface and a value of a limited private tagged type is that the value of a limited interface can designate a protected type or a task type, since synchronous interfaces, task interfaces, and protected interfaces are all considered limited interface types. Also, E.2.2(9.3/1) states that a type that is derived from a remote access type is a remote access type. Therefore we need to consider whether remote access types can designate such interface types. The first point to consider is that E.4(17) states that all forms of remote subprogram calls are potentially blocking operations. This would seem to rule out interfaces where primitive subprograms are required to be implemented by protected subprograms, since protected subprograms are not supposed to be potentially blocking operations. Synchronized interfaces could be used, however, where the primitive subprograms are "normal" as normal subprograms can contain potentially blocking operations (including calls on entries and protected subprograms). Normal primitive subprograms can even be implemented directly as entries or protected subprograms, as these are logicially a wrapper that makes the necessary call from a normal subprogram, and thus also can be potentially blocking. On the surface, being able to call task and protected entries remotely seems to be a powerful construct. Furthermore, such a language feature might allow the possibility of requeuing an entry to a remote object. For example, this could facilitate distributed applications whereby requests made to a central server are requeued to available replicated worker servers on a network. It is felt at this time that implementing remote requeue and remote entry calls would be quite difficult to implement. Such a capability might be worth considering in the the future. However, for now, we disallow remote access types of limited interface types where one or more primitive subprograms are required (by pragma Implemented, see AI05-0030-2) to be implemented by either protected subprograms or entries. Another question has to do with defining how the various kinds of access types can be used in a remote types package. The existing definition states that all access types declared in a remote access types declaration are remote access types. This does not fit well with anonymous access types such as access discriminants, access parameters, and access components. In particular, anonymous access discriminants and access components typically are not accessed remotely except through the containing construct. Certain types defined in remote types library units are not intended to be used as remote access types but only as remote types that can be passed by value remotely as parameters to a remote call. Such types might include primitives that accept anonymous access to subprogram parameters that are intended to be used only locally. For example, the standard container libraries have an Update_Element primitive subprogram that accepts an anonymous access to subprogram parameter. It is possible to conceive an interface however where an access to a remote subprogram is desired instead. There needs to be a way to distinguish between these usages. Since most anonymous access types are only intended to be used locally, limiting remote access types to be only named access types provides a clean way to distinguish usages. !corrigendum A(4) @dinsa The implementation may restrict the replacement of language-defined compilation units. The implementation may restrict children of language-defined library units (other than Standard). @dinst An implementation may omit pragma Remote_Types (see E.2.2) in language-defined library units if the implementation does not conform to Annex E. !corrigendum E.2.2(9/1) @drepl An access type declared in the visible part of a remote types or remote call interface library unit is called a @i. Such a type shall be: @dby A named access type declared in the visible part of a remote types or remote call interface library unit is called a @i. Such a type shall be: !corrigendum E.2.2(9.2/1) @drepl @xbullet @dby @xbullet !corrigendum E.2.2(14/2) @drepl @xbullet @dby @xbullet @xbullet Implemented applies unless the @fa of the pragma is By_Any;> !corrigendum E.2.2(18) @dinsa A remote types library unit need not be pure, and the types it defines may include levels of indirection implemented by using access types. User-specified Read and Write attributes (see 13.13.2) provide for sending values of such a type between active partitions, with Write marshalling the representation, and Read unmarshalling any levels of indirection. @dinss The value of a remote access-to-class-wide limited interface can designate an object of a nonlimited type derived from the interface. A remote access type may designate a class-wide synchronized, protected, or task interface type. !ACATS Test Add ACATS C-tests to check that limited interfaces are supported here. !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. **************************************************************** From: Brad Moore Sent: Thursday, January 24, 2008 9:48 AM >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. Remote Synchronous access types seem to be potentially quite useful. Since you can foresee a way to implement that might not be too difficult, I will plan to write up the AI assuming that synchronous interfaces are to be allowed, and see where that goes. I actually think it will be easier to write up that way because there would be less impact on the wording in the RM. >> 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 i>t 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. Right. I agree. I missed regular subprograms. Same goes for function calls. >> 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. Please disregard. I was assuming the synchronized interface idea wouldn't fly and was fishing for ideas that might salvage the concept, but hadn't thought them through fully. >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. The concept of Remote requeues seems like a powerful one. For example I am thinking of a centralized broker type server that can requeue requests to any of a number of available servers distributed on a network. It sounds like remote requeue would be difficult to implement now, but would be worth revisiting at some point in the future. In the meantime, the pragma "Implemented By_Entry" (or whatever it is called) could be required to disallow remote requeue until such point that remote requeueing is added to the language. That issue can be covered in the AI that deals with the proposed new pragmas, so I will plan to write up the AI on using limited interaces as remote access types without mentioning remote requeue. Remote Requeue seems like an issue deserving its own AI. The AI on the new Implemented pragmas should cover remote requeue for now. >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. Indeed. This sounds to me like a very interesting growth area for Ada to explore and consider for the future. **************************************************************** From: Brad Moore Sent: Thursday, January 24, 2008 10:25 AM One of the areas of investigation for AI05-0060-1 involve the question of how non-limited types derived from limited interfaces should be treated with respect to remote access types. Should they be allowed or disallowed? I have been looking at this, and my current thoughts are that they should be allowed. My reasoning is as follows; From a remote perspective, access to a remote classwide type were designed to be viewed with the semantics of a limited private type. That is, the access is like a handle. One cannot access components of the remote type directly, all functionality is accessed through remote dispatching calls on the handle. Also, it is important to disallow predefined assignment. An application should not need to be linked with the implementation of a remote type. A remote application should only need to know the specification or the interface to a remote type. Currently the RM ensures these qualities by requiring access type declaration in Remote_Type packages to be limited and only extenstions of private types or private types. We need to ensure that if we allow limited interface types to be used as remote access types, that non-limited derivations can be used without breaking the above properties. That is, it should not be possible to assign such a remote access type to another variable. I believe this is covered already by the existing rules. In particular; E 2.2 16/1 - A value of a remote access-to-class-wide type shall be dereferenced (or implicitly converted to an anonymous access type) only as part of a dispatching call where the value designates a controlling operand of the call (see E.4, “Remote Subprogram Calls”). The difference appears to me that before, this rule mostly came for free by implementing rule E 2.2 9 - 9.2/1 E.2.2 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: E.2.2 9.1/1 an access-to-subprogram type, or E.2.2 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. Now the implementation would need to ensure that if the object assigned to the access type is non-limited that E 2.2 16/1 still applies. It sounds to me like this would not be too difficult to implement. If you know the base type is both remote and limited then normal dereferencing should be disallowed. If we allow non-limited derived objects to be used with limited interface remote access types then I am thinking the RM would not need any additional changes to support this, (other than those needed already to support limited interface remote access types). Maybe there would need to be some note added to the AARM to explain this. On the other hand, if we want to disallow non-limited derived objects to be used as access to remote limited interface, then I think there would need to be an additional rule added to disallow this usage. I can see a need to be able to derive a non-limited type from a limited interface, and use assignment locally, but remotely only allow dispatching calls. This would let a programmer have the best of both worlds, and not be forced to choose between making a type non-limited or remote. Does anyone see a problem with this approach? If not, I will write up the AI assuming that non-limited derived objects can be assigned to remote access to limited interfaces. **************************************************************** From: Tucker Taft Sent: Thursday, January 24, 2008 12:32 PM I see no reason that the implementing type for a remote access-to-limited-interface needs itself to be limited. The limitness is important on the client side, but doesn't seem important on the server side. **************************************************************** From: Brad Moore Sent: Wednesday, January 30, 2008 2:05 PM When reviewing the proposed wording changes of AI05-0060, I realized there was a side benefit of one of the changes that has not yet been discussed, and seemed worthy of discussion. I have added the following question to the AI. E.2.2(14/2) states that access parameters are only allowed for the primitive subprograms of a remote access to class-wide types if they are controlling parameters, yet it seems to be useful to have non-controlling formal parameters that are remote access types to allow peer to peer systems. Should we allow remote access types to be passed as parameters to subprograms declared in Remote Types Library units? (Yes.) E.2.2(14/2) rules out passing remote access types as parameters to other remote access-to-class-wide types. This seems unintentional as it would be useful to pass handles to objects around remotely to allow dynamic objects to call each other. For example a peer to peer system could be setup where various remote objects could register with a central server using an RCI package. The central server could act as a switchboard, connecting client objects to each other by calling primitive registration subprograms of the objects passing in a cached handle to the other peer as a remote access type. To allow such usage, E.2.2(14/2) needs to be relaxed to allow remote access type parameters to be passed as non-controlling formal parameters to primitive subprograms of a remote access-to-class-wide type. I was proposing changing this rule as follows: * The primitive subprograms of the corresponding specific [limited private] type shall only have access parameters if they are controlling formal parameters {or remote access type parameters}; each non-controlling formal parameter shall support external streaming (see 13.13/2); Does anyone see any reasons why you shouldn't be able to pass remote access types to non-controlling formal subprograms of a remote-access-to-class-wide type? **************************************************************** From: Tucker Taft Sent: Wednesday, January 30, 2008 5:08 PM I think this is a bit confused. Remote access types may already be passed between partitions. E.2.2(14/2) is saying that the primitive subprograms of the *designated* type of a remote access type may only have access parameters if they are controlling parameters. They can certainly have parameters of a *named* access type, including the same remote access-to-class-wide type, so long as the type is externally streamable. Remote access types are by definition externally streamable. Unfortunately, I see that we lost the critical fact that remote access types are externally streamable in the Ada 2005 process! (Randy are you listening?) E.2.2(8/2) dropped the wording mentioning that only access types that are *non*-remote need user-defined read/write routines. Probably the right fix for this is to change the definition in 13.13.2 for externally streamable to include all remote access types automatically. That fix probably should be its own AI. **************************************************************** From: Randy Brukardt Sent: Wednesday, January 30, 2008 5:26 PM How soon they forget!! We approved such an AI (AI05-0065-1) at the meeting in Fairfax. Indeed, if you were using the working version of the AARM (available online only and only for ARG members) you would notice the updated wording in 13.13.2(52/3). **************************************************************** From: Tucker Taft Sent: Wednesday, January 30, 2008 5:41 PM Wow. My brain really is slipping... **************************************************************** From: Randy Brukardt Sent: Wednesday, January 30, 2008 8:42 PM > ... > * The primitive subprograms of the corresponding specific [limited private] > type shall only have access parameters if they are controlling formal > parameters {or remote access type parameters}; each non-controlling > formal parameter shall support external streaming (see 13.13/2); This change doesn't make sense. An access parameter is always an anonymous access (sub)type (parameters of named access types are *not* access parameters, see 6.1(24/2) for the formal definition of "access parameter". OTOH, your revised E.2.2(9/1) says that a remote access type is always a named access type. Thus, an access parameter can never be a "remote access type parameter" (whatever that is). So this is talking about apples and oranges and the addition adds nothing other than confusion. I suppose you could allow anonymous access types to *be* remote access types in very limited circumstances (presumably only for access-to-classwide), but that would need very different wording. And it's not clear that it is a good idea: I would think that it would be best to have only one type of remote "handle"; having a bunch of anonymous ones and converting between them surely would add complications without an obvious benefit. **************************************************************** From: Brad Moore Sent: Friday, February 1, 2008 10:40 AM >> * The primitive subprograms of the corresponding specific [limited private] >> type shall only have access parameters if they are controlling formal >> parameters {or remote access type parameters}; each non-controlling >> formal parameter shall support external streaming (see 13.13/2); > > This change doesn't make sense. An access parameter is always an anonymous > access (sub)type (parameters of named access types are *not* access > parameters, see 6.1(24/2) for the formal definition of "access parameter". You are right. I misread the sentence to mean any access parameter type, including named and anonymous access types. To get the meaning I was thinking of, I believe the sentence would have had to have specifed "access type parameters" instead of "access parameters". That is pretty subtle. I wonder if it would be helpful in the AARM HTML version if references to "access parameter"s could be hyperlinked to where the term is defined. That might have avoided the confusion in my case. The added clause, "or remote type parameters" above should be removed from the proposed wording changes. I have removed my added question and related text from AI05-0060. > I suppose you could allow anonymous access types to *be* remote access types > in very limited circumstances (presumably only for access-to-classwide), but > that would need very different wording. And it's not clear that it is a good > idea: I would think that it would be best to have only one type of remote > "handle"; having a bunch of anonymous ones and converting between them > surely would add complications without an obvious benefit. I tend to agree. It seems cleaner and simpler to just say that remote access types must be named access types. **************************************************************** From: Brad Moore Sent: Friday, February 1, 2008 10:57 AM Since we are now saying that a remote access type can designate a nonlimited object, we need to ask whether it makes sense for remote access types to designate class-wide nonlimited private types and nonlimited interface types, or even more generally, any class-wide types. It seems like this could be workable, so long as the E.2.2 16/1 rule is upheld. This rule would ensure that the object designated by the remote access type can only be accessed as though it were limited and private. That is, the object could not be assigned and its components cannot be directly accessed remotely. E.2.2(16/1) states that remote access types cannot be dereferenced except through dispatching calls. This would be the rule that would allow the value of a remote access-to-class-wide limited interface type to be an object of a nonlimited type. This rule also enforces the object to be treated as though it is a private type, since it disallows accessing components directly. If this rule enforces that remote access is limited and private in nature, should we allow remote access types to designate all class-wide types? **************************************************************** From: Tucker Taft Sent: Friday, February 1, 2008 1:50 PM Why not just use remote access-to-limited-classwide interface? I would rather not have the rules for remote access types diverge any more than necessary from those for normal access types. **************************************************************** From: Brad Moore Sent: Friday, February 1, 2008 2:44 PM That was my thought as well, which is why my current wording that I submitted to Randy earlier today suggests that though this is a possibility, it should be dealt with in a separate AI, if at all. The approach taken in AI05-0060 is to get maximum capability with minimal wording changes. (Best bang for the buck) I suppose one reason for adding this capability might be for added flexibility. Someone might have some pre-existing nonlimited types and suddenly decide they want to use remote access with these types, without having to change the types to be limited, which might be a lot of maintenance work for a pre-existing system. **************************************************************** From: Randy Brukardt Sent: Friday, February 1, 2008 3:20 PM I think Tuck's point was that you could add a limited interface to such a non-limited type without doing any other changes to the type. Then you could use the limited interface to represent the remote access type. Indeed, if we were doing this from scratch, it would make sense to allow *only* limited interfaces in this case, because they're really what is being implemented remotely (an interface, nothing more). The existing cases are essentially the implicit creation of a remote limited interface for the designated type. **************************************************************** From: Brad Moore Sent: Saturday, February 2, 2008 6:37 PM > I think Tuck's point was that you could add a limited interface to such a > non-limited type without doing any other changes to the type. Good point. I agree. I do not see any use cases that could not be covered by using a remote access to limited interface type. > Indeed, if we were doing this from scratch, it would make sense to allow > *only* limited interfaces in this case, because they're really what is being implemented > remotely (an interface, nothing more). This raises another question. If we want to recommend that remote access-to-class-wide types should designate limited interface types in Ada 2005, should we change the wording so that previously allowed remote access to class-wide limited private types or class-wide private extensions are obsolescent features described in Annex J? If we want to recommend the use of limited interface types, this might make it clearer that the previous uses should no longer be needed in Ada 2005 Regardless whether Annex J is involved, I think it probably makes sense that a note be added to Annex E to recommend limited interface types over other remote access-to-class-wide types for Ada 2005. I will assume that if changes should be made to Annex J, that those would be best covered in a separate AI, unless I hear otherwise. ****************************************************************