Version 1.6 of ai05s/ai05-0060-1.txt

Unformatted version of ai05s/ai05-0060-1.txt version 1.6
Other versions for file ai05s/ai05-0060-1.txt

!standard E.2(14)          08-02-01 AI05-0060-1/03
!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 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 do not need to utilize or support Annex E pragmas in standard library library_unit_declarations if the implementation does not support Annex E.
The definition of remote access types is clarified to only apply to named access types. Anonymous access types may be used as access discriminants, access parameters, and access components of remote types, but they themselves cannot be used remotely except within the context of the containing construct.
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 be 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 class-wide limited private type is allowed in a remote access type. Shouldn't a limited interface be allowed?
(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 be 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? (Maybe, but if so, this should be dealt with in a separate AI)
(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 Annex E 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 E.2(14):
An implementation may insert a comment preceding Annex E pragmas in library_unit_declarations of standard library packages if the implementation does not conform to Annex E. The corresponding library_unit_body and the private part(s) of the library_unit_declaration, if present, would then not need to adhere to the restrictions that otherwise would have been imposed by the pragmas.
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 {or 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):
* The primitive subprograms of the corresponding specific type shall not be implemented by protected subprograms or entries.
Add three new paragraphs after E.2.2(18)
6 Anonymous access types may be used as access discriminants, access parameters, and access components of remote types, but they themselves cannot be used remotely except within the context of the containing construct.
7 The value of a remote access to class-wide limited interface can be an object of a nonlimited type derived from the interface.
8 A remote access type may be a class-wide synchronized interface type, a class-wide protected interface type, or a class-wide task interface type, since these interface types are limited interface types.
!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 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. 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 comment out the Annex E 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 Annex E 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 only designate 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 limited interface types, then this would mean that 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 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 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. This would be a more radical change however, and should perhaps be considered in a separate AI. This AI just relaxes the restriction enough to allow remote access types to designate limited interface types, which adds maximum remote access capability for the minimal amount of change to the RM.
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 such interface types can be used as remote access 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 implemented by protected subprograms, since protected subprograms are not supposed to be potentially blocking operations. Interfaces could be used however, where the primitive subprograms are implemented by normal subprograms, (i.e., not implemented by protected subprograms or task entries), since these sorts of calls can be potentially blocking. Such calls could call protected subprograms of the object directly.
On the surface, being able to call task entries 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 capability would be worth considering in a separate AI and dealt with using a different time schedule than would be needed to implement the changes needed for this AI. Therefore, the approach for now is to disallow remote entry calls until such time that such a feature could be introduced to the language. As a result, the wording for this AI will disallow remote access types of limited interface types where primitive subprograms are 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.
The final point is that E.2.2(14/2) rules out passing remote access types as parameters to other remote access 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.
Overall, being able to use limited interfaces as remote access types seems like a useful capability that can be added to the language with a relatively low level of effort. This AI may pave the way for future capabilities such as remote entry calls, and remote requeue which might give Ada a further advantage over other languages. It may be that using limited interfaces as remote access types could become the preferred way to do remote calls.
-- !corrigendum E.2.2(9/1)
!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.

****************************************************************

Questions? Ask the ACAA Technical Agent