Issue 3331: Valuetype "copying" semantics underspecified? (C++ issue # 1) (cxx_revision) Source: Floorboard Software (Mr. Jonathan Biggar, jon(at)floorboard.com) Nature: Uncategorized Issue Severity: Summary: C++ issue #1: The C++ specification should state that valuetype parameters which are copied by the ORB for collocated invocations are done using an ORB internal mechanism, not _copy_value(). Resolution: Revised Text: Actions taken: February 18, 2000: received issue Discussion: deferred in June 2011 to the next RTF End of Annotations:===== Sender: jbiggar@corvette.floorboard.com Message-ID: <38ADE431.5DB226E9@floorboard.com> Date: Fri, 18 Feb 2000 16:30:41 -0800 From: Jonathan Biggar X-Mailer: Mozilla 4.7 [en] (X11; U; SunOS 5.6 sun4u) X-Accept-Language: en MIME-Version: 1.0 To: issues@omg.org, orb_revision@omg.org, cxx_revision@omg.org Subject: Valuetype "copying" semantics underspecified? Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii X-UIDL: P=1!!4[W!!!$6e9Ik~!! [I've addressed this to the Core RTF and the C++ RTF because although there are some points related only to the C++ language mapping, I belive the larger issues apply across all language mappings. Jeurgen, please open the issues listed at the end of this message in the Core and C++ RTF issue listings.] I'm struggling with the implications of passing valuetypes as arguments to invocations on interfaces, and I think the specification is less than clear on several points, and in fact is broken in a couple of places. To set up the issue, an example: // IDL valuetype Twin { public Twin sibling; factory create(in Twin s); }; interface DNATest { boolean are_twins(in Twin t1, in Twin t2); }; // C++ client code DNATest_var lab = ...; // initialize from somewhere TwinFactory_var tf = ...; // initialize from somewhere Twin *t1 = tf->create(0); Twin *t2 = tf->create(t1); t1->sibling(t2); lab->are_twins(t1, t2); // C++ server code class MyDNATest : public POA_DNATest { ... CORBA::Boolean are_twins(Twin *t1, Twin *t2) { return t1->sibling() == t2 && t2->sibling() == t1; } ... }; Ok, here is my chain of logic: A. The spec requires [Core 5.2.4.3] that valuetypes passed as arguments to interface operations are received on the other end as copies of the original values. B. The spec also requires [Core 5.2.4.2] that sharing relationships in and between parameters of the invocation are maintained by the copies that are generated. Conclusion 1: The implementation of the are_twins() operation presented in the example should work as expected, even though it is operating on a copy of the original Twin valuetypes. (Propositions A & B taken together require that the boolean expression in the are_twins() operation be true as well.) C. The copying and sharing rules in propositions A & B hold whether or not the interface in question is collocated with the client. [C++ 1.22, also implied by Core] D. The programmer provides an overriding implementation of _copy_value() for each valuetype implementation. [Assumption, see OMG Issue ???? posted on 2/16/00] Conclusion 2: The ORB can't use ValueBase::_copy_value() to create copies for collocated invocations. (Since _copy_value() has no way of taking into context multiple parameters of an operation invocation, it can't possibly do the right thing to preserve the proper semantics for the are_twins() operation above. Using _copy_value on each argument would result in two pairs of twins!) Conclusion 3: The semantics of _copy_value() as documented in the C++ specification is considered harmful and should be removed. (Since the ORB can't use it, and yet must provide its own copying mechanism, there is little value to requiring the programmer to provide a (possibly buggy) implementation of _copy_value(). The ORB provided mechanism should instead be made available for use in client code.) ------------------------------------------------------------------------------- So here are the formal issues: C++ issue #1: The C++ specification should state that valuetype parameters which are copied by the ORB for collocated invocations are done using an ORB internal mechanism, not _copy_value(). Sender: jon@corvette.floorboard.com Message-ID: <3AD78411.8DA6C7FD@floorboard.com> Date: Fri, 13 Apr 2001 15:56:17 -0700 From: Jonathan Biggar X-Mailer: Mozilla 4.75 [en] (X11; U; SunOS 5.7 sun4u) X-Accept-Language: en MIME-Version: 1.0 To: cxx_revision@omg.org Subject: Proposal for issue 3326, 3331 & 3332 for vote 3 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii X-UIDL: 2/9e9`,;e9Fa#!!e+Ge9 Issue 3326: ValueBase::_copy_value() function is underspecified Summary: The CORBA 2.3 C++ mapping is clear on what the use of ValueBase::_copy_value is, but is unclear as to who is responsible for providing an overriding definition of this pure virtual function. Is it the IDL compiler, generating an overriding _copy_value() function for each valuetype C++ class, or is the user, when he provides a valuetype implementation class? Issue 3331: Valuetype "copying" semantics underspecified? Summary: C++ issue #1: The C++ specification should state that valuetype parameters which are copied by the ORB for collocated invocations are done using an ORB internal mechanism, not _copy_value(). Issue 3332: Valuetype "copying" semantics underspecified? Summary: C++ issue #2: The ValueBase::_copy_value() function should be deprecated in favor of a new ValueBase::_clone_value() operation. ------------------------------------------------------------------------------- Discussion: The ValueBase::_copy_value() function is problematical. As specified, it must be provided by a valuetype implementation, but it lacks sufficient mechanism to avoid infinite loops when copying a valuetype graph that contains cycles. This suggests that ORBs must not use _copy_value() when it is doing internal copying of valuetype graphs (to maintain location transparency for collocated calls, for example), but must use another internal mechanism to produce a copy. However, this fails when presented with custom valuetypes, since the ORB has no ability to access the internal state of a custom valuetype. Thus, the ORB must fallback to calling _copy_value() for custom valuetypes, which leads back to the problem of valuetype graph cycles. Also, as a stylistic point, Table 1-2 in section 1.17.5 seems to be out of norm for the usual way that member functions are described in the specification. I think we just change this table into prose paragraphs instead. Resolution: Deprecate ValueBase::_copy_value() in favor of a new interface that handles valuetype graph cycles, and at the same time provides an interface that a programmer can use to copy a valuetype graph. Proposal: In section 1.17.5, add the following to the declaration of CORBA::ValueBase: namespace CORBA { class ValueBase { public: ... private: virtual ValueBase *_clone_valuetype(ValueCopyContext *context) { return _copy_valuetype(); } ... }; } Change Table 1-2 in section 1.17.5 to separate prose paragraphs, one describing _add_ref(), _remove_ref() and _refcount_value(), a second paragraph describing the new _clone_valuetype() function, and a third describing _copy_value(). ------------------------------------------------------------------------------ Add the following description of _clone_valuetype(): "The _clone_valuetype() function is used to construct a deep copy of the valuetype, and should be overridden by each valuetype implementation. This function must only be called by the ORB via the CORBA::clone_valuetype() function defined in section 1.17.5.1. The default implementation of this function just calls _copy_valuetype() for backwards compatibility with older code. The context argument is necessary to properly handle valuetype graphs that contain loops. ValueCopyContext is defined in IDL as an abstract valuetype using the normal C++ mapping: // IDL module CORBA { abstract valuetype ValueCopyContext { }; }; Here is an example of how to implement a _clone_valuetype() function: // IDL valuetype V { public V link; }; // C++ class MyV : public OBV_V { public: ... ValueBase *_clone_valuetype(CORBA::ValueCopyContext *context) { return new My_V(V::_downcast(CORBA::clone_valuetype(link(), context))); } ... }; ------------------------------------------------------------------------------ For the _copy_valuetype() paragraph, indicate that _copy_value() is deprecated by changing the text to: "The _copy_value() function is used to make a deep copy of the valuetype instance. This function must be overridden by each valuetype implementation. The copy returned by this function must have no connections with the original instance and must have a lifetime independent of that of the original. Use of this function is deprecated in favor of the new _clone_valuetype function." ------------------------------------------------------------------------------ Also, move this text from the description of _copy_value in Table 1-2 to a separate paragraph at the end of section 1.17.5 and edit to read: "Since C++ supports covariant return types, derived classes can override the _copy_value and _clone_value functions to return a pointer to the derived class rather than ValueBase*, but since covariant return types are still not commonly supported by commercial C++ compilers, the return value can also be ValueBase*, even for derived classes." ------------------------------------------------------------------------------ Finally, add the following to section 1.17.5.1: namespace CORBA { ValueBase *clone_valuetype(ValueBase *original); ValueBase *clone_valuetype(ValueBase *original, ValueCopyContext *&context); } ... The clone_valuetype() function makes a copy of a valuetype, and all valuetypes it references, preserving the pointer relationships between valuetypes in the copy. The first version can be used to copy a single valuetype instance, while the second version can be used to copy multiple valuetypes, preserving any relationships between those valuetypes. The context is an inout argument, and should be passed a zero pointer for the first call, usually by passing in a default initialized ValueCopyContext_var. Here is an example: CORBA::ValueBase *ov1; CORBA::ValueBase *ov2; CORBA::ValueCopyContext_var context; CORBA::ValueBase_var nv1 = CORBA::clone_valuetype(ov1, context); CORBA::ValueBase_var nv2 = CORBA::clone_valuetype(ov2, context); -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org