Proposed pvData.h interface

This commit is contained in:
Marty Kraimer
2013-06-18 10:01:52 -04:00
parent 3de28e3cef
commit ec6b67ffad

View File

@@ -37,7 +37,7 @@
<h1>EPICS Array</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 13-Jun-2013</h2>
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 18-Jun-2013</h2>
<dl>
<dt>Latest version:</dt>
@@ -67,14 +67,398 @@ license.</a></p>
<h2>Introduction</h2>
<p>This is the documentation for the scalarArray data type as defined by pvDataCPP-md.
When complete it will be merged into pvDataCPP.html.
Only sharedVector is currently documented.
It is documented in the next section, but when merged into pvDataCPP.html,
will appear in a later section.
For now ignore the documentation in pvDataApp/pv.</p>
<p>When <b>NOTE EXISTING</b> appears it means that there is a question about
the existing shared_vector implementation.</p>
<p>This is the documentation for pvData.h as defined by pvDataCPP-md.
When complete it will be merged into pvDataCPP.html.</p>
<p>
pvData provides an interface for network accessible structured data.
The interfaces for C++ and Java are similar.
Thus someone who understands the interface in one of the languages
and knows both languages will quickly understand the interface of the other language.
With only a few exceptions the naming and other conventions do
not follow the C++ standard library conventions.
The definition of pvData is similar to the definition for Java.
The differences are mainly related to language differences.
Some differences are:
<dl>
<dt>shared pointers</dt>
<dd>Java has a garbage collector. In C++ the implementation manages
memory. The primary tool is std::tr1::shared_ptr.</dd>
<dt>PVArray</dt>
<dd>The Java garbage collector allows raw data arrays, e. g. int[],
to be shared. For C++ a shared_vector holds the raw data.
</dd>
<dt>ostream replaces toString</dt>
<dd>In Java every object has method toString.
For C++ operator&lt;&lt; replaces toString</dd>
<dt>shared_vector</dt>
<dd>This is similar to std::vector but uses a shared_ptr to wrap the raw
data and also supports a window into the raw data. It does follow
naming and other conventions for C++ standard library containers.</dd>
</dl>
<p>There is one big difference from the existing Java implelentation:
The method PVValueArray::get.
As an example the Java definition for PVDoubleArray is currently:
<pre>
int get(int offset, int length, DoubleArrayData data);
</pre>
This document assumes this be replaced by:
<pre>
double[] get();
</pre>
<p>The existing version allowed the data source to provide the array in chunks.
The new version assumes that the data source always provides contiguous storage
for the entire raw array. If this is accepted it simplifies a lot of code.
</p>
<p>Three topics not discussed in this document are:
<dl>
<dt>pvDataCreate</dt>
<dd>There should be a new method something like:
<pre>
PVScalarArrayPtr createPVScalarArray(const PVScalarArray &amp;, size_t offset, size_t length);
</pre>
This will share the raw data array but allow a new window.
</dd>
<dt>convert</dt>
<dd>This will be changed to do conversions itself instead of calling
methods like getAs. It will again support methods toXXXArray and fromXXXArray,
with a raw array replaced by a shared_vector.
Templates should be able to minimize the code required.</dd>
<dt>PVStructureArray</dt>
<dd>Can this also use shared_vector to hold elements?</dd>
</dl>
</p>
<h2>pvDataApp/pv</h2>
<h3>pvData.h</h3>
<p>This provides the interface for network accessible data.
Although templates are used to minimize the amount of code,
the interface is <b>not</b> meant to be extended.
Only the types defined by pvIntrospect are implemented.</p>
<h4>PVField</h4>
<pre>
class PVField
: virtual public Serializable,
public std::tr1::enable_shared_from_this<PVField>
{
public:
POINTER_DEFINITIONS(PVField);
virtual ~PVField();
virtual void message(String message,MessageType messageType);
const String&amp; getFieldName() const;
String getFullName() const;
virtual void setRequester(RequesterPtr const &amp;prequester);
std::size_t getFieldOffset() const;
std::size_t getNextFieldOffset() const;
std::size_t getNumberFields() const;
PVAuxInfoPtr &amp; getPVAuxInfo();
bool isImmutable() const;
void setImmutable();
const FieldConstPtr &amp; getField() const;
PVStructure * getParent() const;
void replacePVField(const PVFieldPtr&amp; newPVField);
void renameField(String const &amp; newName);
void postPut();
void setPostHandler(PostHandlerPtr const &amp;postHandler);
virtual std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o) const;
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o, size_t index) const;
...
};
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o, const PVFieldPtr &amp; f);
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o, const PVFieldPtr &amp; f, size_t index);
</pre>
<p>The public methods for PVField are:</p>
<dl>
<dt>~PVField</dt>
<dd>Destructor. Since shared pointers are used it should never be called by
user code.</dd>
<dt>message</dt>
<dd>Code attached to this field can call this method to report
problems.</dd>
<dt>getFieldName</dt>
<dd>Get the field name. If the field is a top level structure the field
name will be an empty string.</dd>
<dt>setRequester</dt>
<dd>Sets a requester to be called when message or getRequesterName are
called. This is only legal for the top level PVField. </dd>
<dt>getFieldOffset</dt>
<dd>Get offset of the PVField field within top level structure. Every field
within the PVStructure has a unique offset. The top level structure has
an offset of 0. The first field within the structure has offset equal to
1. The other offsets are determined by recursively traversing each
structure of the tree. </dd>
<dt>getNextFieldOffset</dt>
<dd>Get the next offset. If the field is a scalar or array field then this
is just offset + 1. If the field is a structure it is the offset of the
next field after this structure. Thus (nextOffset - offset) is always
equal to the total number of fields within the field. </dd>
<dt>getNumberFields</dt>
<dd>Get the total number of fields in this field. This is nextFieldOffset -
fieldOffset. </dd>
<dt>getPVAuxInfo</dt>
<dd>Get the PVAuxInfo for this field. PVAuxInfo is described below.</dd>
<dt>isImmutable</dt>
<dd>Is the field immutable?</dd>
<dt>setImmutable</dt>
<dd>Make the field immutable. Once a field is immutable it can never be
changed since there is no method to again make it mutable. This is an
important design decision since it allows immutable array fields to share
the internal primitive data array.</dd>
<dt>getField</dt>
<dd>Get the reflection interface for the data.</dd>
<dt>getParent</dt>
<dd>Get the interface for the parent or null if this is the top level
PVStructure.</dd>
<dt>replacePVField</dt>
<dd>Replace the data implementation for the field.</dd>
<dt>renameField</dt>
<dd>Rename the field name. </dd>
<dt>postPut</dt>
<dd>If a postHandler is registered it is called otherwise no action is
taken.</dd>
<dt>setPostHandler</dt>
<dd>Set the postHandler for the record. Only a single handler can be
registered.</dd>
<dt>operator&lt;&lt;</dt>
<dd>Stream output</dt>
</dl>
<h4>PVScalar</h4>
<pre>
class PVScalar : public PVField {
public:
POINTER_DEFINITIONS(PVScalar);
virtual ~PVScalar();
typedef PVScalar &amp;reference;
typedef const PVScalar&amp; const_reference;
const ScalarConstPtr getScalar() const;
...
};
</pre>
<p>where</p>
<dl>
<dt>getScalar</dt>
<dd>Get the introspection interface for the PVScalar.</dd>
</dl>
<h4>PVScalarValue</h4>
<pre>
template<typename T>
class PVScalarValue : public PVScalar {
public:
POINTER_DEFINITIONS(PVScalarValue);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
virtual ~PVScalarValue() {}
virtual T get() const = 0;
virtual void put(T value) = 0;
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o) const
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o, size_t index) const;
...
};
typedef PVScalarValue&lt;uint8&gt; PVBoolean;
typedef PVScalarValue&lt;int8&gt; PVByte;
typedef PVScalarValue&lt;int16&gt; PVShort;
typedef PVScalarValue&lt;int32&gt; PVInt;
typedef PVScalarValue&lt;int64&gt; PVLong;
typedef PVScalarValue&lt;uint8&gt; PVUByte;
typedef PVScalarValue&lt;uint16&gt; PVUShort;
typedef PVScalarValue&lt;uint32&gt; PVUInt;
typedef PVScalarValue&lt;uint64&gt; PVULong;
typedef PVScalarValue&lt;float&gt; PVFloat;
typedef PVScalarValue&lt;double&gt; PVDouble;
typedef std::tr1::shared_ptr&lt;PVBoolean&gt; PVBooleanPtr;
typedef std::tr1::shared_ptr&lt;PVByte&gt; PVBytePtr;
typedef std::tr1::shared_ptr&lt;PVShort&gt; PVShortPtr;
typedef std::tr1::shared_ptr&lt;PVInt&gt; PVIntPtr;
typedef std::tr1::shared_ptr&lt;PVLong&gt; PVLongPtr;
typedef std::tr1::shared_ptr&lt;PVUByte&gt; PVUBytePtr;
typedef std::tr1::shared_ptr&lt;PVUShort&gt; PVUShortPtr;
typedef std::tr1::shared_ptr&lt;PVUInt&gt; PVUIntPtr;
typedef std::tr1::shared_ptr&lt;PVULong&gt; PVULongPtr;
typedef std::tr1::shared_ptr&lt;PVFloat&gt; PVFloatPtr;
typedef std::tr1::shared_ptr&lt;PVDouble&gt; PVDoublePtr;
// PVString is special case, since it implements SerializableArray
class PVString : public PVScalarValue&lt;String&gt;, SerializableArray {
public:
virtual ~PVString() {}
...
};
</pre>
<p>where</p>
<dl>
<dt>get</dt>
<dd>Get the value stored in the object.</dd>
<dt>put</dt>
<dd>Change the value stored in the object.</dd>
<dt>operator&lt;&lt;</dt>
<dd>Methods for stream I/O.</dd>
</dl>
<h4>PVArray</h4>
<p>PVArray is the base interface for all the other PV Array interfaces. It
extends PVField and provides the additional methods:</p>
<pre>class PVArray : public PVField, public SerializableArray {
public:
POINTER_DEFINITIONS(PVArray);
virtual ~PVArray();
virtual std::size_t getLength() const = 0;
virtual void setLength(std::size_t length) = 0;
bool isCapacityMutable() const;
void setCapacityMutable(bool isMutable);
virtual std::size_t getCapacity() const = 0;
virtual void setCapacity(std::size_t capacity) = 0;
...
};</pre>
<dl>
<dt>getLength</dt>
<dd>Get the current length. This is less than or equal to the capacity.</dd>
<dt>setLength</dt>
<dd>Set the length. If the PVField is not mutable then an exception is
thrown. If this is greater than the capacity setCapacity is called.</dd>
<dt>isCapacityMutable</dt>
<dd>Is the capacity mutable</dd>
<dt>setCapacityMutable</dt>
<dd>Specify if the capacity can be changed.</dd>
<dt>getCapacity</dt>
<dd>Get the capacity, i.e. this is the size of the underlying data
array.</dd>
<dt>setCapacity</dt>
<dd>Set the capacity. The semantics are implementation dependent but
typical semantics are as follows: If the capacity is not mutable an
exception is thrown. A new data array is created and data is copied from
the old array to the new array. </dd>
</dl>
<h4>PVScalarArray</h4>
<p>PVScalarArray is the base class for scalar array data. PVValueArray is a
templete for the various scalar array data classes. There is a class for each
possible scalar type, i. e. PVBooleanArray, ..., PVStringArray.</p>
<pre>class PVScalarArray : public PVArray {
public:
POINTER_DEFINITIONS(PVScalarArray);
typedef PVScalarArray &amp;reference;
typedef const PVScalarArray&amp; const_reference;
virtual ~PVScalarArray();
const ScalarArrayConstPtr getScalarArray() const;
...
};
// PVString is special case, since it implements SerializableArray
class PVString : public PVScalarValue&lt;String&gt;, SerializableArray {
public:
virtual ~PVString() {}
...
};
</pre>
<p>where</p>
<dl>
<dt>getScalarArray</dt>
<dd>Get the introspection interface.</dd>
</dl>
<h4>PVValueArray</h4>
<p>This is a template class plus instances for PVBooleanArray, ...,
PVStringArray.</p>
<pre>template&lt;typename T&gt;
class PVValueArray :
public PVScalarArray
...
{
public:
POINTER_DEFINITIONS(PVValueArray);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef PVValueArray &amp; reference;
typedef const PVValueArray &amp; const_reference;
typedef shared_vector&lt;T&gt; svector;
typedef shared_vector&lt;const T&gt; const_svector;
virtual ~PVValueArray() {}
const_svector &amp; get();
size_t put(size_t offset,size_t length, const_svector &amp;from, size_t fromOffset);
void shareData(const_svector &amp;from);
virtual std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o) const;
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; o, size_t index) const;
...
};
typedef PVValueArray&lt;uint8&gt; PVBooleanArray;
typedef std::tr1::shared_ptr&lt;PVBooleanArray&gt; PVBooleanArrayPtr;
typedef PVValueArray&lt;int8&gt; PVByteArray;
typedef std::tr1::shared_ptr&lt;PVByteArray&gt; PVByteArrayPtr;
typedef PVValueArray&lt;int16&gt; PVShortArray;
typedef std::tr1::shared_ptr&lt;PVShortArray&gt; PVShortArrayPtr;
typedef PVValueArray&lt;int32&gt; PVIntArray;
typedef std::tr1::shared_ptr&lt;PVIntArray&gt; PVIntArrayPtr;
typedef PVValueArray&lt;int64&gt; PVLongArray;
typedef std::tr1::shared_ptr&lt;PVLongArray&gt; PVLongArrayPtr;
typedef PVValueArray&lt;uint8&gt; PVUByteArray;
typedef std::tr1::shared_ptr&lt;PVUByteArray&gt; PVUByteArrayPtr;
typedef PVValueArray&lt;uint16&gt; PVUShortArray;
typedef std::tr1::shared_ptr&lt;PVUShortArray&gt; PVUShortArrayPtr;
typedef PVValueArray&lt;uint32&gt; PVUIntArray;
typedef std::tr1::shared_ptr&lt;PVUIntArray&gt; PVUIntArrayPtr;
typedef PVValueArray&lt;uint64&gt; PVULongArray;
typedef std::tr1::shared_ptr&lt;PVULongArray&gt; PVULongArrayPtr;
typedef PVValueArray&lt;float&gt; PVFloatArray;
typedef std::tr1::shared_ptr&lt;PVFloatArray&gt; PVFloatArrayPtr;
typedef PVValueArray&lt;double&gt; PVDoubleArray;
typedef std::tr1::shared_ptr&lt;PVDoubleArray&gt; PVDoubleArrayPtr;
typedef PVValueArray&lt;String&gt; PVStringArray;
typedef std::tr1::shared_ptr&lt;PVStringArray&gt; PVStringArrayPtr;
</pre>
<p>where</p>
<dl>
<dt>get</dt>
<dd>Get the shared_vector that holds the data.
Code that calls this is able to modify the array elements
but should be very careful if it does.
For example it must call postPut after modifying the array elements.
It must also respect isImmutable().
</dd>
<dt>put</dt>
<dd>This is the recommended method for modifying the array elements.
It may change the capacity if len asks for more elements
than the cureent capacity allows.
It does not change the current length.
</dd>
<dt>shareData</dt>
<dd>Share data with an existing shared_vector.
Note that if capacity is every changed then data will no
longer be shared.</dd>
<dt>operator&lt;&lt;</dt>
<dd>Methods for stream I/O.</dd>
</dl>
<h2>shared_vector</h2>
<h3>Status</h3>
@@ -82,6 +466,8 @@ the existing shared_vector implementation.</p>
are now documented, but not all have a description or example.
Thus the documentation needs more work.
</p>
<p>When <b>NOTE EXISTING</b> appears it means that there is a question about
the existing shared_vector implementation.</p>
<h3>Introduction</h3>
<p>A shared_vector is a container as defined by the C++ standard library.
It is like std::vector but provides two additional features
@@ -738,260 +1124,6 @@ use_count 1 offset 0 count 16 total 16
<h4>specialization for untyped pointers</h4>
<p>Not yet documented</p>
<h2>pvDataApp/pv</h2>
<p><b>INGORE REST OF DOCUMENT!!!!</b></p>
<h3>pvData.h</h3>
<h4>PVArray</h4>
<p>PVArray is the base interface for all the other PV Array interfaces. It
extends PVField and provides the additional methods:</p>
<pre>class PVArray : public PVField, public SerializableArray {
public:
POINTER_DEFINITIONS(PVArray);
virtual ~PVArray();
virtual void setImmutable();
std::size_t getLength() const;
virtual void setLength(std::size_t length);
std::size_t getCapacity() const;
bool isCapacityMutable() const;
void setCapacityMutable(bool isMutable);
virtual void setCapacity(std::size_t capacity) = 0;
...
};</pre>
<dl>
<dt>setImmutable</dt>
<dd>Set the data immutable. Note that this is permanent since there is no
methods to make it mutable.</dd>
<dt>getLength</dt>
<dd>Get the current length. This is less than or equal to the capacity.</dd>
<dt>setLength</dt>
<dd>Set the length. If the PVField is not mutable then an exception is
thrown. If this is greater than the capacity setCapacity is called.</dd>
<dt>getCapacity</dt>
<dd>Get the capacity, i.e. this is the size of the underlying data
array.</dd>
<dt>setCapacity</dt>
<dd>Set the capacity. The semantics are implementation dependent but
typical semantics are as follows: If the capacity is not mutable an
exception is thrown. A new data array is created and data is copied from
the old array to the new array. </dd>
<dt>isCapacityMutable</dt>
<dd>Is the capacity mutable</dd>
<dt>setCapacityMutable</dt>
<dd>Specify if the capacity can be changed.</dd>
<dt>setCapacity</dt>
<dd>Set the capaciity.</dd>
</dl>
<h4>PVScalarArray</h4>
<p>PVScalarArray is the base class for scalar array data. PVValueArray is a
templete for the various scalar array data classes. There is a class for each
possible scalar type, i. e. PVBooleanArray, ..., PVStringArray.</p>
<pre>class PVScalarArray : public PVArray {
public:
POINTER_DEFINITIONS(PVScalarArray);
virtual ~PVScalarArray();
typedef PVScalarArray &amp;reference;
typedef const PVScalarArray&amp; const_reference;
const ScalarArrayConstPtr getScalarArray() const ;
virtual std::ostream&amp; dumpValue(std::ostream&amp; o, size_t index) const = 0;
...
}</pre>
<p>where</p>
<dl>
<dt>getScalarArray</dt>
<dd>Get the introspection interface.</dd>
<dt>dumpValue</dt>
<dd>Method for streams I/O.</dd>
</dl>
<h4>PVValueArray</h4>
<p>This is a template class plus instances for PVBooleanArray, ...,
PVStringArray.</p>
<pre>template&lt;typename T&gt;
class PVValueArray : public PVScalarArray {
public:
POINTER_DEFINITIONS(PVValueArray);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef PVArrayData&lt;T&gt; ArrayDataType;
typedef std::vector&lt;T&gt; vector;
typedef const std::vector&lt;T&gt; const_vector;
typedef std::tr1::shared_ptr&lt;vector&gt; shared_vector;
typedef PVValueArray &amp; reference;
typedef const PVValueArray &amp; const_reference;
virtual ~PVValueArray() {}
virtual std::size_t get(
std::size_t offset, std::size_t length, ArrayDataType &amp;data) = 0;
virtual std::size_t put(std::size_t offset,
std::size_t length, const_pointer from, std::size_t fromOffset) = 0;
virtual std::size_t put(std::size_t offset,
std::size_t length, const_vector &amp;from, std::size_t fromOffset);
virtual void shareData(
shared_vector const &amp; value,
std::size_t capacity,
std::size_t length) = 0;
virtual pointer get() = 0;
virtual pointer get() const = 0;
virtual vector const &amp; getVector() = 0;
virtual shared_vector const &amp; getSharedVector() = 0;
std::ostream&amp; dumpValue(std::ostream&amp; o) const;
std::ostream&amp; dumpValue(std::ostream&amp; o, size_t index) const;
protected:
PVValueArray(ScalarArrayConstPtr const &amp; scalar)
: PVScalarArray(scalar) {}
friend class PVDataCreate;
};
template&lt;typename T&gt;
std::size_t PVValueArray&lt;T&gt;::put(
std::size_t offset,
std::size_t length,
const_vector &amp;from,
std::size_t fromOffset)
{ return put(offset,length, &amp;from[0], fromOffset); }
/**
* Definitions for the various scalarArray types.
*/
typedef PVArrayData&lt;uint8&gt; BooleanArrayData;
typedef PVValueArray&lt;uint8&gt; PVBooleanArray;
typedef std::tr1::shared_ptr&lt;PVBooleanArray&gt; PVBooleanArrayPtr;
typedef PVArrayData&lt;int8&gt; ByteArrayData;
typedef PVValueArray&lt;int8&gt; PVByteArray;
typedef std::tr1::shared_ptr&lt;PVByteArray&gt; PVByteArrayPtr;
typedef PVArrayData&lt;int16&gt; ShortArrayData;
typedef PVValueArray&lt;int16&gt; PVShortArray;
typedef std::tr1::shared_ptr&lt;PVShortArray&gt; PVShortArrayPtr;
typedef PVArrayData&lt;int32&gt; IntArrayData;
typedef PVValueArray&lt;int32&gt; PVIntArray;
typedef std::tr1::shared_ptr&lt;PVIntArray&gt; PVIntArrayPtr;
typedef PVArrayData&lt;int64&gt; LongArrayData;
typedef PVValueArray&lt;int64&gt; PVLongArray;
typedef std::tr1::shared_ptr&lt;PVLongArray&gt; PVLongArrayPtr;
typedef PVArrayData&lt;uint8&gt; UByteArrayData;
typedef PVValueArray&lt;uint8&gt; PVUByteArray;
typedef std::tr1::shared_ptr&lt;PVUByteArray&gt; PVUByteArrayPtr;
typedef PVArrayData&lt;uint16&gt; UShortArrayData;
typedef PVValueArray&lt;uint16&gt; PVUShortArray;
typedef std::tr1::shared_ptr&lt;PVUShortArray&gt; PVUShortArrayPtr;
typedef PVArrayData&lt;uint32&gt; UIntArrayData;
typedef PVValueArray&lt;uint32&gt; PVUIntArray;
typedef std::tr1::shared_ptr&lt;PVUIntArray&gt; PVUIntArrayPtr;
typedef PVArrayData&lt;uint64&gt; ULongArrayData;
typedef PVValueArray&lt;uint64&gt; PVULongArray;
typedef std::tr1::shared_ptr&lt;PVULongArray&gt; PVULongArrayPtr;
typedef PVArrayData&lt;float&gt; FloatArrayData;
typedef PVValueArray&lt;float&gt; PVFloatArray;
typedef std::tr1::shared_ptr&lt;PVFloatArray&gt; PVFloatArrayPtr;
typedef PVArrayData&lt;double&gt; DoubleArrayData;
typedef PVValueArray&lt;double&gt; PVDoubleArray;
typedef std::tr1::shared_ptr&lt;PVDoubleArray&gt; PVDoubleArrayPtr;
typedef PVArrayData&lt;String&gt; StringArrayData;
typedef PVValueArray&lt;String&gt; PVStringArray;
typedef std::tr1::shared_ptr&lt;PVStringArray&gt; PVStringArrayPtr;</pre>
<p>where</p>
<dl>
<dt>get( std::size_t offset, std::size_t length, ArrayDataType &amp;data)
</dt>
<dd>This method "exposes" it's internal array by setting data.data and
data.offset. The caller is responsible for copying the array elements.
This violates the principle that objects should not expose their internal
data but is done for efficency. For example it makes it possible to copy
between arrays with identical element types without requiring an
intermediate array.</dd>
<dt>put(std::size_t offset, std::size_t length, const_pointer from,
std::size_t fromOffset)</dt>
<dd>Put data into the array. from is a raw array.</dd>
<dt>put(std::size_t offset, std::size_t length, const_vector &amp;from,
std::size_t fromOffset)</dt>
<dd>Put data into the array from a vector holding the raw array.</dd>
<dt>shareData( shared_vector const &amp; value, std::size_t capacity,
std::size_t length)</dt>
<dd>Make the instance share the raw data from value.<br />
One use is
for immutable arrays. In this case the caller must set the PVArray to be
immutable. In the PVArray is not immutable then it is the applications
responsibility to coordinate access to the array. Again this violates the
principle that objects should not expose their internal data but is
important for immutable arrays. For example pvData and the javaIOC define
many enumerated structures where an enumerated structure has two fields:
index and choices. Choices is a PVStringArray that holds the enumerated
choices. Index is a PVInt that is the index of the currently selected
choice. For many enumerated structures choices is immutable. Allowing the
choices internal String[] to be shared between all the instances of an
enumerated structure saves on storage.<br />
Another use for shared data is an application which processes an
array via multiple modules. Each accesses the internal data array of a
PVArray. In this case it is the applications responsibility
to coordinate access to the array.</dd>
<dt>get()</dt>
<dd>Get the raw array.</dd>
<dt>getVector()</dt>
<dd>Get the vector holding the raw array.</dd>
<dt>getSharedVector()</dt>
<dd>Get the shared vector holding the data.</dd>
<dt>dumpValue</dt>
<dd>Method for streams I/O.</dd>
</dl>
<p>Both get and put return the number of elements actually transfered. The
arguments are:</p>
<dl>
<dt>offset</dt>
<dd>The offset in the PV array.</dd>
<dt>len</dt>
<dd>The maximum number of elements to transfer. The number actually
transfered will be less than or equal to this value.</dd>
<dt>data</dt>
<dd>Get sets data.data to it's internal array and data.offset to the offset
into the array. The caller is responsible for the actual data
transfer.</dd>
<dt>from</dt>
<dd>The array from which the data is taken. This array is supplied by the
caller</dd>
<dt>fromOffset</dt>
<dd>The offset in from</dd>
</dl>
<p>The caller must be prepared to make multiple calls to retrieve or put an
entire array. A caller should accept or put partial arrays. For example the
following reads an entire array:</p>
<pre>void getArray(PVDoubleArrayPtr &amp; pv,DoubleArray const &amp; to)
{
size_t len = pv-&gt;getLength();
if(to.size()&lt;len) to.resize(len);
DoubleArrayData data;
size_t offset = 0;
while(offset&lt;len) {
size_t num = pv-&gt;get(offset,(len-offset),data);
DoubleArray &amp;from = data.data;
size_t fromOffset = data.offset;
for(size_t i=0; i&lt;num; i++) to[i+offset] = from[i + fromOffset];
offset += num;
}
} </pre>
</div>
</body>