From 3de28e3cef76fbf2d0b234181ed5743617a1e707 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Thu, 13 Jun 2013 14:52:27 -0400 Subject: [PATCH 1/5] added pvArray.html; made queue.h and bitSetUtil.* compatible with pvDataCPP. --- documentation/pvArray.html | 998 ++++++++++++++++++++++++++++++++ pvDataApp/misc/queue.h | 8 +- pvDataApp/pvMisc/bitSetUtil.cpp | 40 +- pvDataApp/pvMisc/bitSetUtil.h | 2 +- 4 files changed, 1022 insertions(+), 26 deletions(-) create mode 100644 documentation/pvArray.html diff --git a/documentation/pvArray.html b/documentation/pvArray.html new file mode 100644 index 0000000..af43eb6 --- /dev/null +++ b/documentation/pvArray.html @@ -0,0 +1,998 @@ + + + + + + EPICS pvArray + + + + + + + + +
+

EPICS Array

+ + +

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

+ +
+
Latest version:
+
pvArray.html +
+
This version:
+
none
+
Previous version:
+
None
+
Editors:
+
Marty Kraimer, BNL
+ Michael Davidsaver, BNL
+
+ + +
+
+ + +
+

Table of Contents

+
+
+ + +

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.

+ +

shared_vector

+

Status

+

I think that all public components of sharedVector.h +are now documented, but not all have a description or example. +Thus the documentation needs more work. +

+

Introduction

+

A shared_vector is a container as defined by the C++ standard library. +It is like std::vector but provides two additional features +1) shared raw array and 2) a window into the raw array.

+

To support these two features a shared_vector keeps the following +private data: +

+
m_data
+
This is a std::tr1::shared_ptr for the actual data array. +
+
m_offset
+
This is the offset of the first element seen by the window.
+
m_count
+
This is the size, i. e. total number of elements, seen by the window.
+
m_total
+
This is the number of elements between offset and the end of the array referenced + by m_data.
+
+Note that only m_data is shared. Thus each shared_vector has it's own window.

+

The following subsections are organized as follows: +

+
shared_vector example
+
The example code is based on a shared_vector<int32> + This subsection show the C++ definitions that are assumed by + the example code. + The source that contains the example code will be part + of this project but not yet.
+
std::vector compatible subsections
+
The types and methods that have the same names as std::vector.
+
share_vector specific
+
The methods that are not part of std::vector.
+

+

The subsections that are compatible with std::vector are organized +and start with a brief summary modeled after Section 31.3(STL Containers) in:
+"The C++ Programming Language, C++11, Fourth Edition", Bjarne Stroustrup,2013
+The subsection names are the same names that Stroustrup uses. +Each subsection starts with a brief summary that is similar to +the summary Stroustrup has at the beginnining of each subsection.

+

The comparison is always with std::vector. +In addition it shows what is defined by by std::vector but not by +shared_vector.

+

Someone who already understand the C++ STL can understand shared_vector +by just looking at the brief summarys. +For others the brief summary is followed by tutorial information. +

+

shared_vector example

+

The examples all assume that the following has been defined:

+
+typedef shared_vector<int32> Int32Array;
+...
+static void dumpArray(String const &message,Int32Array const& int32Array);
+
+

The following: +

+Int32Array int32Array(5);
+dumpArray("example",int32Array);
+
+creates a shared vector that holds an array of five elements where each element is a +32 bit signed integer. +The call to dumpArray displays the message and the array elements on standard out: +
+example 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+

+

exampleSharedVector is a main program that has the code for the +examples shown below.

+

Member Types

+

Brief Summary +

+value_type              Type of element
+size_type               Unsigned type of subscripts, element counts, etc.
+difference_type         Signed type of difference between iterators
+iterator                Behaves like value_type*
+const_iterator          Behaves like const value_type*
+reverse_iterator        Behaves like value_type*
+const_reverse_iterator  Behaves like const value_type*
+reference               value_types&
+const_reference         const_value_type&
+pointer                 Behaves like value_type *
+const_pointer           Behaves like const value_type*
+//not part of std::vector
+element_type            same as value_type
+shared_pointer_type     std::tr1::shared_ptr<value_type>
+// defined by std::vector but not by shared_vector
+allocator_type
+
+

+

+The typedefs are compatible with the STL container member types. +These define types for various types of variables that belong to a container +or are used to access a container.

+

value_type, reference, and const_reference

+

These three typedefs define the same types as the equivalent types for +an element of the shared_vector. +

+Int32Array::value_type value;
+//is the same as
+int32 value;
+
+Int32Array::reference rvalue = value;
+//is the same as
+int32 & rvalue = value;
+
+Int32Array::const_reference rvalue = value;
+//is the same as
+const int32 & rvalue = value;
+
+

+

pointer and const_pointer

+

The following is an example of code that uses the +pointer typedef:

+
+Int32Array int32Array(5);
+Int32Array::pointer pint32Array = int32Array.data();
+size_t len = int32Array.size();
+for(size_t i=0; i<len; ++i) pint32Array[i] = i;
+
+

A const_pointer is like a pointer except that only read access to the array elements +is allowed.

+

Dangorous: data should not be used unless it is necessary to +call C code. The above code should be:

+
+Int32Array int32Array(5);
+size_t len = int32Array.size();
+for(size_t i=0; i<len; ++i) int32Array[i] = i;
+
+ +

difference_type

+

This is used to get the number of elements between two elements. +For example:

+
+Int32Array::difference_type pdiff = int32Array[3] - int32Array[1];
+// pdiff will have the value 2
+
+

element_type and shared_pointer_type

+

These are member types defined by std::tr1::shared_ptr. +These are not used by any of the client methods.

+ +

Constructors, Destructor, and Assignments

+

Brief Summary +

+C c();         Default constructor; c is empty.
+C c(n);        c is initialized with n elementis with the value value_type{};
+               offset is 0; size is n;
+C c(n,e);      Initialize c with n copies of e.
+               offset is 0; size is n;
+
+C c(c);        Copy an existing shared_vector of the same type.
+               offset and taken same as v.
+               shared_ptr is copied; not the raw array
+C operator=(c) Assignment constructor.
+               shared_ptr is copied; not the raw array
+C c(c,o,n);    Copy an existing std::tr1::shared_ptr<value_type>
+               offset is o; size is c;
+C c(r,o,n);    Use an existing raw pointer.
+               default deleter use "delete[]" to delete.
+               offset is o; size is c;
+C c(r,d,o,n);  Use an existing raw pointer and deleter d;
+               offset is o; size is c;
+
+not implemented
+~C()           The C++ default destructor is used.
+C++11 specific
+&& constructor move constructor
+{} constructor uniform initializer constructor
+
+where +
+
C
+
The class name, e. g. shared_vector<int32>
+
c
+
shared_vector instance
+
n
+
size, i. e. the number of elements
+
o
+
offset
+
e
+
element instance
+
r
+
raw pointer, e. g. int32 *
+
d
+
a deleter, i. e. object that destroys the raw array.
+
+

+

Construct by creating new raw array

+
+shared_vector();
+shared_vector(size_t n);
+shared_vector(size_t n, value_type e);
+
+

The first three constructors all create a new shared_vector +by also creating a new raw array, +The difference is the size of the array, i.e. how many elements it contains, +and how the elements are initalized. +

+
+
shared_vector()
+
The array is empty, i.e. it has no elements.
+
shared_vector(size_t n)
+
The array has n elements. Each element is initialized +by the default constructor for the element type. +For numeric elements, like int32, this means 0.
+
shared_vector(size_t n, value_type e)
+
The array has n elements. +Each element has the initial value e. +
+
+

The following: +

+    cout << "***exampleConstructors***" << endl;
+    Int32Array emptyArray();
+    Int32Array zeroArray(16);
+    int32 value = 1;
+    Int32Array oneArray(8, value);
+    dumpArray("emptyArray",emptyArray);
+    dumpArray("zeroArray",zeroArray);
+    dumpArray("oneArray",oneArray);
+
+produces +
+***exampleConstructors***
+emptyArray 1
+zeroArray {16}[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
+oneArray {8}[1, 1, 1, 1, 1, 1, 1, 1]
+
+

NOTE EXISTING: Why did emptyArray disply the above. +Should it be "emptyArray {0} []"? +

+

Construct by sharing raw array from a shared_vector

+
+shared_vector(const shared_vector& o);
+shared_vector_base& operator=(const shared_vector_base& o);
+
+

These create a vector by coping the contents of an existing shared_vector +of the same type into the newly created vector. +Note that the complete raw array is not copied but just the std::tr1:: shared_ptr +that holds the array.

+

The following: +

+    cout << "***exampleCopyConstructors***" << endl;
+    size_t max = 16;
+    Int32Array int32Array(max);
+    for(size_t i=0; i<max; ++i) int32Array[i] = i+1;
+    Int32Array xxx(int32Array);    //copy constructor
+    Int32Array yyy = int32Array;   //copy assignment
+    cout << "dataPtr int32Array " << int32Array.dataPtr();
+    cout << " xxx " << xxx.dataPtr();
+    cout << " yyy " << yyy.dataPtr() << endl;
+    dumpArray("int32Array",emptyArray);
+    dumpArray("xxx",emptyArray);
+    dumpArray("yyy",emptyArray);
+
+produces +
+***exampleConstructors***
+dataPtr int32Array 0x136ea90 xxx 0x136ea90 yyy 0x136ea90
+int32Array {16}[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
+xxx {16}[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
+yyy {16}[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
+
+

Construct by wrapping an existing raw array

+
+shared_vector(A v, size_t o, size_t c)
+shared_vector(A d, B b, size_t o, size_t c)
+
+

NOTE EXISTING: Are these constructors necessary? +If code wants to wrap an existing raw array then +a std::tr1::shared_ptr can first be created +and the constructor in the next section can be called.

+

These "wrap" an existing raw pointer. +They allows access to a sub-array starting at offset o> +and has size c +The second provides a destructor and the first has a default deleter.

+

The default deleter does the following: +When the shared_vector is deleted, i. e. when no code references it, +the statement "delete[] a;" is executed.

+

An example of wrapping a raw array without using these constructors is:

+
+class Int32ArrayDeleter
+{
+//Note that this an example that does nothing.
+//But it could have private data
+public:
+     Int32ArrayDeleter() {}
+     virtual ~Int32ArrayDeleter() {}
+     void operator()(int32* a){
+         // MUST HANDLE DELETION
+         // default is "delete[] a;"
+     }
+};
+...
+int32 *pother; // something managed by other code
+size_t capacity; // size of array managed by other code
+
+Int32Array int32Array(pother,int32array_deleter,0,capacity);
+
+

This is used to wrap arrays that are managed by other +code. This should only be used if You understand the other code +and know what your deleter has to do. +An example, exampleShareRawArray, gives a more complete example. +

+ +

Create a shared_vector from an existing shared_ptr

+
+shared_vector(const std::tr1::shared_ptr<E1>& d, size_t o, size_t c)
+
+

This creates a vector from an existing smart pointer. +Thus the vector will share reference counting with the existing smart +pointer. This is useful for creating "windows" into the array +that the smart pointer references.

+ + + +

Create a shared_vector from an existing shared_vector

+
+ template<typename E1>
+    shared_vector(const shared_vector<E1>& o) :base_t(o) {}
+
+

NOTE EXISTING: I do not understand how this works or what it does.

+

This create a vector by coping the contents of an existing shared_vector +of the same or a different but related type +into the newly created vector. +This constructor creates a new raw array and copies the elements from +the existing array to the new array.

+ +

Size and Capacity

+

Brief Summary +

+size()      Return the number of elements in the window
+empty()     Is the window empty? this means shared_ptr is empty
+max_size()  The maximum possible number of elements.
+capacity()  The number of possible elements without re-allocating raw array.
+reserve(n)  Reserve at least n elements in raw array; May cause reallocation.
+resize(n)   Change size to n; May cause reallocation
+clear()     shared_ptr is reset, Window will be empty.
+
+not implemented
+resize(n,v)
+shrink_to_fit()
+

+

Details +

+size_t size() const;
+bool empty() const;
+size_t max_size() const;
+size_t capacity() const;
+void reserve(size_t n);
+void resize(size_t n);
+void clear();
+
+

+
+
size
+
The current number of elements in the window.
+
empty
+
(true,false) if size is (0,>0)
+
max_size
+
Maximum possible number of elements. +NOTE EXISTING; Should this be sizof(W)/(size_t -1) ? +
+
capacity
+
The maximum size the window can be without reallocating raw array
+
reserve
+
Set the maximum number of element that the window can see. + If the caller is the only user of the window and the number + of elements specified does not cause the number of elements to change + then this method just returns. + In all other cases a new raw array is allocated.

+
resize
+
Change the window size: may cause a reallocation of the raw array.
+
clear
+
If the shared_vector is not already empty the shared_ptr will + be reset. The new size will be 0.
+
+

The following: +

+static void exampleSizeEtc()
+{
+    cout << "***exampleSizeEtc***" << endl;
+    size_t max = 16;
+    Int32Array int32Array(max);
+    size_t capacity = int32Array.capacity();
+    size_t size = int32Array.size();
+    bool empty = int32Array.empty();
+    size_t max_size = int32Array.max_size();
+    cout<< "capacity" << capacity;
+    cout<< " size " << size;
+    cout<< " empty " << (empty ? true : false) ;
+    cout<< " max_size " << max_size << endl;
+}
+
+
+produces: +
+***exampleSizeEtc***
+capacity16 size 16 empty 0 max_size 18446744073709551615
+
+

+

Iterators

+

Brief Summary +

+begin()      First element
+end()        One past last element
+cbegin()     Constant first element
+cend()       Constant last element
+rbegin()     First element of reverse sequence
+rend()       One past last element of reverse sequence
+crbegin()    Constant first element of reverse sequence
+crend()      Constant last element of reverse sequence
+

+

+shared_vector supports both iterators and reverse iterators as defined by the STL. +For both constant iterators are also defined. +A constant iterator does not allow an array elemnent to be modified.

+

The following is an example of a constant iterator.

+
+int32 sum = 0;
+for(Int32Array::const_iterator iter=int32Array.begin(); iter<int32Array.end(); ++iter )
+{
+     sum += *iter;
+}
+
+

The following is an example of a non constant iterator.

+
+int32 value = 0;
+for(Int32Array::iterator iter=int32Array.begin(); iter<int32Array.end(); ++iter )
+{
+     *iter += ++value;
+}
+
+

Element Access

+

Brief Summary +

+operator[i]    random element access 
+data()         return the raw array
+
+implemented by std::vector but not implemented
+front()
+back()
+at()
+

+

Note that: +

+Int32Array::pointer pint32= int32Array.data();
+
+is NOT gauranteed to be the same as +
+int32 * pint32 = int32Array.data();
+
+

+

NOTE EXISTING: data() should be defined to return a const_pointer. +It is currently defined to return a plain pointer.

+

Stack Operations

+

Brief Summary +

+push_back(x)     Add an element after the last element
+pop_back(x)      Remove the last element.
+

+

List operations

+

shared_vector does not support the standard list operations like: +

+implemented by std::vector but not by shared_vector
+
+insert(p,x)   Add x before p
+...
+
+

+

Other Operations

+

Brief Summary +

+operator==       Do all elements of both containers compare equal.
+operator!=       Does any element not compare equal.
+operator<<       ostream operator
+swap(c2)         Swap the contents of two shared_vectors of the same type.
+swap(c1,c2)      Swap the contents of two shared_vectors of the same type.
+
+not implemented
+operator<
+operator<=
+operator>
+operator>=
+

+

operators equals, not equals, and ostream

+
+template<typename A, typename B>
+bool operator==(const epics::pvData::shared_vector<A>& a,
+                const epics::pvData::shared_vector<B>& b);
+
+template<typename A, typename B>
+bool operator!=(const epics::pvData::shared_vector<A>& a,
+                const epics::pvData::shared_vector<B>& b);
+
+template<typename E>
+std::ostream& operator<<(
+    std::ostream& strm, const epics::pvData::shared_vector<E>& arr);
+
+
+

swap

+

Swap the contents of two shared_vectors. The following code: +

+    cout << "***exampleSwap***" << endl;
+    Int32Array first(8);
+    Int32Array second(16);
+    cout << " before swap  size ";
+    cout<< "first " << first.size() << " second " << second.size() << endl;
+    first.swap(second);
+    cout << " after swap   size ";
+    cout<< "first " << first.size() << " second " << second.size() << endl;
+    swap(first,second);
+    cout << " swap again   size ";
+    cout<< "first " << first.size() << " second " << second.size() << endl;
+
+produces: +
+***exampleSwap***
+ before swap  size first 8 second 16
+ after swap   size first 16 second 8
+ swap again   size first 8 second 16
+

+ +

shared_vector specific operations

+

Brief Summary +

+void make_unique()         Make caller the only user of std::tr1::shared_ptr
+bool unique()              Is the caller the only user of std::tr1::shared_ptr
+void slice(offset,length)  Change window offset andsize
+
+// following should only be used for debugging
+const std::tr1::shared_ptr<E>&
+       dataPtr()           Return const  shared_ptr
+size_t dataOffset()        Return offset.
+size_t dataCount()         Return count which is also the size
+size_t dataTotal()         Return total number of elements between
+                           offset and end of the raw array
+
+// following converts from type FROM to type TO
+shared_vector static_shared_vector_cast(const shared_vector<FROM>& src);
+
+// following casts from const Type to Type
+shared_vector
+const_shared_vector_cast(const shared_vector<const TYPE>& src)
+

+

NOTE EXISTING: The C++ standard library considers a slice to be every nth element +of some part of an array, i. e., slice has arguments (offset,length,stride). +shared_vector only has offset and length. +Perhaps it should have another name like rewindow. +

make_unique and unique

+
+void make_unique();
+bool unique() const;
+
+
+
make_unique
+
Makes sure that caller is the only user of this standard_vector. + If the caller is not already the only user a new raw array is allocated.
+
unique
+
+ Returns (true,false) if there is only one user of the shared_vector. +
+
+

slice

+
+void slice(size_t offset, size_t length=(size_t)-1);
+
+

This modifies the "window" into the raw array starting at offset and of +the specified length. The offset and length are forced to be +within the raw array. +Note that this method never reallocates the underlying raw array. +

+

The following code: +

+static void exampleSlice()
+{
+    cout << "***exampleSlice***" << endl;
+    size_t max = 16;
+    Int32Array int32Array(max);
+    int32 value = 0;
+    for(Int32Array::iterator iter = int32Array.begin(); iter!=int32Array.end(); ++iter)
+    {
+        *iter = ++value;
+    }
+    dumpArray("int32Array",int32Array);
+    size_t offset = 0;
+    size_t length = 8;
+    Int32Array window1(int32Array);
+    window1.slice(offset,length);
+    dumpArray("window1",window1);
+    offset = 8;
+    length = 8;
+    Int32Array window2(int32Array);
+    window2.slice(offset,length);
+    dumpArray("window2",window2);
+    offset = 2;
+    length = 4;
+    Int32Array window3(window2);
+    window3.slice(offset,length);
+    dumpArray("window3",window3);
+}
+
+produces the following output: +
+***exampleSlice***
+int32Array 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+window1 1 2 3 4 5 6 7 8
+window2 9 10 11 12 13 14 15 16
+window3 11 12 13 14
+
+

dataPtr, dataOffset, dataCount, and dataTotal

+
+
dataPtr
+
Returns the shared_ptr that holds the raw array. +
+
dataOffset
+
Offset in the data array of first element
+
dataCount
+
Number of visible elements. + Same as size. +
+
dataTotal
+
Total number of elements between m_offset and the end of data. + Same as capacity. +
+
+

The following: +

+static void exampleDataEtc()
+{
+    cout << "***exampleDataEtc***" << endl;
+    size_t max = 16;
+    Int32Array int32Array(max);
+    long use_count = int32Array.dataPtr().use_count();
+    long offset = int32Array.dataOffset();
+    long count = int32Array.dataCount();
+    long total = int32Array.dataTotal();
+    cout << "use_count " << use_count;
+    cout << " offset " << offset;
+    cout << " count " << count;
+    cout << " total " <<  total << endl;
+}
+
+produces: +
+***exampleDataEtc***
+use_count 1 offset 0 count 16 total 16
+
+

+ +

static_shared_vector_cast

+

Not yet documented

+ +

const_shared_vector_cast

+

Not yet documented

+ +

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;
+    }
+} 
+ + + +
+ + diff --git a/pvDataApp/misc/queue.h b/pvDataApp/misc/queue.h index d496594..dea98f2 100644 --- a/pvDataApp/misc/queue.h +++ b/pvDataApp/misc/queue.h @@ -29,9 +29,9 @@ public: int getNumberFree(); int getNumberUsed(); queueElementPtr & getFree(); - void setUsed(queueElementPtr &element); + void setUsed(queueElementPtr const &element); queueElementPtr & getUsed(); - void releaseUsed(queueElementPtr &element); + void releaseUsed(queueElementPtr const &element); private: queueElementPtr nullElement; queueElementPtrArray elements; @@ -92,7 +92,7 @@ std::tr1::shared_ptr & Queue::getFree() } template -void Queue::setUsed(std::tr1::shared_ptr &element) +void Queue::setUsed(std::tr1::shared_ptr const &element) { if(element!=elements[nextSetUsed++]) { throw std::logic_error("not correct queueElement"); @@ -112,7 +112,7 @@ std::tr1::shared_ptr & Queue::getUsed() } template -void Queue::releaseUsed(std::tr1::shared_ptr &element) +void Queue::releaseUsed(std::tr1::shared_ptr const &element) { if(element!=elements[nextReleaseUsed++]) { throw std::logic_error( diff --git a/pvDataApp/pvMisc/bitSetUtil.cpp b/pvDataApp/pvMisc/bitSetUtil.cpp index cf6569d..b27075c 100644 --- a/pvDataApp/pvMisc/bitSetUtil.cpp +++ b/pvDataApp/pvMisc/bitSetUtil.cpp @@ -13,25 +13,31 @@ namespace epics { namespace pvData { +using std::tr1::static_pointer_cast; +using std::size_t; + static bool checkBitSetPVField( - PVField *pvField,BitSet *bitSet,int32 initialOffset) + PVFieldPtr const &pvField,BitSetPtr const &bitSet,int32 initialOffset) { - bool atLeastOneBitSet = false; - bool allBitsSet = true; int32 offset = initialOffset; int32 nbits = pvField->getNumberFields(); if(nbits==1) return bitSet->get(offset); int32 nextSetBit = bitSet->nextSetBit(offset); if(nextSetBit>=(offset+nbits)) return false; + if(nextSetBit<0) return false; if(bitSet->get(offset)) { if(nbits>1) { for(int32 i=offset+1; iclear(i); } return true; } - PVStructure *pvStructure = static_cast(pvField); + + bool atLeastOneBitSet = false; + bool allBitsSet = true; + PVStructurePtr pvStructure = static_pointer_cast(pvField); + offset = pvStructure->getFieldOffset() + 1; while(offsetgetSubField(offset).get(); + PVFieldPtr pvSubField = pvStructure->getSubField(offset); int32 nbitsNow = pvSubField->getNumberFields(); if(nbitsNow==1) { if(bitSet->get(offset)) { @@ -41,24 +47,16 @@ static bool checkBitSetPVField( } offset++; } else { - offset++; - PVStructure *pvSubStructure = static_cast(pvField); - PVFieldPtrArray pvSubStructureFields = - pvSubStructure->getPVFields(); - int num = pvSubStructure->getStructure()->getNumberFields(); - for(int32 i=0; iget(offset)) { - allBitsSet = false; - } - } else { + bool result = checkBitSetPVField(pvSubField,bitSet,offset); + if(result) { + atLeastOneBitSet = true; + if(!bitSet->get(offset)) { allBitsSet = false; } - offset += pvSubSubField->getNumberFields(); + } else { + allBitsSet = false; } + offset += pvSubField->getNumberFields(); } } if(allBitsSet) { @@ -72,7 +70,7 @@ static bool checkBitSetPVField( return atLeastOneBitSet; } -bool BitSetUtil::compress(BitSet *bitSet,PVStructure *pvStructure) +bool BitSetUtil::compress(BitSetPtr const &bitSet,PVStructurePtr const &pvStructure) { return checkBitSetPVField(pvStructure,bitSet,0); } diff --git a/pvDataApp/pvMisc/bitSetUtil.h b/pvDataApp/pvMisc/bitSetUtil.h index 44fac32..add517a 100644 --- a/pvDataApp/pvMisc/bitSetUtil.h +++ b/pvDataApp/pvMisc/bitSetUtil.h @@ -17,7 +17,7 @@ namespace epics { namespace pvData { class BitSetUtil : private NoDefaultMethods { public: - static bool compress(BitSet *bitSet,PVStructure *pvStructure); + static bool compress(BitSetPtr const &bitSet,PVStructurePtr const &pvStructure); }; }} From ec6b67ffad27b1db7318e4b451cab0e9fc1f8f24 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Tue, 18 Jun 2013 10:01:52 -0400 Subject: [PATCH 2/5] 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;
-    }
-} 
- - From 5f52f140944eed84c19adbc78dea847642410854 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Tue, 25 Jun 2013 12:18:38 -0400 Subject: [PATCH 3/5] comparison between implementations --- documentation/pvArray.html | 793 ++++++++++++++++++++++++++++++++++++- 1 file changed, 771 insertions(+), 22 deletions(-) diff --git a/documentation/pvArray.html b/documentation/pvArray.html index 4b21ed5..8621bb7 100644 --- a/documentation/pvArray.html +++ b/documentation/pvArray.html @@ -37,7 +37,7 @@

EPICS Array

-

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

+

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

Latest version:
@@ -68,7 +68,18 @@ license.

Introduction

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

+When complete it will be merged into pvDataCPP.html. +This document proposes an implementation of the PVXXX interfaces that are +different than the existing pvDataCPP-md interfaces. +See the next section for a comparison of the four interface descriptions. +The main reason for proposing a different definition is the primary +purpose for pvData:
+pvData (Process Variable Data) defines and implements an efficent +way to store, access, and communicate memory resident data structures.
+This statement appears as the first sentence of pvDataJava.html. +A few sentances later the document makes clear that communication +includes network communication. +Thus it is important to keep the Java and C++ descriptions similar.

pvData provides an interface for network accessible structured data. The interfaces for C++ and Java are similar. @@ -82,7 +93,7 @@ Some differences are:

shared pointers
Java has a garbage collector. In C++ the implementation manages - memory. The primary tool is std::tr1::shared_ptr.
+ memory. An important 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. @@ -92,8 +103,11 @@ Some differences are: 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.
+ data and also supports a window into the raw data. It does follow the + naming and other conventions for C++ standard library containers. + Code that wants to use features of the C++ standard library + like iterators and algorithms can get the shared_vector. +

There is one big difference from the existing Java implelentation: The method PVValueArray::get. @@ -120,13 +134,736 @@ PVScalarArrayPtr createPVScalarArray(const PVScalarArray &, size_t offset, s

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.
+ methods like getAs. It will again support methods toXXXArray and fromXXXArray. + Templates should be used to minimize the code required.
PVStructureArray
Can this also use shared_vector to hold elements?

+

PVXXX: pvDataJava, pvDataCPP, pvDataCPP-md, and proposed interface

+

The following compares the definitions of the following: PVField, +PVScalar and extensions, PVArray and extensions. +Note, however, that PVStructureArray is not discussed. +

+

PVField

+

This is the base for all the PVXXX iterfaces. +It provides basic methods for allowing network transfer and for +traversing structured data. +The pvDataJava and pvDataCPP definitions are similar. +pvDataCPP-md added method getFullName. +The proposed interface is like the existing pvDataCPP except that +the toString and dumpValue methods are replaced by the stream operator<<. +

+

Java

+
interface PVField extends Requester, Serializable {
+    String getFieldName();
+    void setRequester(Requester requester);
+    int getFieldOffset();
+    int getNextFieldOffset();
+    int getNumberFields();
+    PVAuxInfo getPVAuxInfo();
+    boolean isImmutable();
+    void setImmutable();
+    Field getField();
+    PVStructure getParent();
+    void renameField(String newName);
+    void postPut(); // calls PVRecordField.postPut if this is a field of a record
+    void setPostHandler(PostHandler postHandler);
+    void toString(StringBuilder buf);
+    void toString(StringBuilder buf,int indentLevel);
+    String toString();
+}
+

pvDataCPP

+
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);
+   String getFieldName() 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;
+   virtual 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 bool equals(PVField &pv);
+   virtual void toString(StringBuilder buf) ;
+   virtual void toString(StringBuilder buf,int indentLevel);
+   std::ostream& dumpValue(std::ostream& o) const;
+ ...
+}
+
+std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
+
+

pvDataCPP-md

+
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);
+   String getFieldName() 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;
+   virtual 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 bool equals(PVField &pv);
+   virtual void toString(StringBuilder buf) ;
+   virtual void toString(StringBuilder buf,int indentLevel);
+   std::ostream& dumpValue(std::ostream& o) const;
+   // not in pvDataCPP
+   String getFullName() const;
+ ...
+}
+
+std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
+
+

proposed

+
+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 bool equals(PVField &pv);
+    virtual std::ostream& operator<<(std::ostream& o) const = 0;
+    virtual std::ostream& operator<<(std::ostream& o, size_t index) const = 0;
+...
+};
+
+std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
+std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f, size_t index);
+
+

PVScalar

+

The Java and pvDataCPP versions differ in that Java has an interface definition +for each scalar type, i. e. PVBoolean, ..., PVString, +and the CPP versions provide a template PVValue for the implementation.

+

+pvDataCPP-md differs from pvDataCPP in that it implements three additional +methods: +

+
getAs
+
This is used to implement the Convert::toXXX methods. + This belongs in the Convert implementation not in PVScalar.
+
putFrom
+
This is used to implement the Convert::fromXXX scalar methods. + This belongs in the Convert implementation not in PVScalar.
+
assign
+
This does the same thing as the Convert::fromXXX methods except + that it does not go through Convert. + This belongs in the Convert implementation not in PVScalar.
+
+

+

The proposed version is like the pvDataCPP version except for dumpValue +and the stream interators.

+

pvDataJava

+
+interface PVScalar extends PVField {
+    Scalar getScalar();
+}
+
+interface PVBoolean extends PVScalar {
+    boolean get();
+    void put(boolean value);
+}
+
+interface PVByte extends PVScalar {
+    byte get();
+    void put(byte value);
+}
+...
+interface PVDouble extends PVScalar {
+    double get();
+    void put(double value);
+}
+interface PVString extends PVScalar, SerializableArray {
+    String get();
+    void put(String value);
+}
+
+

pvDataCPP

+
class PVScalar : public PVField {
+public:
+    POINTER_DEFINITIONS(PVScalar);
+    virtual ~PVScalar();
+    typedef PVScalar &reference;
+    typedef const PVScalar& const_reference;
+    const ScalarConstPtr getScalar() const ;
+ ...
+}
+
+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& dumpValue(std::ostream& o) const
+    void operator>>=(T& value) const;
+    void operator<<=(T value);
+ ...
+}
+
+typedef PVScalarValue PVBoolean;
+typedef PVScalarValue PVByte;
+...typedef PVScalarValue PVDouble;
+typedef std::tr1::shared_ptr PVBooleanPtr;
+typedef std::tr1::shared_ptr PVBytePtr;
+...
+typedef std::tr1::shared_ptr PVDoublePtr;
+
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<String>, SerializableArray {
+public:
+    virtual ~PVString() {}
+ ...
+};
+ +

pvDataCPP-md

+
class PVScalar : public PVField {
+public:
+    POINTER_DEFINITIONS(PVScalar);
+    virtual ~PVScalar();
+    typedef PVScalar &reference;
+    typedef const PVScalar& const_reference;
+    const ScalarConstPtr getScalar() const ;
+
+    // not in pvDataCPP
+    template<ScalarType ID>
+    inline typename ScalarTypeTraits<ID>::type getAs() const;
+
+    virtual void getAs(void *, ScalarType) const = 0;
+    template<ScalarType ID>
+    inline void putFrom(typename ScalarTypeTraits<ID>::type val)
+
+    virtual void putFrom(const void *, ScalarType) = 0;
+    virtual void assign(const PVScalar&) = 0;
+
+ ...
+}
+
+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& dumpValue(std::ostream& o) const
+    void operator>>=(T& value) const;
+    void operator<<=(T value);
+
+    // not in pvDataCPP
+    static const ScalarType typeCode;
+ ...
+}
+
+typedef PVScalarValue PVBoolean;
+typedef PVScalarValue PVByte;
+...typedef PVScalarValue PVDouble;
+typedef std::tr1::shared_ptr PVBooleanPtr;
+typedef std::tr1::shared_ptr PVBytePtr;
+...
+typedef std::tr1::shared_ptr PVDoublePtr;
+
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<String>, SerializableArray {
+public:
+    virtual ~PVString() {}
+ ...
+};
+

proposed

+
+class PVScalar : public PVField {
+public:
+    POINTER_DEFINITIONS(PVScalar);
+    virtual ~PVScalar();
+
+    typedef PVScalar &reference;
+    typedef const PVScalar& const_reference;
+
+    const ScalarConstPtr getScalar() const;
+...
+};
+
+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;
+
+    void operator>>=(T& value) const;
+    void operator<<=(T value);
+    virtual std::ostream& operator<<(std::ostream& o) const
+    virtual std::ostream& operator>>(std::ostream& o, size_t index) const;
+...
+};
+typedef PVScalarValue<uint8> PVBoolean;
+typedef PVScalarValue<int8> PVByte;
+typedef PVScalarValue<double> PVDouble;
+...
+typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
+typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
+...
+typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<String>, SerializableArray {
+public:
+    virtual ~PVString() {}
+ ...
+};
+
+

PVArray

+

The Java and pvDataCPP versions differ in that Java has an interface definition +for each scalarArray type, i. e. PVBooleanArray, ..., PVStringArray, +and the CPP versions provide a template PVValueArray for the implementation.

+

+pvDataCPP-md differs from pvDataCPP in that it implements additional +methods: +

+
getAs
+
This is used to implement the Convert::toXXXArray methods. + This belongs in the Convert implementation not in PVArray.
+
putFrom
+
This is used to implement the Convert::fromXXXArray scalar methods. + This belongs in the Convert implementation not in PVArray.
+
assign
+
This does the same thing as the Convert::fromXXXArray methods except + that it does not go through Convert. + This belongs in the Convert implementation not in PVArray.
+
copyOut
+
This is used to copy data to a raw array.
+
copyIn
+
This is used to copy data in from a raw array. +
+

+

The proposed version is differs from pvJava, pvDataCPP, and pvCPP-md. +It is like the Java version if the Java get method is simplified as discussed above. +For example PVDoubleArray::get becomes: +

+    double[] get();
+
+The corresponding C++ version becomes: +
+    const svector & get();
+
+

+

The remaining difference is that dumpValue is replaced by the stream operator<<.

+

The main difference from the pvDataJava version is that PVValueArray "wraps" shared_vector. +Thus shared_vector takes the place of the raw arrays in Java. +This allows the C++ interface to be more similar to Java.

+

The main difference from the pvDataCPP-md version is that it does not implement +the extra methods and allows +the client access to the shared_vector. +The client is then able to perform C++ specific things to the data. +BUT it also means that if the client modifies the shared_vector the client is also responsibel +for ensuring that the immutable and capacity related features of PVField and PVArray are +respected and the postPut is properly handled. +The new method for PVValueArray: + + void put(const svector &from); + +helps ensure that shared_vector from the client is kept in sync with the shared_vector wrapped +by PVValueArray. But the used is still responsible for making sure that +PVField::isImmutable is honored. +

+

pvDataJava

+
interface PVArray extends PVField, SerializableArray {
+    int getLength();
+    void setLength(int length);
+    int getCapacity();
+    void setCapacity(int length);
+    boolean isCapacityMutable();
+    void setCapacityMutable(boolean isMutable);
+}
+
+interface PVScalarArray extends PVArray {
+    ScalarArray getScalarArray();
+}
+

For each scalar type an associated array data interface is defined. Each has +a get and put method. For example:

+
public class DoubleArrayData {
+    public double[] data;
+    public int offset;
+}
+
+interface PVDoubleArray extends PVArray {
+    int get(int offset, int len, DoubleArrayData data);
+    int put(int offset,int len, double[] from, int fromOffset);
+    void shareData(double[] from);
+}
+

pvDataCPP

+
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;
+    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
+
+ ...
+};
+
+std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);
+
+
+template<typename T>
+class PVArrayData {
+private:
+    std::vector<T> init;
+public:
+    POINTER_DEFINITIONS(PVArrayData);
+    typedef T  value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    std::vector<T> & data;
+    std::size_t offset;
+    PVArrayData()
+    : data(init)
+    {}
+};
+
+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;
+ ...
+}
+
+template<typename T>
+class PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> {
+    typedef detail::PVVectorStorage<T,PVScalarArray> base_t;
+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;
+
+...
+};
+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<String> StringArrayData;
+typedef PVValueArray<String> PVStringArray;
+typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;i
+
+ +

pvDataCPP-md

+
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;
+    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
+ ...
+};
+
+std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);
+
+template<typename T>
+class PVArrayData {
+private:
+    std::vector<T> init;
+public:
+    POINTER_DEFINITIONS(PVArrayData);
+    typedef T  value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    std::vector<T> & data;
+    std::size_t offset;
+    PVArrayData()
+    : data(init)
+    {}
+};
+
+class PVScalarArray : public PVArray {
+public:
+    POINTER_DEFINITIONS(PVScalarArray);
+    virtual ~PVScalarArray();
+    typedef PVScalarArray &reference;
+    typedef const PVScalarArray& const_reference;
+    const ScalarArrayConstPtr getScalarArray() const ;
+
+    // in pvDataCPP but not in pvDataCPP=md
+    //virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
+
+    // not in pvDataCPP
+    template<ScalarType ID>
+    virtual void
+    getAs(shared_vector<typename ScalarTypeTraits<ID>::type>& out) const;
+
+    virtual void
+    getAs(ScalarType, shared_vector<void>& out) const = 0;
+
+    template<ScalarType ID>
+    inline size_t copyOut(typename ScalarTypeTraits<ID>::type* inp, size_t len) const;
+
+    virtual size_t copyOut(ScalarType id, void* ptr, size_t olen) const = 0;
+
+    template<ScalarType ID>
+    inline void putFrom(const shared_vector<typename ScalarTypeTraits<ID>::type>& inp);
+
+    virtual void putFrom(ScalarType, const shared_vector<void>&) = 0;
+
+    template<ScalarType ID>
+    inline void copyIn(const typename ScalarTypeTraits<ID>::type* inp, size_t len);
+
+    virtual void copyIn(ScalarType, const void*, size_t) = 0;
+
+    virtual void assign(PVScalarArray& pv) = 0;
+    
+ ...
+}
+
+template<typename T>
+class PVValueArray : public detail::PVVectorStorage {
+    typedef detail::PVVectorStorage base_t;
+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;
+
+    /// not in pvDataCPP
+    static const ScalarType typeCode;
+    typedef ::epics::pvData::shared_vector<T> svector;
+    typedef ::epics::pvData::shared_vector<const T> const_svector;
+
+     virtual void
+    getAs(ScalarType id, ::epics::pvData::shared_vector<void>& out) const;
+    virtual size_t copyOut(ScalarType id, void* ptr, size_t olen) const;
+    virtual void
+    putFrom(ScalarType id, const ::epics::pvData::shared_vector<void>& inp);
+    virtual void copyIn(ScalarType id, const void* ptr, size_t len);
+    virtual void assign(PVScalarArray& pv);
+
+
+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<String> StringArrayData;
+typedef PVValueArray<String> PVStringArray;
+typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;i
+
+

proposed

+
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;
+ ...
+};
+
+
+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() {}
+ ...
+};
+
+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() const;
+    size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset);
+    void put(const svector & from);
+
+    void shareData(const svector &from);
+    virtual std::ostream& operator<<(std::ostream& o) const;
+    virtual std::ostream& operator<<(std::ostream& o, size_t index) const;
+
+...
+};
+
+typedef PVValueArray<uint8> PVBooleanArray;
+typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
+...
+typedef PVValueArray<String> PVStringArray;
+typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
+
+ + +

pvDataApp/pv

pvData.h

This provides the interface for network accessible data. @@ -159,8 +896,9 @@ public: 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; + virtual bool equals(PVField &pv); + virtual std::ostream& operator<<(std::ostream& o) const = 0; + virtual std::ostream& operator<<(std::ostream& o, size_t index) const = 0; ... }; @@ -255,9 +993,11 @@ public: virtual ~PVScalarValue() {} virtual T get() const = 0; virtual void put(T value) = 0; + void operator>>=(T& value) const; + void operator<<=(T value); - std::ostream& operator<<(std::ostream& o) const - std::ostream& operator<<(std::ostream& o, size_t index) const; + virtual std::ostream& operator<<(std::ostream& o) const + virtual std::ostream& operator<<(std::ostream& o, size_t index) const; ... }; typedef PVScalarValue<uint8> PVBoolean; @@ -298,6 +1038,7 @@ public:

put
Change the value stored in the object.
operator<<
+
operator>>
Methods for stream I/O.
@@ -390,13 +1131,14 @@ public: 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); + const svector & get() const; + size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset); + void put(const svector & from); - void shareData(const_svector &from); + void shareData(const svector &from); - virtual std::ostream& operator<<(std::ostream& o) const; - std::ostream& operator<<(std::ostream& o, size_t index) const; + virtual std::ostream& operator<<(std::ostream& o) const + virtual std::ostream& operator<<(std::ostream& o, size_t index) const; ... }; @@ -446,17 +1188,25 @@ typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr; For example it must call postPut after modifying the array elements. It must also respect isImmutable(). +
size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset);
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.
+
void put(const svector & from);
+
This puts data into the PVValueArray from the shared_vector. + If the shared_vector holds the same raw array as the PVValueArray then + the shared_vector held by the PVValueArray is put in sync with from. + If not the shared_vector will share the data. + potsPut will always be called.
shareData
Share data with an existing shared_vector. - Note that if capacity is every changed then data will no + Note that if capacity is ever changed then data will no longer be shared.
operator<<
+
operator>>
Methods for stream I/O.
@@ -587,8 +1337,7 @@ for(size_t i=0; i<len; ++i) pint32Array[i] = i;

A const_pointer is like a pointer except that only read access to the array elements is allowed.

-

Dangorous: data should not be used unless it is necessary to -call C code. The above code should be:

+

NOTE: data The above code is better implemented as:

 Int32Array int32Array(5);
 size_t len = int32Array.size();
@@ -826,7 +1575,7 @@ void clear();
      
(true,false) if size is (0,>0)
max_size
Maximum possible number of elements. -NOTE EXISTING; Should this be sizof(W)/(size_t -1) ? +NOTE EXISTING; Should be ((size_t)-1)/sizeof(T)
capacity
The maximum size the window can be without reallocating raw array
@@ -913,7 +1662,7 @@ at()
 Int32Array::pointer pint32= int32Array.data();
 
-is NOT gauranteed to be the same as +is guaranteed to be the same as
 int32 * pint32 = int32Array.data();
 
From b58b97a9162baf87bb46efd931ec8705c7d9e0a6 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Fri, 28 Jun 2013 14:17:23 -0400 Subject: [PATCH 4/5] minor changes --- documentation/pvArray.html | 147 ++++++++++++++----------------------- 1 file changed, 55 insertions(+), 92 deletions(-) diff --git a/documentation/pvArray.html b/documentation/pvArray.html index 8621bb7..b5c53c3 100644 --- a/documentation/pvArray.html +++ b/documentation/pvArray.html @@ -37,7 +37,7 @@

EPICS Array

-

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

+

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

Latest version:
@@ -66,6 +66,22 @@ license.

+

Changes

+

Since the last version of this document the following changes have +been made to the proposed interface definitionsi for PVValueArray:

+
+
put(const svector &from)
+
This has been removed. shareData can be used instead.
+
get
+
The get methods has been replaced by two methods. + One allows write access to array elements and the other does not. +
+
+

The stream operator++ methods were changed so that they only appear +in PVField. All the complexity should be hidden in the implementation +and, perhaps like Java, in the convert facility.

+

A few minor changes were made because of mistakes in documenting +existing API descriptions.

Introduction

This is the documentation for pvData.h as defined by pvDataCPP-md. When complete it will be merged into pvDataCPP.html. @@ -73,21 +89,19 @@ This document proposes an implementation of the PVXXX interfaces that are different than the existing pvDataCPP-md interfaces. See the next section for a comparison of the four interface descriptions. The main reason for proposing a different definition is the primary -purpose for pvData:
-pvData (Process Variable Data) defines and implements an efficent -way to store, access, and communicate memory resident data structures.
+purpose for pvData: +

pvData (Process Variable Data) defines and implements an efficent +way to store, access, and communicate memory resident data structures.
This statement appears as the first sentence of pvDataJava.html. A few sentances later the document makes clear that communication includes network communication. -Thus it is important to keep the Java and C++ descriptions similar.

-

-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 +Thus pvData provides an interface for network accessible structured data. +If the interfaces for C++ and Java are similar then +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 pvData.h API is similar to the definition for Java. The differences are mainly related to language differences. Some differences are:

@@ -99,8 +113,8 @@ Some differences are: 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
+
In Java every object has method toString(). + For C++ stream 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 the @@ -109,13 +123,13 @@ Some differences are: like iterators and algorithms can get the shared_vector.
-

There is one big difference from the existing Java implelentation: +

There is one big difference from the existing Java API: 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: +This document assumes this will be replaced by:
     double[] get();
 
@@ -137,13 +151,13 @@ PVScalarArrayPtr createPVScalarArray(const PVScalarArray &, size_t offset, s methods like getAs. It will again support methods toXXXArray and fromXXXArray. Templates should be used to minimize the code required.
PVStructureArray
-
Can this also use shared_vector to hold elements?
+
This should also be able to use shared_vector to hold elements.

PVXXX: pvDataJava, pvDataCPP, pvDataCPP-md, and proposed interface

The following compares the definitions of the following: PVField, PVScalar and extensions, PVArray and extensions. -Note, however, that PVStructureArray is not discussed. +PVStructureArray is not discussed.

PVField

This is the base for all the PVXXX iterfaces. @@ -152,7 +166,7 @@ traversing structured data. The pvDataJava and pvDataCPP definitions are similar. pvDataCPP-md added method getFullName. The proposed interface is like the existing pvDataCPP except that -the toString and dumpValue methods are replaced by the stream operator<<. +the dumpValue method is replaced by the stream operator<<.

Java

interface PVField extends Requester, Serializable {
@@ -199,7 +213,7 @@ public:
    virtual bool equals(PVField &pv);
    virtual void toString(StringBuilder buf) ;
    virtual void toString(StringBuilder buf,int indentLevel);
-   std::ostream& dumpValue(std::ostream& o) const;
+   virtual std::ostream& dumpValue(std::ostream& o) const =0;
  ...
 }
 
@@ -250,7 +264,6 @@ public:
     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;
@@ -265,13 +278,12 @@ public:
     void postPut();
     void setPostHandler(PostHandlerPtr const &postHandler);
     virtual bool equals(PVField &pv);
-    virtual std::ostream& operator<<(std::ostream& o) const = 0;
-    virtual std::ostream& operator<<(std::ostream& o, size_t index) const = 0;
+    void toString(StringBuilder buf) ;
+    void toString(StringBuilder buf,int indentLevel);
+    std::ostream& operator<<(std::ostream& o) const;
 ...
 };
 
-std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
-std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f, size_t index);
 

PVScalar

The Java and pvDataCPP versions differ in that Java has an interface definition @@ -448,8 +460,6 @@ public: void operator>>=(T& value) const; void operator<<=(T value); - virtual std::ostream& operator<<(std::ostream& o) const - virtual std::ostream& operator>>(std::ostream& o, size_t index) const; ... }; typedef PVScalarValue<uint8> PVBoolean; @@ -501,6 +511,7 @@ For example PVDoubleArray::get becomes: The corresponding C++ version becomes:

     const svector & get();
+    const const_svector & get() const;
 

The remaining difference is that dumpValue is replaced by the stream operator<<.

@@ -511,17 +522,13 @@ This allows the C++ interface to be more similar to Java.

the extra methods and allows the client access to the shared_vector. The client is then able to perform C++ specific things to the data. -BUT it also means that if the client modifies the shared_vector the client is also responsibel -for ensuring that the immutable and capacity related features of PVField and PVArray are +BUT it also means that if the client modifies the shared_vector +the client is also responsible for ensuring that the +immutable and capacity related features of PVField and PVArray are respected and the postPut is properly handled. -The new method for PVValueArray: -
- void put(const svector &from); - -helps ensure that shared_vector from the client is kept in sync with the shared_vector wrapped -by PVValueArray. But the used is still responsible for making sure that -PVField::isImmutable is honored.

+

Note that two get methods exist. +One allows write access to the raw data and the other doesn't/

pvDataJava

interface PVArray extends PVField, SerializableArray {
     int getLength();
@@ -564,8 +571,6 @@ public:
  ...
 };
 
-std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);
-
 
 template<typename T>
 class PVArrayData {
@@ -590,13 +595,11 @@ public:
     typedef PVScalarArray &reference;
     typedef const PVScalarArray& const_reference;
     const ScalarArrayConstPtr getScalarArray() const ;
-    virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
  ...
 }
 
 template<typename T>
-class PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> {
-    typedef detail::PVVectorStorage<T,PVScalarArray> base_t;
+class PVValueArray : public PVScalarArray {
 public:
     POINTER_DEFINITIONS(PVValueArray);
     typedef T  value_type;
@@ -630,13 +633,6 @@ public:
 
 ...
 };
-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.
@@ -820,17 +816,8 @@ public:
  ...
 };
 
-// PVString is special case, since it implements SerializableArray
-class PVString : public PVScalarValue<String>, SerializableArray {
-public:
-    virtual ~PVString() {}
- ...
-};
-
 template<typename T>
-class PVValueArray :
-public PVScalarArray
-...
+class PVValueArray : public PVScalarArray
 {
 public:
     POINTER_DEFINITIONS(PVValueArray);
@@ -844,13 +831,11 @@ public:
     typedef shared_vector<const T> const_svector;
 
     virtual ~PVValueArray() {}
-    const svector & get() const;
+    const svector & get() ;
+    const const_svector &get() const;
     size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset);
-    void put(const svector & from);
 
     void shareData(const svector &from);
-    virtual std::ostream& operator<<(std::ostream& o) const;
-    virtual std::ostream& operator<<(std::ostream& o, size_t index) const;
 
 ...
 };
@@ -882,7 +867,6 @@ public:
     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;
@@ -897,8 +881,9 @@ public:
     void postPut();
     void setPostHandler(PostHandlerPtr const &postHandler);
     virtual bool equals(PVField &pv);
-    virtual  std::ostream& operator<<(std::ostream& o) const = 0;
-    virtual std::ostream& operator<<(std::ostream& o, size_t index) const = 0;
+    void toString(StringBuilder buf) ;
+    void toString(StringBuilder buf,int indentLevel);
+    std::ostream& operator<<(std::ostream& o) const;
 ...
 };
 
@@ -995,9 +980,6 @@ public:
     virtual void put(T value) = 0;
     void operator>>=(T& value) const;
     void operator<<=(T value);
-
-    virtual std::ostream& operator<<(std::ostream& o) const
-    virtual std::ostream& operator<<(std::ostream& o, size_t index) const;
 ...
 };
 typedef PVScalarValue<uint8> PVBoolean;
@@ -1095,13 +1077,6 @@ public:
     const ScalarArrayConstPtr getScalarArray() const;
  ...
 };
-
-// PVString is special case, since it implements SerializableArray
-class PVString : public PVScalarValue<String>, SerializableArray {
-public:
-    virtual ~PVString() {}
- ...
-};
 

where

@@ -1115,10 +1090,7 @@ public:

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

template<typename T>
-class PVValueArray :
-public PVScalarArray
-...
-{
+class PVValueArray : public PVScalarArray {
 public:
     POINTER_DEFINITIONS(PVValueArray);
     typedef T  value_type;
@@ -1131,14 +1103,11 @@ public:
     typedef shared_vector<const T> const_svector;
 
     virtual ~PVValueArray() {}
-    const svector & get() const;
+    const svector & get() ;
+    const const_svector &get() const;
     size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset);
-    void put(const svector & from);
 
     void shareData(const svector &from);
-
-    virtual std::ostream& operator<<(std::ostream& o) const
-    virtual std::ostream& operator<<(std::ostream& o, size_t index) const;
 ...
 };
 
@@ -1195,19 +1164,13 @@ typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
        than the cureent capacity allows.
        It does not change the current length.
       
-   
void put(const svector & from);
-
This puts data into the PVValueArray from the shared_vector. - If the shared_vector holds the same raw array as the PVValueArray then - the shared_vector held by the PVValueArray is put in sync with from. - If not the shared_vector will share the data. - potsPut will always be called.
shareData
Share data with an existing shared_vector. Note that if capacity is ever changed then data will no - longer be shared.
-
operator<<
-
operator>>
-
Methods for stream I/O.
+ longer be shared. + This method can also be called to force the PVValueArray to have a new + raw array. This is usefull for implementing Copy On Write. +

shared_vector

From 776ff49ed2c0409b942102b2f9e4714a1d35dbc7 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Wed, 3 Jul 2013 12:11:05 -0400 Subject: [PATCH 5/5] added --- documentation/pvDataDiscussion.html | 792 ++++++++++++++++++++++++++++ 1 file changed, 792 insertions(+) create mode 100644 documentation/pvDataDiscussion.html diff --git a/documentation/pvDataDiscussion.html b/documentation/pvDataDiscussion.html new file mode 100644 index 0000000..08a1e45 --- /dev/null +++ b/documentation/pvDataDiscussion.html @@ -0,0 +1,792 @@ + + + + + + EPICS pvDataDiscussion + + + + + + + + +
+

EPICS pvDataDiscussion

+ + +

EPICS v4 Working Group, Working Draft, 03-Jul-2013

+ +
+
Latest version:
+
pvDataDiscussion.html +
+
This version:
+
none
+
Previous version:
+
None
+
Editors:
+
Marty Kraimer, BNL
+
+ + +
+
+ + +
+

Table of Contents

+
+
+ + +

Introduction

+

As pvDataCPP progressed PVField and derived classes accumulated +more and more member functions. +These member functions have nothing to do with the primary primary +purpose for pvData: +

pvData (Process Variable Data) defines and implements an efficent +way to store, access, and communicate memory resident data structures.
+This statement appears as the first sentence of pvDataJava.html. +A few sentances later the document makes it clear that communication +includes efficent network communication. +Thus pvData provides an interface for network accessible structured data. +The problem of adding member functions that have nothing to do with the primary purpose +started with the Java API. +It already had extra methods that solved problems that should have had a different solution. +This document removes the extra methods so that when new problems arise in the future +the solution will not involve adding new member functions to the introspection and data API. +

+

The introspection and data API for pvData should only encapuslate methods that support the primary purpose +stated above. +The interfaces for C++ and Java should be similar so that +someone who understands the interface in one of the languages +and knows both languages will quickly understand the interface of the other language.

+

There is another problem with the existing API. There are methods that allow the "structure" +to change after an pvData object is created. An example is PVField::renameField(String newName). +Such methods should not exist.

+

There are methods regarding immutability: setImmutable, isImmutablei, setCapacityMutable, and isCapacityMutable. +Should they exists? For now lets assume no. +

+

One last issue is the interface for array data. This document proposes a simplified +version of what currently exists. It requires that the implementation always provides storage for +the complete raw array. The existing APIs allow the implementation to provide the data in +"chunks". Giving up this requirement simplifies the array interfaces. +The existing C++ implementation of PVValueArray has serious problems. +The shared_vector that is implemented in pvDataCP-md provides the solution to fixing +the problems. This document describes an API that is very similar to the new Java API +except that raw arrays are replaced by shared_vector.

+

This document will first describe changes to the existing Java interfaces +and then the corresponding C++ API.

+

Java API

+

The following shows which methods will be removed from the existing interfaces +and what will be added. +The methods to be removed are in red +and methods to add are in blue +Also the removed methods are at the end with a comment above. +The new methods also have a comment. +

+

Introspection Interfaces

+ +
interface Field extends Serializable {
+    String getId();
+    Type getType();
+    // following will be removed
+    void toString(StringBuilder buf);
+    void toString(StringBuilder buf,int indentLevel);
+    String toString();
+}
+
+
+// new interface
+interface FieldToString {
+    String toString(Field field);
+}
+
+interface Scalar extends Field {
+    ScalarType getScalarType();
+}
+
+interface ScalarArray extends Field {
+    ScalarType getElementType();
+}
+
+interface Structure extends Field {
+    Field getField(String fieldName);
+    int getFieldIndex(String fieldName);
+    Field[] getFields();
+    Field getField(int fieldIndex);
+    String[] getFieldNames();
+    String getFieldName(int fieldIndex)
+}
+
+interface StructureArray extends Field {
+    Structure getStructure();
+}
+
+interface FieldCreate {
+    Scalar createScalar(ScalarType scalarType);
+    ScalarArray createScalarArray(ScalarType elementType);
+    StructureArray createStructureArray(Structure elementStructure);
+    Structure createStructure(String[] fieldNames, Field[] field);
+    Structure createStructure(String id,String[] fieldNames, Field[] field);
+    Structure createStructure(Structure structToClone);
+    Field deserialize(ByteBuffer buffer, DeserializableControl control);
+    // following will be removed
+    Structure appendField(Structure structure,String fieldName, Field field);
+    Structure appendFields(Structure structure,String[] fieldNames, Field[] fields);
+}
+
+

Data Interfaces

+
+interface PVField extends Requester, Serializable {
+    String getFieldName();
+    void setRequester(Requester requester);
+    int getFieldOffset();
+    int getNextFieldOffset();
+    int getNumberFields();
+    Field getField();
+    PVStructure getParent();
+    void postPut();
+    void setPostHandler(PostHandler postHandler);
+    // following will be removed
+    PVAuxInfo getPVAuxInfo();
+    boolean isImmutable();
+    void setImmutable();
+    void renameField(String newName);
+    void toString(StringBuilder buf);
+    void toString(StringBuilder buf,int indentLevel);
+    String toString();
+}
+
+
+// The following is a new interface
+interface PVFieldToString {
+    String toString(PVField pvField);
+    void setMaxInitialArrayElements(int num);
+    void setMaxFinalArrayElements(int num);
+    int getMaxInitialArrayElements();
+    int getMaxFinalArrayElements();
+}
+    
+interface PVScalar extends PVField{
+    Scalar getScalar();
+}
+
+interface PVDouble extends PVScalar{
+    double get();
+    void put(double value);
+}
+// also PVBoolean, PVByte, PVShort, PVInt, PVLong, PVFloat, and PVString
+
+interface PVArray extends PVField, SerializableArray {
+    int getLength();
+    void setLength(int length);
+    int getCapacity();
+    void setCapacity(int length);
+    // following will be removed
+    boolean isCapacityMutable();
+    void setCapacityMutable(boolean isMutable);
+}
+
+interface PVScalarArray extends PVArray {
+    ScalarArray getScalarArray();
+}
+
+
+//following will be removed
+public class DoubleArrayData {
+    public double[] data;
+    public int offset;
+}
+
+interface PVDoubleArray extends PVArray {
+    // following are new
+    double[] get();
+    void swap(double[] value);
+    //following will be removed
+    int get(int offset, int len, DoubleArrayData data);
+    int put(int offset,int len, double[] from, int fromOffset);
+    void shareData(double[] from);
+}
+
+// also PVBooleanArray, ..., PVStringArray
+
+
+interface PVStructure extends PVField , BitSetSerializable{
+    Structure getStructure();
+    PVField[] getPVFields();
+    PVField getSubField(String fieldName);
+    PVField getSubField(int fieldOffset);
+    // The following are convenience methods
+    PVBoolean getBooleanField(String fieldName);
+    PVByte getByteField(String fieldName);
+    PVShort getShortField(String fieldName);
+    PVInt getIntField(String fieldName);
+    PVLong getLongField(String fieldName);
+    PVFloat getFloatField(String fieldName);
+    PVDouble getDoubleField(String fieldName);
+    PVString getStringField(String fieldName);
+    PVScalarArray getScalarArrayField(String fieldName);
+    PVStructureArray getStructureArrayField(String fieldName);
+    PVStructure getStructureField(String fieldName);
+    PVArray getArrayField(String fieldName,ScalarType elementType);
+    // following will be removed
+    void appendPVField(String fieldName,PVField pvField);
+    void appendPVFields(String[] fieldNames,PVField[] pvFields);
+    void removePVField(String fieldName);
+    void replacePVField(PVField oldPVField,PVField newPVField);
+    String getExtendsStructureName();
+    boolean putExtendsStructureName(String extendsStructureName);
+    public boolean checkValid();
+}
+ 
+
+//following will be removed
+public class StructureArrayData {
+    public PVStructure[] data;
+    public int offset;
+}
+
+
+interface PVStructureArray extends PVArray{
+    StructureArray getStructureArray();
+    // following are new
+    PVStructure[] get();
+    void swap(PVStructure[] value);
+    // following will be removed
+    int get(int offset, int length, StructureArrayData data);
+    int put(int offset,int length, PVStructure[] from, int fromOffset);
+    void shareData(PVStructure[] from);
+}
+
+
+public interface PVDataCreate {
+    PVField createPVField(Field field);
+    PVField createPVField(PVField fieldToClone);
+    PVScalar createPVScalar(Scalar scalar);
+    PVScalar createPVScalar(ScalarType fieldType);
+    PVScalar createPVScalar(PVScalar scalarToClone);
+    PVScalarArray createPVScalarArray(ScalarArray array);
+    PVScalarArray createPVScalarArray(ScalarType elementType);
+    PVScalarArray createPVScalarArray(PVScalarArray arrayToClone;
+    PVStructureArray createPVStructureArray(StructureArray structureArray);
+    PVStructure createPVStructure(Structure structure);
+    PVStructure createPVStructure(String[] fieldNames,Field[] fields);
+    PVStructure createPVStructure(PVStructure structToClone);
+    // following will be removed
+    PVField[] flattenPVStructure(PVStructure pvStructure);
+}
+
+

PVFieldToString

+

In addition to toString this has methods to limit the number of array element to display. +The existing Java implementation of toString displayed all elements. +For large arrays this is not desirable. +The new methods provide a way for the client to limit the number of elements. +The default might be set to something like display up to 10 elements with 5 fron the beginning and 5 from the end.

+

For C++ this can be a replacement for dumpValue.

+

PVBooleanArray, ..., PVStructureArray

+

The old get and put are replaced by two new and simpler methods: +

+
get
+
Returns the raw array. If the client code modifies the elements in the array then + the client must call postPut. The client also has to realize that if the raw array held by the PVXXXArray changes + then the client is no longer sharing data +
swap
+
This exchanges the old raw data with the new raw data.
+
+

+

+The method setCapacity will always create a new raw array and copy old data from the old to the new array. +This is not true now since the implementation does not create a new array if the old capacity is equal to the requested capacity. +

+

C++ API

+

The C++ class definitions are similar to the Java definitions with two main exceptions: +

+
toString
+
In c++ this is replaced by std::ostream.
+
raw array data
+
Java supports array data like double[] + The C++ replacement is shared_vector<double>, which is implemented + in pvDataCPP-md.
+

Introspection Interfaces

+ +
+class Field :
+    virtual public Serializable,
+    public std::tr1::enable_shared_from_this<Field>
+{
+public:
+    POINTER_DEFINITIONS(Field);
+    virtual ~Field();
+    Type getType() const{return m_type;}
+    virtual String getID() const = 0;
+    
+    // following will be removed
+    virtual void toString(StringBuilder buf) const{toString(buf,0);}
+    virtual void toString(StringBuilder buf,int indentLevel) const;
+    
+ ...
+};
+
+// new function
+std::ostream &toString(Field::const_reference field, std::ostream& o);
+
+
+class Scalar : public Field{
+public:
+    POINTER_DEFINITIONS(Scalar);
+    virtual ~Scalar();
+    typedef Scalar& reference;
+    typedef const Scalar& const_reference;
+
+    ScalarType getScalarType() const {return scalarType;}
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
+    
+    // following will be removed
+    virtual void toString(StringBuilder buf) const{toString(buf,0);}
+    virtual void toString(StringBuilder buf,int indentLevel) const;
+    virtual String getID() const;
+    
+ ...
+};
+class ScalarArray : public Field{
+public:
+    POINTER_DEFINITIONS(ScalarArray);
+    typedef ScalarArray& reference;
+    typedef const ScalarArray& const_reference;
+
+    ScalarArray(ScalarType scalarType);
+    ScalarType  getElementType() const {return elementType;}
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+    
+    // following will be removed
+    virtual void toString(StringBuilder buf) const{toString(buf,0);}
+    virtual void toString(StringBuilder buf,int indentLevel) const;
+    virtual String getID() const;
+    
+ ...
+};
+
+class Structure : public Field {
+public:
+    POINTER_DEFINITIONS(Structure);
+    typedef Structure& reference;
+    typedef const Structure& const_reference;
+
+   std::size_t getNumberFields() const {return numberFields;}
+   FieldConstPtr getField(String const & fieldName) const;
+   FieldConstPtr getField(std::size_t index) const;
+   std::size_t getFieldIndex(String const &fieldName) const;
+   FieldConstPtrArray const & getFields() const {return fields;}
+   StringArray const & getFieldNames() const;
+   String getFieldName(std::size_t fieldIndex);
+   virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+   virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+    
+    // following will be removed
+   void renameField(std::size_t fieldIndex,String const &newName);
+   virtual void toString(StringBuilder buf,int indentLevel) const;
+   virtual String getID() const;
+   
+ ...
+};
+
+class StructureArray : public Field{
+public:
+    POINTER_DEFINITIONS(StructureArray);
+    typedef StructureArray& reference;
+    typedef const StructureArray& const_reference;
+
+    StructureConstPtr  getStructure() const {return pstructure;}
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+    
+    // following will be removed
+    virtual void toString(StringBuilder buf,int indentLevel=0) const;
+    virtual String getID() const;
+    
+ ...
+};
+
+class FieldCreate  {
+public:
+    static FieldCreatePtr getFieldCreate();
+    ScalarConstPtr  createScalar(ScalarType scalarType) const
+    ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
+    StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
+    StructureConstPtr createStructure (
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    StructureConstPtr createStructure (
+        String const &id,
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
+    
+    // following will be removed
+    StructureConstPtr appendField(
+        StructureConstPtr const & structure,
+        String const &fieldName, FieldConstPtr const & field) const;
+    StructureConstPtr appendFields(
+        StructureConstPtr const & structure,
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    
+ ...
+};
+
+extern FieldCreatePtr getFieldCreate();
+ 
+

Data Interfaces

+
+class PVField
+: virtual public Serializable,
+  public std::tr1::enable_shared_from_this<PVField>
+{
+public:
+   POINTER_DEFINITIONS(PVField);
+   virtual ~PVField();
+   inline const String &getFieldName() const ;
+   virtual void setRequester(RequesterPtr const &prequester);
+   std::size_t getFieldOffset() const;
+   std::size_t getNextFieldOffset() const;
+   std::size_t getNumberFields() const;
+   const FieldConstPtr & getField() const ;
+   PVStructure * getParent() const
+   void postPut() ;
+   void setPostHandler(PostHandlerPtr const &postHandler);
+    // following will be removed
+    
+   virtual void message(String message,MessageType messageType);
+   void replacePVField(const PVFieldPtr&  newPVField);
+   String getFullName() const;
+   virtual bool equals(PVField &pv);
+   PVAuxInfoPtr & getPVAuxInfo()
+   bool isImmutable() const;
+   virtual void setImmutable();
+   void replacePVField(const PVFieldPtr&  newPVField);
+   void renameField(String const &newName);
+   virtual void toString(StringBuilder buf) ;
+   virtual void toString(StringBuilder buf,int indentLevel);
+   std::ostream& dumpValue(std::ostream& o) const;
+   
+ ...
+};
+
+
+// The following is a new class
+class PVFieldToString {
+    String toString(const PVFieldPtr &pvField);
+    void setMaxInitialArrayElements(size_t num);
+    void setMaxFinalArrayElements(size_t num);
+    size_t getMaxInitialArrayElements();
+    size_t getMaxFinalArrayElements();
+...
+}
+
+class PVScalar : public PVField {
+public:
+    POINTER_DEFINITIONS(PVScalar);
+    virtual ~PVScalar();
+    typedef PVScalar &reference;
+    typedef const PVScalar& const_reference;
+
+    const ScalarConstPtr getScalar() const ;
+ ...
+}
+
+
+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;
+    
+    // following will be removed
+    std::ostream& dumpValue(std::ostream& o)
+    void operator>>=(T& value) const;
+    void operator<<=(T value);
+    
+ ...
+}
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<String>, SerializableArray {
+public:
+    virtual ~PVString() {}
+ ...
+}
+class PVArray : public PVField, public SerializableArray {
+public:
+    POINTER_DEFINITIONS(PVArray);
+    virtual ~PVArray();
+    std::size_t getLength() const;
+    virtual void setLength(std::size_t length);
+    std::size_t getCapacity() const;
+    virtual void setCapacity(std::size_t capacity) = 0;
+    
+    // following will be removed
+    virtual void setImmutable();
+    bool isCapacityMutable() const;
+    void setCapacityMutable(bool isMutable);
+    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
+    
+ ...
+};
+
+class PVScalarArray : public PVArray {
+public:
+    POINTER_DEFINITIONS(PVScalarArray);
+    virtual ~PVScalarArray();
+    typedef PVScalarArray &reference;
+    typedef const PVScalarArray& const_reference;
+
+    const ScalarArrayConstPtr getScalarArray() const ;
+    
+    // following will be removed
+    virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
+    
+ ...
+}
+
+
+// following will be removed
+template<typename T>
+class PVArrayData {
+private:
+    std::vector<T> init;
+public:
+    POINTER_DEFINITIONS(PVArrayData);
+    typedef T  value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    std::vector<T> & data;
+    std::size_t offset;
+    PVArrayData()
+    : data(init)
+    {}
+};
+
+
+template<typename T>
+class PVValueArray : public PVScalarArray {
+public:
+    POINTER_DEFINITIONS(PVValueArray);
+    typedef T  value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    // following are new typeDefs
+    typedef shared_vector<T> svector;
+    typedef shared_vector<const T> const_svector; 
+
+    virtual ~PVValueArray() {}
+    // following are added
+    svector get();
+    void swap(svector& value);
+    
+    // following are removed
+    typedef PVValueArray & reference;
+    typedef const PVValueArray & const_reference;
+    typedef PVArrayData<T> ArrayDataType;
+    typedef std::vector<T> vector;
+    typedef const std::vector<T> const_vector;
+    typedef std::tr1::shared_ptr<vector> shared_vector;
+
+    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;
+    
+...
+};
+
+typedef PVValueArray<uint8> PVBooleanArray;
+typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
+...
+typedef PVValueArray<String> PVStringArray;
+typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
+
+class PVStructure : public PVField,public BitSetSerializable {
+public:
+    POINTER_DEFINITIONS(PVStructure);
+    virtual ~PVStructure();
+    typedef PVStructure & reference;
+    typedef const PVStructure & const_reference;
+
+    StructureConstPtr getStructure() const;
+    const PVFieldPtrArray & getPVFields() const;
+    PVFieldPtr getSubField(String const &fieldName) const;
+    PVFieldPtr getSubField(std::size_t fieldOffset) const;
+    PVBooleanPtr getBooleanField(String const &fieldName) ;
+    PVBytePtr getByteField(String const &fieldName) ;
+    PVShortPtr getShortField(String const &fieldName) ;
+    PVIntPtr getIntField(String const &fieldName) ;
+    PVLongPtr getLongField(String const &fieldName) ;
+    PVUBytePtr getUByteField(String const &fieldName) ;
+    PVUShortPtr getUShortField(String const &fieldName) ;
+    PVUIntPtr getUIntField(String const &fieldName) ;
+    PVULongPtr getULongField(String const &fieldName) ;
+    PVFloatPtr getFloatField(String const &fieldName) ;
+    PVDoublePtr getDoubleField(String const &fieldName) ;
+    PVStringPtr getStringField(String const &fieldName) ;
+    PVStructurePtr getStructureField(String const &fieldName) ;
+    PVScalarArrayPtr getScalarArrayField(
+        String const &fieldName,ScalarType elementType) ;
+    PVStructureArrayPtr getStructureArrayField(String const &fieldName) ;
+    virtual void serialize(
+        ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
+    virtual void deserialize(
+        ByteBuffer *pbuffer,DeserializableControl *pflusher);
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher,BitSet *pbitSet) const;
+    virtual void deserialize(ByteBuffer *pbuffer,
+        DeserializableControl*pflusher,BitSet *pbitSet);
+    PVStructure(StructureConstPtr const & structure);
+    PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields);
+    
+    // following are removed
+    void appendPVField(
+        String const &fieldName,
+        PVFieldPtr const & pvField);
+    void appendPVFields(
+        StringArray const & fieldNames,
+        PVFieldPtrArray const & pvFields);
+    void removePVField(String const &fieldName);
+    virtual void setImmutable();
+    String getExtendsStructureName() const;
+    bool putExtendsStructureName(
+        String const &extendsStructureName);
+    
+};
+
+
+// following will be removed
+typedef PVArrayData<PVStructurePtr> StructureArrayData;
+
+
+class PVStructureArray : public PVArray
+{
+public:
+    POINTER_DEFINITIONS(PVStructureArray);
+    typedef PVStructurePtr  value_type;
+    typedef PVStructurePtr* pointer;
+    typedef const PVStructurePtr* const_pointer;
+    
+    // following are new typeDefs
+    typedef shared_vector<PVStructurePtr> svector;
+    typedef shared_vector<const PVStructurePtr> const_svector;
+    
+
+    virtual ~PVStructureArray() {}
+    virtual void setCapacity(size_t capacity);
+    virtual void setLength(std::size_t length);
+    virtual StructureArrayConstPtr getStructureArray() const ;
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher) const;
+    virtual void deserialize(ByteBuffer *buffer,
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
+    // following are new
+    svector get();
+    void swap(svector & value);
+    
+    // following are removed
+    typedef PVArrayData<PVStructurePtr> ArrayDataType;
+    typedef std::vector<PVStructurePtr> vector;
+    typedef const std::vector<PVStructurePtr> const_vector;
+    typedef std::tr1::shared_ptr<vector> shared_vector;
+    typedef PVStructureArray &reference;
+    typedef const PVStructureArray& const_reference;
+    
+    virtual std::size_t append(std::size_t number);
+    virtual bool remove(std::size_t offset,std::size_t number);
+    virtual void compress();
+    virtual std::size_t get(std::size_t offset, std::size_t length,
+        StructureArrayData &data);
+    virtual std::size_t put(std::size_t offset,std::size_t length,
+        const_vector const & from, std::size_t fromOffset);
+    virtual void shareData(
+         shared_vector const & value,
+         std::size_t capacity,
+         std::size_t length);
+    virtual pointer get() { return &((*value.get())[0]); }
+    virtual pointer get() const { return &((*value.get())[0]); }
+    virtual vector const & getVector() {return *value;}
+    virtual shared_vector const & getSharedVector() {return value;}
+    
+ ...
+};
+
+class PVDataCreate {
+public:
+    static PVDataCreatePtr getPVDataCreate();
+    PVFieldPtr createPVField(FieldConstPtr const & field);
+    PVFieldPtr createPVField(PVFieldPtr const & fieldToClone);
+    PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
+    PVScalarPtr createPVScalar(ScalarType scalarType);
+    PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
+    PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
+    PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
+    PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const  & scalarArrayToClone);
+    PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
+    PVStructurePtr createPVStructure(StructureConstPtr const & structure);
+    PVStructurePtr createPVStructure(
+        StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
+   PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
+ ...
+};
+
+extern PVDataCreatePtr getPVDataCreate();
+
+ + +
+ +