OSF DCE Application Development Guide--Introduction and Style Guide

RPC Parameters
6.3.3.2 Pointer Types
For reasons of efficiency, IDL distinguishes between reference [ref], full [ptr], and
unique [unique] pointers. As we saw above, even though pointers are used by
applications to pass data by reference, the lack of shared address space means that the
stubs have to pass the data by value and provide the receiver with a reference to the
passed data.
In the simplest case, a pointer always points to the same memory: that is, its value does
not change. In such a case the stubs always marshall the passed value from and to the
same memory location on the sender and receiver respectively. This style of marshalling
is provided by [ref] pointers.
When the value of a pointer changes during a call, the stubs have a more complex task.
Suppose, for example, an [in, out] pointer is NULL before an RPC and is set by the
server application to point to some data structure allocated by the server. As in the [ref]
pointer case, the server stub needs to marshall the (new) referent and the client to
unmarshall it, but the client stub also needs to do two more things: it needs to allocate
space for the unmarshalled referent, and it needs to point the previously NULL pointer to
it. Similarly, for a pointer that initially points to one memory location and is changed
during an RPC to point to another, the client stub needs to allocate new memory to hold
the unmarshalled value of the new referent and to change the pointer value accordingly.
Not all of the extra work is confined to the client stub either. Obviously, the client stub
needs to find out that the value of the pointer has changed, so the server has to marshall,
and the RPC protocol to transmit, extra data to indicate this. This style of marshalling is
provided by full ([ptr]) pointers, and it obviously requires more overhead than reference
pointer marshalling.
Unique pointers provide for an intermediate case: a pointer that always points either to a
single memory location or is NULL. Such a pointer may change from NULL to a
nonnull value or from a nonnull value to NULL, but never has more than one nonnull
value. Such a pointer is marshalled more efficiently than a full pointer, but not as
efficiently as a reference pointer.
Applications should consider the [ref] and [unique] pointer types as optimizations. A
full [ptr] pointer can always be used. The [ref] and [unique] pointer types may be used
whenever the application is guaranteed to meet the restrictive conditions under which
these types work.
As a guide to using the pointer types, there are a few general rules and a number of
special cases, having mainly to do with embedded pointers and data of variable size.
The rules are as follows:
In passing parameters, you need to distinguish carefully between top-level and
lower-level pointers. A top-level pointer is a pointer passed as an argument to a call.
A lower-level pointer is one contained in the referent of a top-level pointer. The
directional semantics [out] and [in, out] both require parameters to be passed by
reference and hence always require a top-level pointer.
The model is, essentially, that the client provides a container into which the returned
value is written. In the [out] parameter case, the contents of the container are
assumed to be unimportant on input and are not marshaled by the client stub. In the
[in, out] case, the contents are assumed to be meaningful and are passed to the
124246 Tandem Computers Incorporated 6 11