From ec6b67ffad27b1db7318e4b451cab0e9fc1f8f24 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Tue, 18 Jun 2013 10:01:52 -0400 Subject: [PATCH] Proposed pvData.h interface --- documentation/pvArray.html | 658 ++++++++++++++++++++++--------------- 1 file changed, 395 insertions(+), 263 deletions(-) diff --git a/documentation/pvArray.html b/documentation/pvArray.html index af43eb6..4b21ed5 100644 --- a/documentation/pvArray.html +++ b/documentation/pvArray.html @@ -37,7 +37,7 @@

EPICS Array

-

EPICS v4 Working Group, Working Draft, 13-Jun-2013

+

EPICS v4 Working Group, Working Draft, 18-Jun-2013

Latest version:
@@ -67,14 +67,398 @@ license.

Introduction

-

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.

-

When NOTE EXISTING appears it means that there is a question about -the existing shared_vector implementation.

+

This is the documentation for pvData.h as defined by pvDataCPP-md. +When complete it will be merged into pvDataCPP.html.

+

+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: +

+
shared pointers
+
Java has a garbage collector. In C++ the implementation manages + memory. The primary tool is std::tr1::shared_ptr.
+
PVArray
+
The Java garbage collector allows raw data arrays, e. g. int[], + to be shared. For C++ a shared_vector holds the raw data. +
+
ostream replaces toString
+
In Java every object has method toString. + For C++ operator<< replaces toString
+
shared_vector
+
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.
+
+

There is one big difference from the existing Java implelentation: +The method PVValueArray::get. +As an example the Java definition for PVDoubleArray is currently: +

+    int get(int offset, int length, DoubleArrayData data);
+
+This document assumes this be replaced by: +
+    double[] get();
+
+

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. +

+

Three topics not discussed in this document are: +

+
pvDataCreate
+
There should be a new method something like: +
+PVScalarArrayPtr createPVScalarArray(const PVScalarArray &, size_t offset, size_t length);
+      
+ This will share the raw data array but allow a new window. +
+
convert
+
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.
+
PVStructureArray
+
Can this also use shared_vector to hold elements?
+
+

+

pvDataApp/pv

+

pvData.h

+

This provides the interface for network accessible data. +Although templates are used to minimize the amount of code, +the interface is not meant to be extended. +Only the types defined by pvIntrospect are implemented.

+ +

PVField

+
+class PVField
+: virtual public Serializable,
+  public std::tr1::enable_shared_from_this
+{
+public:
+    POINTER_DEFINITIONS(PVField);
+    virtual ~PVField();
+    virtual void message(String message,MessageType messageType);
+    const String& getFieldName() const;
+    String getFullName() const;
+    virtual void setRequester(RequesterPtr const &prequester);
+    std::size_t getFieldOffset() const;
+    std::size_t getNextFieldOffset() const;
+    std::size_t getNumberFields() const;
+    PVAuxInfoPtr & getPVAuxInfo();
+    bool isImmutable() const;
+    void setImmutable();
+    const FieldConstPtr & getField() const;
+    PVStructure * getParent() const;
+    void replacePVField(const PVFieldPtr&  newPVField);
+    void renameField(String const & newName);
+    void postPut();
+    void setPostHandler(PostHandlerPtr const &postHandler);
+    virtual  std::ostream& operator<<(std::ostream& o) const;
+    std::ostream& operator<<(std::ostream& o, size_t index) const;
+...
+};
+
+std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
+std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f, size_t index);
+
+

The public methods for PVField are:

+
+
~PVField
+
Destructor. Since shared pointers are used it should never be called by + user code.
+
message
+
Code attached to this field can call this method to report + problems.
+
getFieldName
+
Get the field name. If the field is a top level structure the field + name will be an empty string.
+
setRequester
+
Sets a requester to be called when message or getRequesterName are + called. This is only legal for the top level PVField.
+
getFieldOffset
+
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.
+
getNextFieldOffset
+
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.
+
getNumberFields
+
Get the total number of fields in this field. This is nextFieldOffset - + fieldOffset.
+
getPVAuxInfo
+
Get the PVAuxInfo for this field. PVAuxInfo is described below.
+
isImmutable
+
Is the field immutable?
+
setImmutable
+
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.
+
getField
+
Get the reflection interface for the data.
+
getParent
+
Get the interface for the parent or null if this is the top level + PVStructure.
+
replacePVField
+
Replace the data implementation for the field.
+
renameField
+
Rename the field name.
+
postPut
+
If a postHandler is registered it is called otherwise no action is + taken.
+
setPostHandler
+
Set the postHandler for the record. Only a single handler can be + registered.
+
operator<<
+
Stream output +
+

PVScalar

+
+class PVScalar : public PVField {
+public:
+    POINTER_DEFINITIONS(PVScalar);
+    virtual ~PVScalar();
+
+    typedef PVScalar &reference;
+    typedef const PVScalar& const_reference;
+
+    const ScalarConstPtr getScalar() const;
+...
+};
+
+

where

+
+
getScalar
+
Get the introspection interface for the PVScalar.
+
+ +

PVScalarValue

+
+template
+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& operator<<(std::ostream& o) const
+    std::ostream& operator<<(std::ostream& o, size_t index) const;
+...
+};
+typedef PVScalarValue<uint8> PVBoolean;
+typedef PVScalarValue<int8> PVByte;
+typedef PVScalarValue<int16> PVShort;
+typedef PVScalarValue<int32> PVInt;
+typedef PVScalarValue<int64> PVLong;
+typedef PVScalarValue<uint8> PVUByte;
+typedef PVScalarValue<uint16> PVUShort;
+typedef PVScalarValue<uint32> PVUInt;
+typedef PVScalarValue<uint64> PVULong;
+typedef PVScalarValue<float> PVFloat;
+typedef PVScalarValue<double> PVDouble;
+typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
+typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
+typedef std::tr1::shared_ptr<PVShort> PVShortPtr;
+typedef std::tr1::shared_ptr<PVInt> PVIntPtr;
+typedef std::tr1::shared_ptr<PVLong> PVLongPtr;
+typedef std::tr1::shared_ptr<PVUByte> PVUBytePtr;
+typedef std::tr1::shared_ptr<PVUShort> PVUShortPtr;
+typedef std::tr1::shared_ptr<PVUInt> PVUIntPtr;
+typedef std::tr1::shared_ptr<PVULong> PVULongPtr;
+typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
+typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<String>, SerializableArray {
+public:
+    virtual ~PVString() {}
+ ...
+};
+
+ +

where

+
+
get
+
Get the value stored in the object.
+
put
+
Change the value stored in the object.
+
operator<<
+
Methods for stream I/O.
+
+ + +

PVArray

+ +

PVArray is the base interface for all the other PV Array interfaces. It +extends PVField and provides the additional methods:

+
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;
+ ...
+};
+
+
getLength
+
Get the current length. This is less than or equal to the capacity.
+
setLength
+
Set the length. If the PVField is not mutable then an exception is + thrown. If this is greater than the capacity setCapacity is called.
+
isCapacityMutable
+
Is the capacity mutable
+
setCapacityMutable
+
Specify if the capacity can be changed.
+
getCapacity
+
Get the capacity, i.e. this is the size of the underlying data + array.
+
setCapacity
+
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.
+
+ + +

PVScalarArray

+ +

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.

+
class PVScalarArray : public PVArray {
+public:
+    POINTER_DEFINITIONS(PVScalarArray);
+    typedef PVScalarArray &reference;
+    typedef const PVScalarArray& const_reference;
+
+    virtual ~PVScalarArray();
+    const ScalarArrayConstPtr getScalarArray() const;
+ ...
+};
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<String>, SerializableArray {
+public:
+    virtual ~PVString() {}
+ ...
+};
+
+ +

where

+
+
getScalarArray
+
Get the introspection interface.
+
+ +

PVValueArray

+ +

This is a template class plus instances for PVBooleanArray, ..., +PVStringArray.

+
template<typename T>
+class PVValueArray :
+public PVScalarArray
+...
+{
+public:
+    POINTER_DEFINITIONS(PVValueArray);
+    typedef T  value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef PVValueArray & reference;
+    typedef const PVValueArray & const_reference;
+
+    typedef shared_vector<T> svector;
+    typedef shared_vector<const T> const_svector;
+
+    virtual ~PVValueArray() {}
+    const_svector & get();
+    size_t put(size_t offset,size_t length, const_svector &from, size_t fromOffset);
+
+    void shareData(const_svector &from);
+
+    virtual std::ostream& operator<<(std::ostream& o) const;
+    std::ostream& operator<<(std::ostream& o, size_t index) const;
+...
+};
+
+typedef PVValueArray<uint8> PVBooleanArray;
+typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
+
+typedef PVValueArray<int8> PVByteArray;
+typedef std::tr1::shared_ptr<PVByteArray> PVByteArrayPtr;
+
+typedef PVValueArray<int16> PVShortArray;
+typedef std::tr1::shared_ptr<PVShortArray> PVShortArrayPtr;
+
+typedef PVValueArray<int32> PVIntArray;
+typedef std::tr1::shared_ptr<PVIntArray> PVIntArrayPtr;
+
+typedef PVValueArray<int64> PVLongArray;
+typedef std::tr1::shared_ptr<PVLongArray> PVLongArrayPtr;
+
+typedef PVValueArray<uint8> PVUByteArray;
+typedef std::tr1::shared_ptr<PVUByteArray> PVUByteArrayPtr;
+
+typedef PVValueArray<uint16> PVUShortArray;
+typedef std::tr1::shared_ptr<PVUShortArray> PVUShortArrayPtr;
+
+typedef PVValueArray<uint32> PVUIntArray;
+typedef std::tr1::shared_ptr<PVUIntArray> PVUIntArrayPtr;
+
+typedef PVValueArray<uint64> PVULongArray;
+typedef std::tr1::shared_ptr<PVULongArray> PVULongArrayPtr;
+
+typedef PVValueArray<float> PVFloatArray;
+typedef std::tr1::shared_ptr<PVFloatArray> PVFloatArrayPtr;
+
+typedef PVValueArray<double> PVDoubleArray;
+typedef std::tr1::shared_ptr<PVDoubleArray> PVDoubleArrayPtr;
+
+typedef PVValueArray<String> PVStringArray;
+typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
+
+ +

where

+
+
get
+
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(). +
+
put
+
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. +
+
shareData
+
Share data with an existing shared_vector. + Note that if capacity is every changed then data will no + longer be shared.
+
operator<<
+
Methods for stream I/O.
+

shared_vector

Status

@@ -82,6 +466,8 @@ the existing shared_vector implementation.

are now documented, but not all have a description or example. Thus the documentation needs more work.

+

When NOTE EXISTING appears it means that there is a question about +the existing shared_vector implementation.

Introduction

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

specialization for untyped pointers

Not yet documented

-

pvDataApp/pv

-

INGORE REST OF DOCUMENT!!!!

-

pvData.h

- -

PVArray

- -

PVArray is the base interface for all the other PV Array interfaces. It -extends PVField and provides the additional methods:

-
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;
- ...
-};
-
-
setImmutable
-
Set the data immutable. Note that this is permanent since there is no - methods to make it mutable.
-
getLength
-
Get the current length. This is less than or equal to the capacity.
-
setLength
-
Set the length. If the PVField is not mutable then an exception is - thrown. If this is greater than the capacity setCapacity is called.
-
getCapacity
-
Get the capacity, i.e. this is the size of the underlying data - array.
-
setCapacity
-
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.
-
isCapacityMutable
-
Is the capacity mutable
-
setCapacityMutable
-
Specify if the capacity can be changed.
-
setCapacity
-
Set the capaciity.
-
- - -

PVScalarArray

- -

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.

-
class PVScalarArray : public PVArray {
-public:
-    POINTER_DEFINITIONS(PVScalarArray);
-    virtual ~PVScalarArray();
-    typedef PVScalarArray &reference;
-    typedef const PVScalarArray& const_reference;
-    const ScalarArrayConstPtr getScalarArray() const ;
-    virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
- ...
-}
- -

where

-
-
getScalarArray
-
Get the introspection interface.
-
dumpValue
-
Method for streams I/O.
-
- -

PVValueArray

- -

This is a template class plus instances for PVBooleanArray, ..., -PVStringArray.

-
template<typename T>
-class PVValueArray : public PVScalarArray {
-public:
-    POINTER_DEFINITIONS(PVValueArray);
-    typedef T  value_type;
-    typedef T* pointer;
-    typedef const T* const_pointer;
-    typedef PVArrayData<T> ArrayDataType;
-    typedef std::vector<T> vector;
-    typedef const std::vector<T> const_vector;
-    typedef std::tr1::shared_ptr<vector> shared_vector;
-    typedef PVValueArray & reference;
-    typedef const PVValueArray & const_reference;
-
-    virtual ~PVValueArray() {}
-    virtual std::size_t get(
-         std::size_t offset, std::size_t length, ArrayDataType &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 &from, std::size_t fromOffset);
-    virtual void shareData(
-         shared_vector const & value,
-         std::size_t capacity,
-         std::size_t length) = 0;
-    virtual pointer get() = 0;
-    virtual pointer get() const = 0;
-    virtual vector const & getVector() = 0;
-    virtual shared_vector const & getSharedVector() = 0;
-    std::ostream& dumpValue(std::ostream& o) const;
-    std::ostream& dumpValue(std::ostream& o, size_t index) const;
-protected:
-    PVValueArray(ScalarArrayConstPtr const & scalar)
-    : PVScalarArray(scalar) {}
-    friend class PVDataCreate;
-};
-
-template<typename T>
-std::size_t PVValueArray<T>::put(
-    std::size_t offset,
-    std::size_t length,
-    const_vector &from,
-    std::size_t fromOffset)
-{ return put(offset,length, &from[0], fromOffset); }
-
-/**
- * Definitions for the various scalarArray types.
- */
-typedef PVArrayData<uint8> BooleanArrayData;
-typedef PVValueArray<uint8> PVBooleanArray;
-typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
-
-typedef PVArrayData<int8> ByteArrayData;
-typedef PVValueArray<int8> PVByteArray;
-typedef std::tr1::shared_ptr<PVByteArray> PVByteArrayPtr;
-
-typedef PVArrayData<int16> ShortArrayData;
-typedef PVValueArray<int16> PVShortArray;
-typedef std::tr1::shared_ptr<PVShortArray> PVShortArrayPtr;
-
-typedef PVArrayData<int32> IntArrayData;
-typedef PVValueArray<int32> PVIntArray;
-typedef std::tr1::shared_ptr<PVIntArray> PVIntArrayPtr;
-
-typedef PVArrayData<int64> LongArrayData;
-typedef PVValueArray<int64> PVLongArray;
-typedef std::tr1::shared_ptr<PVLongArray> PVLongArrayPtr;
-
-typedef PVArrayData<uint8> UByteArrayData;
-typedef PVValueArray<uint8> PVUByteArray;
-typedef std::tr1::shared_ptr<PVUByteArray> PVUByteArrayPtr;
-
-typedef PVArrayData<uint16> UShortArrayData;
-typedef PVValueArray<uint16> PVUShortArray;
-typedef std::tr1::shared_ptr<PVUShortArray> PVUShortArrayPtr;
-
-typedef PVArrayData<uint32> UIntArrayData;
-typedef PVValueArray<uint32> PVUIntArray;
-typedef std::tr1::shared_ptr<PVUIntArray> PVUIntArrayPtr;
-
-typedef PVArrayData<uint64> ULongArrayData;
-typedef PVValueArray<uint64> PVULongArray;
-typedef std::tr1::shared_ptr<PVULongArray> PVULongArrayPtr;
-
-typedef PVArrayData<float> FloatArrayData;
-typedef PVValueArray<float> PVFloatArray;
-typedef std::tr1::shared_ptr<PVFloatArray> PVFloatArrayPtr;
-
-typedef PVArrayData<double> DoubleArrayData;
-typedef PVValueArray<double> PVDoubleArray;
-typedef std::tr1::shared_ptr<PVDoubleArray> PVDoubleArrayPtr;
-
-typedef PVArrayData<String> StringArrayData;
-typedef PVValueArray<String> PVStringArray;
-typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
- -

where

-
-
get( std::size_t offset, std::size_t length, ArrayDataType &data) -
-
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.
-
put(std::size_t offset, std::size_t length, const_pointer from, - std::size_t fromOffset)
-
Put data into the array. from is a raw array.
-
put(std::size_t offset, std::size_t length, const_vector &from, - std::size_t fromOffset)
-
Put data into the array from a vector holding the raw array.
-
shareData( shared_vector const & value, std::size_t capacity, - std::size_t length)
-
Make the instance share the raw data from value.
- 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.
- 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.
-
get()
-
Get the raw array.
-
getVector()
-
Get the vector holding the raw array.
-
getSharedVector()
-
Get the shared vector holding the data.
-
dumpValue
-
Method for streams I/O.
-
- -

Both get and put return the number of elements actually transfered. The -arguments are:

-
-
offset
-
The offset in the PV array.
-
len
-
The maximum number of elements to transfer. The number actually - transfered will be less than or equal to this value.
-
data
-
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.
-
from
-
The array from which the data is taken. This array is supplied by the - caller
-
fromOffset
-
The offset in from
-
- -

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:

-
void getArray(PVDoubleArrayPtr & pv,DoubleArray const & to)
-{
-    size_t len = pv->getLength();
-    if(to.size()<len) to.resize(len);
-    DoubleArrayData data;
-    size_t offset = 0;
-    while(offset<len) {
-        size_t num = pv->get(offset,(len-offset),data);
-        DoubleArray &from = data.data;
-        size_t fromOffset = data.offset;
-        for(size_t i=0; i<num; i++) to[i+offset] = from[i + fromOffset];
-        offset += num;
-    }
-} 
- -