From 3de28e3cef76fbf2d0b234181ed5743617a1e707 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Thu, 13 Jun 2013 14:52:27 -0400 Subject: [PATCH] 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); }; }}