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 @@ + + + +
+ +This product is made available subject to acceptance of the EPICS open source +license.
+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.
+ +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. +
+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: +
The following subsections are organized as follows: +
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. +
+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.
+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.
+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; ++ +
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; ++ +
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 ++
These are member types defined by std::tr1::shared_ptr. +These are not used by any of the client methods.
+ +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
++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. +
+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} []"? +
++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, ...]
+
++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. +
+ ++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.
+ + + +
+ 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.
+ +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(); ++ +
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 ++ +
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;
+}
+
+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.
+Brief Summary +
+push_back(x) Add an element after the last element +pop_back(x) Remove the last element. ++
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 +... ++ +
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>= ++
+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 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 ++ +
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. +
+void make_unique(); +bool unique() const; ++
+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 ++
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 ++ + +
Not yet documented
+ +Not yet documented
+ +Not yet documented
+ +INGORE REST OF DOCUMENT!!!!
+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;
+ ...
+};
+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
+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
+Both get and put return the number of elements actually transfered. The +arguments are:
+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;
+ }
+}
+
+
+
+