diff --git a/documentation/pvDataCPP_20121212.html b/documentation/pvDataCPP_20121212.html new file mode 100644 index 0000000..78d053e --- /dev/null +++ b/documentation/pvDataCPP_20121212.html @@ -0,0 +1,3646 @@ + + + +
+ +This product is made available subject to acceptance of the EPICS open source +license.
+pvDataCPP is a computer software package for the efficient +storage, access, and communication, of structured data. It is specifically the +C++ implementation of pvData, which is one part of the set of related products in the EPICS +V4 control system programming environment:
+Each of these products has a Java and a C++ implementation.
+ +The products are all part of the V4 implementation of Experimental Physics and Industrial +Control System (EPICS).
+ +This is the 12-Dec-2012 version of the C++ implementation of pvData.
+ +The text describes software which is a complete implementation of pvData as +currently planned by the EPICS V4 Working Group.
+ +The following is a list of unresolved issues for pvDataCPP:
++class Structure +... +StringArray fieldNames; +FieldConstPtrArray fields + +class PVStructure +... +PVFieldPtrArray pvFields; ++To +
+class Structure +... +StringArrayPtr fieldNames; +FieldConstPtrArrayPtr fields + +class PVStructure +... +PVFieldPtrArrayPtr pvFields; ++If these are changed several methods also change so that raw vectors are never passed as +argument or returned from methods.
pvData is one of a set of related projects. It describes and implements the +data that the other projects support. Thus it is not useful by itself but +understanding pvData is required in order to understand the other projects. The +reader should also become familar with projects pvAccess and pvIOC, which are +located via the same sourceforge site as this project.
+ +The Java and C++ implementation of pvData implement the same data model but +differ in implementation because of the differences between Java and C++.
+ +It is a good idea to read all of pvDataJava.html but read at least the +first two chapters:
+The material in these two chapters is NOT repeated in this documentation.
+ +Doxygen documentation is available at doxygenDoc
+ +All code in project pvDataCPP appears in namespace:
+namespace epics { namespace pvData {
+ // ...
+}}
+
+pvDataCPP introspection and data objects are designed to be shared. They are +made availiable via std::tr1::shared_ptr. In addition arrays are +implemented via std::vector. The following naming conventions are used +in typedefs:
+As an example pvType.h includes the following definitions:
+typedef std::vector<double> DoubleArray;
+typedef std::tr1::shared_ptr<DoubleArray> DoubleArrayPtr;
+inline double * get(DoubleArray &value)
+{
+ return &value[0];
+}
+inline const double * get(const DoubleArray &value)
+{
+ return static_cast<const double *>(&value[0]);
+}
+typedef std::vector<double>::iterator DoubleArray_iterator;
+typedef std::vector<double>::const_iterator DoubleArray_const_iterator;
+
+where
+Directory pvDataApp/pv has header files that completely describe pvData. The +implementation is provided in directory pvDataApp/factory. Test programs +appears in testApp/pv.
+ +NOTES:
+A PVStructure is a field that contains an array of subfields. Each field has +code for accessing the field. The interface for each field is an interface that +extends PVField. Each field also has an introspection interface, which an +extension of Field. This section describes the complete set of C++ +introspection and data interfaces for pvData.
+ +Class FieldCreate creates introspection objects. Class PVDataCreate creates +data objects. Class Convert provides a rich set of methods for converting and +copying data between fields.
+ +Directory pvDataApp/pv has the following header files:
+This provides C/C++ definitions for the pvData primitive types: boolean, +byte, short, int, long, ubyte,ushort, uint,u long,float, double, and string. +Because pvData is network data, the C++ implementation must implement the +proper semantics for the primitive types.
+ +pvType.h provides the proper semantics.
+ +It has the definitions:
+typedef uint8_t boolean; +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; +// float and double are types +typedef std::string String; + +/** + * A boolean array. + */ +typedef std::vector<uint8> BooleanArray; +typedef std::tr1::shared_ptr<BooleanArray> BooleanArrayPtr; +/* get is same is ubyte*/ +typedef std::vector<uint8>::iterator BooleanArray_iterator; +typedef std::vector<uint8>::const_iterator BooleanArray_const_iterator; + +/** + * A byte array. + */ +typedef std::vector<int8> ByteArray; +typedef std::tr1::shared_ptr<ByteArray> ByteArrayPtr; +inline int8 * get(ByteArray &value); +inline int8 const * get(ByteArray const &value); +inline int8 * get(ByteArrayPtr &value); +inline int8 const * get(ByteArrayPtr const &value); +inline ByteArray & getVector(ByteArrayPtr &value); +inline ByteArray const & getVector(ByteArrayPtr const &value); +typedef std::vector<int8>::iterator ByteArray_iterator; +typedef std::vector<int8>::const_iterator ByteArray_const_iterator; + +/* similar definitions are present for ALL the primitive types */+ +
where
+This subsection describes pvIntrospect.h This file is quite big so rather +than showing the entire file, it will be described in parts.
+ +A primary reason for pvData is to support network access to structured data. +pvAccess transports top level pvStructures. In addition a pvAccess server holds +a set of pvnames, where each pvname if a unique name in the local network.
+ +Given a pvname PV), it is possible to introspect the field without requiring +access to data. The reflection and data interfaces are separate because the +data may not be available. For example when a pvAccess client connects to a PV, +the client library can obtain the reflection information without obtaining any +data. Only when a client issues an I/O request will data be available. This +separation is especially important for arrays and structures so that a client +can discover the type without requiring that a large data array or structure be +transported over the network.
+ +Types are defined as:
+enum Type {
+ scalar,
+ scalarArray,
+ structure,
+ structureArray;
+};
+
+class TypeFunc {
+public:
+ const char* name(Type);
+ static void toString(StringBuilder buf,const Type type);
+};
+
+enum ScalarType {
+ pvBoolean,
+ pvByte, pvShort, pvInt, pvLong,
+ pvUByte, pvUShort, pvUInt, pvULong,
+ pvFloat,pvDouble,
+ pvString;
+};
+
+namespace ScalarTypeFunc {
+public:
+ bool isInteger(ScalarType type);
+ bool isUInteger(ScalarType type);
+ bool isNumeric(ScalarType type);
+ bool isPrimitive(ScalarType type);
+ ScalarType getScalarType(String const &value);
+ const char* name(ScalarType);
+ void toString(StringBuilder buf,ScalarType scalarType);
+};
+
+Type is one of the following:
+ScalarType is one of the following:
+TypeFunction is a set of convenience methods for Type
+ScalarTypeFunction is a set of convenience methods for ScalarType
+This section describes the reflection interfaces which provide the +following:
+class Field;
+class Scalar;
+class ScalarArray;
+class Structure;
+class StructureArray;
+
+typedef std::tr1::shared_ptr<const Field> FieldConstPtr;
+typedef std::vector<FieldConstPtr> FieldConstPtrArray;
+typedef std::tr1::shared_ptr<const Scalar> ScalarConstPtr;
+typedef std::tr1::shared_ptr<const ScalarArray> ScalarArrayConstPtr;
+typedef std::tr1::shared_ptr<const Structure> StructureConstPtr;
+typedef std::tr1::shared_ptr<const StructureArray> StructureArrayConstPtr;
+
+
+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;
+ virtual void toString(StringBuilder buf) const{toString(buf,0);}
+ virtual void toString(StringBuilder buf,int indentLevel) const;
+ ...
+};
+
+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 toString(StringBuilder buf) const{toString(buf,0);}
+ virtual void toString(StringBuilder buf,int indentLevel) const;
+ virtual String getID() const;
+ virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+ virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
+ ...
+};
+
+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 toString(StringBuilder buf) const{toString(buf,0);}
+ virtual void toString(StringBuilder buf,int indentLevel) const;
+ virtual String getID() const;
+ virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+ virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+ ...
+};
+
+class StructureArray : public Field{
+public:
+ POINTER_DEFINITIONS(StructureArray);
+ typedef StructureArray& reference;
+ typedef const StructureArray& const_reference;
+
+ StructureConstPtr getStructure() const {return pstructure;}
+ virtual void toString(StringBuilder buf,int indentLevel=0) const;
+ virtual String getID() const;
+ virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+ virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+ ...
+};
+
+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;
+ void renameField(std::size_t fieldIndex,String const &newName);
+ String getFieldName(std::size_t fieldIndex);
+ virtual void toString(StringBuilder buf,int indentLevel) const;
+ virtual String getID() const;
+ virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+ virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+ ...
+};
+
+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;
+ StructureConstPtr appendField(
+ StructureConstPtr const & structure,
+ String const &fieldName, FieldConstPtr const & field) const;
+ StructureConstPtr appendFields(
+ StructureConstPtr const & structure,
+ StringArray const & fieldNames,
+ FieldConstPtrArray const & fields) const;
+ FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
+ ...
+};
+
+extern FieldCreatePtr getFieldCreate();
+The file standardField.h has a class description for creating or sharing +Field objects for standard fields. For each type of field a method is provided. +Each creates a structure that has a field named "value" and a set of properyt +fields, The property field is a comma separated string of property names of the +following: alarm, timeStamp, display, control, and valueAlarm. An example is +"alarm,timeStamp,valueAlarm". The method with properties creates a structure +with fields named value and each of the property names. Each property field is +a structure defining the property. The details about each property is given in +the section named "Property". For example the call:
+StructureConstPtr example = standardField->scalar( + pvDouble, + "value,alarm,timeStamp");+ +
Will result in a Field definition that has the form:
+structure example + double value + alarm_t alarm + int severity + int status + string message + timeStamp_t timeStamp + long secondsPastEpoch + int nanoSeconds + int userTag+ +
In addition there are methods that create each of the property structures, +i.e. the methods named: alarm, .... enumeratedAlarm."
+ +standardField.h contains:
+class StandardField;
+typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
+
+class StandardField {
+public:
+ static StandardFieldPtr getStandardField();
+ ~StandardField();
+ StructureConstPtr scalar(ScalarType type,String const &properties);
+ StructureConstPtr scalarArray(
+ ScalarType elementType, String const &properties);
+ StructureConstPtr structureArray(
+ StructureConstPtr const & structure,String const &properties);
+ StructureConstPtr enumerated();
+ StructureConstPtr enumerated(String const &properties);
+ StructureConstPtr alarm();
+ StructureConstPtr timeStamp();
+ StructureConstPtr display();
+ StructureConstPtr control();
+ StructureConstPtr booleanAlarm();
+ StructureConstPtr byteAlarm();
+ StructureConstPtr ubyteAlarm();
+ StructureConstPtr shortAlarm();
+ StructureConstPtr ushortAlarm();
+ StructureConstPtr intAlarm();
+ StructureConstPtr uintAlarm();
+ StructureConstPtr longAlarm();
+ StructureConstPtr ulongAlarm();
+ StructureConstPtr floatAlarm();
+ StructureConstPtr doubleAlarm();
+ StructureConstPtr enumeratedAlarm();
+ ...
+};
+This subsection describes pvData.h This file is quite big so rather than +showing the entire file, it will be described in parts.
+ +These are typedefs for Array and Ptr for the various pvData class +definitions, i.e. typdefs for "std::vector" and "std::tr1::shared_ptr".
+class PVAuxInfo; +class PostHandler; + +class PVField; +class PVScalar; + +class PVScalarArray; + +class PVStructure; +class PVStructureArray; + +typedef std::tr1::shared_ptr<PVAuxInfo> PVAuxInfoPtr; + +typedef std::tr1::shared_ptr<PostHandler> PostHandlerPtr; + +typedef std::tr1::shared_ptr<PVField> PVFieldPtr; +typedef std::vector<PVFieldPtr> PVFieldPtrArray; +typedef std::vector<PVFieldPtr>::iterator PVFieldPtrArray_iterator; +typedef std::vector<PVFieldPtr>::const_iterator PVFieldPtrArray_const__iterator; + +typedef std::tr1::shared_ptr<PVScalar> PVScalarPtr; +typedef std::tr1::shared_ptr<PVScalarArray> PVScalarArrayPtr; + +typedef std::tr1::shared_ptr<PVStructure> PVStructurePtr; +typedef std::vector<PVStructurePtr> PVStructurePtrArray; +typedef std::vector<PVStructurePtr>::iterator PVStructurePtrArray_iterator; +typedef std::vector<PVStructurePtr>::const_iterator PVStructurePtrArray_const__iterator; + +typedef std::tr1::shared_ptr<PostHandler> PostHandlerPtr+ +
PostHandler is a class that must be implemented by any code that calls +setPostHandler. It's single virtual method. postPut is called whenever +PVField::postPut is called.
+class PostHandler
+{
+public:
+ POINTER_DEFINITIONS(PostHandler);
+ virtual ~PostHandler(){}
+ virtual void postPut() = 0;
+};
+
+PVField is the base interface for accessing data. A data structure consists +of a top level PVStructure. Every field of every structure of every top level +structure has a PVField associated with it.
+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;
+ ...
+}
+
+The public methods for PVField are:
+AuxInfo (Auxillary Information) is information about a field that is +application specific. It will not be available outside the application that +implements the database. In particular it will not be made available to Channel +Access. It is used by the database itself to override the default +implementation of fields. The JavaIOC uses it for attaching support code. +Database Configuration and other tools can use it for configuration +information. Each Field and each PVField can have have an arbitrary number of +auxInfos. An auxInfo is a (key,PVScalar) pair where key is a string.
+class PVAuxInfo : private NoDefaultMethods {
+public:
+ typedef std::map<String,PVScalarPtr> PVInfoMap;
+ typedef std::map<String,PVScalarPtr>::iterator PVInfoIter;
+ typedef std::pair<String,PVScalarPtr> PVInfoPair;
+
+ PVAuxInfo(PVField *pvField);
+ ~PVAuxInfo();
+ PVField * getPVField();
+ PVScalarPtr createInfo(String const &key,ScalarType scalarType);
+ PVScalarPtr getInfo(String const &key);
+ PVInfoMap & getInfoMap();
+ void toString(StringBuilder buf);
+ void toString(StringBuilder buf,int indentLevel);
+ ...
+};
+
+where
+This is the base class for all scalar data.
+class PVScalar : public PVField {
+public:
+ POINTER_DEFINITIONS(PVScalar);
+ virtual ~PVScalar();
+ typedef PVScalar &reference;
+ typedef const PVScalar& const_reference;
+ const ScalarConstPtr getScalar() const ;
+ ...
+}
+
+where
+The interfaces for primitive data types are:
+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;
+ ...
+}
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<String>, SerializableArray {
+public:
+ virtual ~PVString() {}
+ ...
+};
+
+where
+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;
+ ...
+};
+This is the argument to one of the get methods of PVValueArray.
+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)
+ {}
+};
+
+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;
+ }
+}
+
+
+
+The interface for a structure is:
+class PVStructure : public PVField,public BitSetSerializable {
+public:
+ POINTER_DEFINITIONS(PVStructure);
+ virtual ~PVStructure();
+ typedef PVStructure & reference;
+ typedef const PVStructure & const_reference;
+ virtual void setImmutable();
+ StructureConstPtr getStructure() const;
+ const PVFieldPtrArray & getPVFields() const;
+ PVFieldPtr getSubField(String const &fieldName) const;
+ PVFieldPtr getSubField(std::size_t fieldOffset) const;
+ void appendPVField(
+ String const &fieldName,
+ PVFieldPtr const & pvField);
+ void appendPVFields(
+ StringArray const & fieldNames,
+ PVFieldPtrArray const & pvFields);
+ void removePVField(String const &fieldName);
+ 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) ;
+ String getExtendsStructureName() const;
+ bool putExtendsStructureName(
+ String const &extendsStructureName);
+ 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);
+};
+
+where
+The interface for an array of structures is:
+typedef PVArrayData<PVStructurePtr> StructureArrayData;
+
+class PVStructureArray : public PVArray
+{
+public:
+ POINTER_DEFINITIONS(PVStructureArray);
+ typedef PVStructurePtr value_type;
+ typedef PVStructurePtr* pointer;
+ typedef const PVStructurePtr* const_pointer;
+ 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 ~PVStructureArray() {}
+ virtual void setCapacity(size_t capacity);
+ virtual void setLength(std::size_t length);
+ virtual StructureArrayConstPtr getStructureArray() const ;
+ 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 void serialize(ByteBuffer *pbuffer,
+ SerializableControl *pflusher) const;
+ virtual void deserialize(ByteBuffer *buffer,
+ DeserializableControl *pflusher);
+ virtual void serialize(ByteBuffer *pbuffer,
+ SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
+ 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;}
+ ...
+}
+
+where
+The other methods are similar to the methods for other array types.
+ +PVDataCreate is an interface that provides methods that create PVField +interfaces. A factory is provided that creates PVDataCreate.
+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();
+
+where
+A class StandardPVField has methods for creating standard data fields. Like +class StandardField it has two forms of the methods which create a field, one +without properties and one with properties. Again the properties is some +combination of alarm, timeStamp, control, display, and valueAlarm. And just +like StandardField there are methods to create the standard properties. The +methods are:
+class StandardPVField;
+typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
+
+class StandardPVField : private NoDefaultMethods {
+public:
+ static StandardPVFieldPtr getStandardPVField();
+ ~StandardPVField();
+ PVStructurePtr scalar(ScalarType type,String const &properties);
+ PVStructurePtr scalarArray(ScalarType elementType, String const &properties);
+ PVStructurePtr structureArray(StructureConstPtr const &structure,String const &properties);
+ PVStructurePtr enumerated(StringArray const &choices);
+ PVStructurePtr enumerated(StringArray const &choices, String const &properties);
+ ...
+}
+
+
+extern StandardPVFieldPtr getStandardPVField();
+
+NOTE about copying immutable array fields. If an entire immutable array +field is copied to another array that has the same elementType, both offsets +are 0, and the length is the length of the source array, then the shareData +method of the target array is called and the target array is set immutable. +Thus the source and target share the same primitive array.
+ +This section describes the supported conversions between data types.
+bool operator==(PVField&, PVField&);
+
+static inline bool operator!=(PVField& a, PVField& b)
+{return !(a==b);}
+
+
+bool operator==(const Field&, const Field&);
+bool operator==(const Scalar&, const Scalar&);
+bool operator==(const ScalarArray&, const ScalarArray&);
+bool operator==(const Structure&, const Structure&);
+bool operator==(const StructureArray&, const StructureArray&);
+
+static inline bool operator!=(const Field& a, const Field& b)
+{return !(a==b);}
+static inline bool operator!=(const Scalar& a, const Scalar& b)
+{return !(a==b);}
+static inline bool operator!=(const ScalarArray& a, const ScalarArray& b)
+{return !(a==b);}
+static inline bool operator!=(const Structure& a, const Structure& b)
+{return !(a==b);}
+static inline bool operator!=(const StructureArray& a, const StructureArray& b)
+{return !(a==b);}
+class Convert;
+typedef std::tr1::shared_ptr<Convert> ConvertPtr;
+
+class Convert {
+public:
+ static ConvertPtr getConvert();
+ ~Convert();
+ void getFullName(StringBuilder buf,PVFieldPtr const & pvField);
+ bool equals(PVFieldPtr const &a,PVFieldPtr const &b);
+ bool equals(PVField &a,PVField &b);
+ void getString(StringBuilder buf,PVFieldPtr const & pvField,int indentLevel);
+ void getString(StringBuilder buf,PVFieldPtr const & pvField);
+ void getString(StringBuilder buf,PVField const * pvField,int indentLevel);
+ void getString(StringBuilder buf,PVField const * pvField);
+ std::size_t fromString(
+ PVStructurePtr const &pv,
+ StringArray const & from,
+ std::size_t fromStartIndex = 0);
+ void fromString(PVScalarPtr const & pv, String const & from);
+ std::size_t fromString(PVScalarArrayPtr const & pv, String const &from);
+ std::size_t fromStringArray(
+ PVScalarArrayPtr const & pv,
+ std::size_t offset, std::size_t length,
+ StringArray const & from,
+ std::size_t fromOffset);
+ std::size_t toStringArray(PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ StringArray & to,
+ std::size_t toOffset);
+ bool isCopyCompatible(FieldConstPtr const & from, FieldConstPtr const & to);
+ void copy(PVFieldPtr const & from, PVFieldPtr const & to);
+ bool isCopyScalarCompatible(
+ ScalarConstPtr const & from,
+ ScalarConstPtr const & to);
+ void copyScalar(PVScalarPtr const & from, PVScalarPtr const & to);
+ bool isCopyScalarArrayCompatible(
+ ScalarArrayConstPtr const & from,
+ ScalarArrayConstPtr const & to);
+ std::size_t copyScalarArray(
+ PVScalarArrayPtr const & from,
+ std::size_t offset,
+ PVScalarArrayPtr const & to,
+ std::size_t toOffset,
+ std::size_t length);
+ bool isCopyStructureCompatible(
+ StructureConstPtr const & from, StructureConstPtr const & to);
+ void copyStructure(PVStructurePtr const & from, PVStructurePtr const & to);
+ bool isCopyStructureArrayCompatible(
+ StructureArrayConstPtr const & from, StructureArrayConstPtr const & to);
+ void copyStructureArray(
+ PVStructureArrayPtr const & from, PVStructureArrayPtr const & to);
+ int8 toByte(PVScalarPtr const & pv);
+ int16 toShort(PVScalarPtr const & pv);
+ int32 toInt(PVScalarPtr const & pv);
+ int64 toLong(PVScalarPtr const & pv);
+ uint8 toUByte(PVScalarPtr const & pv);
+ uint16 toUShort(PVScalarPtr const & pv);
+ uint32 toUInt(PVScalarPtr const & pv);
+ uint64 toULong(PVScalarPtr const & pv);
+ float toFloat(PVScalarPtr const & pv);
+ double toDouble(PVScalarPtr const & pv);
+ String toString(PVScalarPtr const & pv);
+ void fromByte(PVScalarPtr const & pv,int8 from);
+ void fromShort(PVScalarPtr const & pv,int16 from);
+ void fromInt(PVScalarPtr const & pv, int32 from);
+ void fromLong(PVScalarPtr const & pv, int64 from);
+ void fromUByte(PVScalarPtr const & pv,uint8 from);
+ void fromUShort(PVScalarPtr const & pv,uint16 from);
+ void fromUInt(PVScalarPtr const & pv, uint32 from);
+ void fromULong(PVScalarPtr const & pv, uint64 from);
+ void fromFloat(PVScalarPtr const & pv, float from);
+ void fromDouble(PVScalarPtr const & pv, double from);
+ std::size_t toByteArray(PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ int8* to,
+ std::size_t toOffset);
+ std::size_t toShortArray(PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ int16* to,
+ std::size_t toOffset);
+ std::size_t toIntArray(PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ int32* to,
+ std::size_t toOffset);
+ std::size_t toLongArray(PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ int64* to,
+ std::size_t toOffset);
+ std::size_t toUByteArray(PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ uint8* to,
+ std::size_t toOffset);
+ std::size_t toUShortArray(PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ uint16* to,
+ std::size_t toOffset);
+ std::size_t toUIntArray(
+ PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ uint32* to,
+ std::size_t toOffset);
+ std::size_t toULongArray(
+ PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ uint64* to,
+ std::size_t toOffset);
+ std::size_t toFloatArray(
+ PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ float* to,
+ std::size_t toOffset);
+ std::size_t toDoubleArray(
+ PVScalarArrayPtr const & pv,
+ std::size_t offset,
+ std::size_t length,
+ double* to, std::size_t
+ toOffset);
+ std::size_t fromByteArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const int8* from, std::size_t fromOffset);
+ std::size_t fromByteArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const ByteArray & from, std::size_t fromOffset);
+ std::size_t fromShortArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const int16* from, std::size_t fromOffset);
+ std::size_t fromShortArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const ShortArray & from, std::size_t fromOffset);
+ std::size_t fromIntArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const int32* from, std::size_t fromOffset);
+ std::size_t fromIntArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const IntArray & from, std::size_t fromOffset);
+ std::size_t fromLongArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const int64* from, std::size_t fromOffset);
+ std::size_t fromLongArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const LongArray & from, std::size_t fromOffset);
+ std::size_t fromUByteArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const uint8* from, std::size_t fromOffset);
+ std::size_t fromUByteArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const UByteArray & from, std::size_t fromOffset);
+ std::size_t fromUShortArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const uint16* from, std::size_t fromOffset);
+ std::size_t fromUShortArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const UShortArray & from, std::size_t fromOffset);
+ std::size_t fromUIntArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const uint32* from, std::size_t fromOffset);
+ std::size_t fromUIntArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const UIntArray & from, std::size_t fromOffset);
+ std::size_t fromULongArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const uint64* from, std::size_t fromOffset);
+ std::size_t fromULongArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const ULongArray & from, std::size_t fromOffset);
+ std::size_t fromFloatArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const float* from, std::size_t fromOffset);
+ std::size_t fromFloatArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const FloatArray & from, std::size_t fromOffset);
+ std::size_t fromDoubleArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const double* from, std::size_t fromOffset);
+ std::size_t fromDoubleArray(
+ PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
+ const DoubleArray & from, std::size_t fromOffset);
+ void newLine(StringBuilder buf, int indentLevel);
+ ...
+}
+
+extern ConvertPtr getConvert();
+
+The array methods all return the number of elements copied or converted. +This can be less than len if the PVField array contains less than len +elements.
+ +newLine is a convenience method for code that implements toString It +generates a newline and inserts blanks at the beginning of the newline.
+ +Only fields named "value" have properties. A record can have multiple value +fields, which can appear in the top level structure of a record or in a +substructure. All other fields in the structure containing a value field are +considered properties of the value field. The fieldname is also the property +name. The value field can have any type, i.e. scalar, scalarArray, or +structure. Typical property fields are timeStamp, alarm, display, control, and +history. The timeStamp is a special case. If it appears anywhere in the +structure hieraracy above a value field it is a property of the value field.
+ +For example the following top level structure has a single value field. The +value field has properties alarm, timeStamp, and display.
+structure counterOutput + double value + alarm_t + int severity 0 + int status 0 + string message + timeStamp_t + long secondsPastEpoch + int nanoSeconds + int userTag + display_t + double limitLow 0.0 + double limitHigh 10.0 + string description "Sample Description" + string format "%f" + string units volts+ +
The following example has three value fields each with properties alarm and +timeStamp. Voltage, Current, and Power each have a different alarms but all +share the timeStamp.
+structure powerSupplyValue + double value + alarm_t + int severity 0 + int status 0 + string message + +structure powerSupplySimple + alarm_t + int severity 0 + int status 0 + string message + timeStamp_t + long secondsPastEpoch + int nanoSeconds + int userTag + powerSupplyValue_t voltage + double value + alarm_t + int severity 0 + int status 0 + string message + powerSupplyValue_t power + double value + alarm_t + int severity 0 + int status 0 + string message + powerSupplyValue_t current + double value + alarm_t + int severity 0 + int status 0 + string message+ +
The following field names have special meaning, i.e. support properties for +general purpose clients.
+In addition a structure can have additional fields that support the value +field but are not recognized by most general purpose client tools. Typical +examples are:
+The model allows for device records. A device record has structure fields +that that support the PVData data model. For example a powerSupport record can +have fields power, voltage, current that each support the PVData data model. +
+ +Except for enumerated, each property has two files: a property.h and a +pvProperty.h . For example: timeStamp.h and pvTimeStamp.h In each case the +property.h file defined methods for manipulating the property data and the +pvProperty.h provides methods to transfer the property data to/from a pvData +structure.
+ +All methods copy data via copy by value semantics, i.e. not by pointer or by +reference. No property class calls new or delete and all allow the compiler to +generate default methods. All allow a class instance to be generated on the +stack. For example the following is permitted:
+void example(PVFieldPtr const &pvField) {
+ Alarm alarm;
+ PVAlarm pvAlarm;
+ bool result;
+ result = pvAlarm.attach(pvField);
+ assert(result);
+ Alarm al;
+ al.setMessage(String("testMessage"));
+ al.setSeverity(majorAlarm);
+ result = pvAlarm.set(al);
+ assert(result);
+ alarm = pvAlarm.get();
+ ...
+}
+
+A timeStamp is represented by the following structure
+structure timeStamp + long secondsPartEpoch + int nanoSeconds + int userTag+ +
The Epoch is the posix epoch, i.e. Jan 1, 1970 00:00:00 UTC. Both the +seconds and nanoSeconds are signed integers and thus can be negative. Since the +seconds is kept as a 64 bit integer, it allows for a time much greater than the +present age of the universe. Since the nanoSeconds portion is kept as a 32 bit +integer it is subject to overflow if a value that corresponds to a value that +is greater than a little more than 2 seconds of less that about -2 seconds. The +support code always adjust seconds so that the nanoSecconds part is normlized, +i. e. it has is 0<=nanoSeconds<nanoSecPerSec..
+ +Two header files are provided for manipulating time stamps:
+This provides
+extern int32 milliSecPerSec;
+extern int32 microSecPerSec;
+extern int32 nanoSecPerSec;
+extern int64 posixEpochAtEpicsEpoch;
+
+class TimeStamp {
+public:
+ TimeStamp()
+ :secondsPastEpoch(0), nanoSeconds(0), userTag(0) {}
+ TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 0,int32 userTag = 0);
+ //default constructors and destructor are OK
+ //This class should not be extended
+ void normalize();
+ void fromTime_t(const time_t &);
+ void toTime_t(time_t &) const;
+ int64 getSecondsPastEpoch() const {return secondsPastEpoch;}
+ int64 getEpicsSecondsPastEpoch() const {
+ return secondsPastEpoch - posixEpochAtEpicsEpoch;
+ }
+ int32 getNanoSeconds() const {return nanoSeconds;}
+ int32 getUserTag() const {return userTag;}
+ void setUserTag(int userTag) {this->userTag = userTag;}
+ void put(int64 secondsPastEpoch,int32 nanoSeconds = 0) {
+ this->secondsPastEpoch = secondsPastEpoch;
+ this->nanoSeconds = nanoSeconds;
+ normalize();
+ }
+ void put(int64 milliseconds);
+ void getCurrent();
+ double toSeconds() const ;
+ bool operator==(TimeStamp const &) const;
+ bool operator!=(TimeStamp const &) const;
+ bool operator<=(TimeStamp const &) const;
+ bool operator< (TimeStamp const &) const;
+ bool operator>=(TimeStamp const &) const;
+ bool operator> (TimeStamp const &) const;
+ static double diff(TimeStamp const & a,TimeStamp const & b);
+ TimeStamp & operator+=(int64 seconds);
+ TimeStamp & operator-=(int64 seconds);
+ TimeStamp & operator+=(double seconds);
+ TimeStamp & operator-=(double seconds);
+ int64 getMilliseconds(); // milliseconds since epoch
+ ...
+}
+
+where
+The TimeStamp class provides arithmetic operations on time stamps. The +result is always kept in normalized form, which means that the nano second +portion is 0≤=nano<nanoSecPerSec. Note that it is OK to have timeStamps +for times previous to the epoch.
+ +TimeStamp acts like a primitive. It can be allocated on the stack and the +compiler is free to generate default methods, i.e. copy constructor, assignment +constructor, and destructor.
+ +One use for TimeStamp is to time how long a section of code takes to +execute. This is done as follows:
+TimeStamp startTime; + TimeStamp endTime; + ... + startTime.getCurrent(); + // code to be measured for elapsed time + endTime.getCurrent(); + double time = TimeStamp::diff(endTime,startTime);+ +
class PVTimeStamp {
+public:
+ PVTimeStamp();
+ //default constructors and destructor are OK
+ //This class should not be extended
+ //returns (false,true) if pvField(isNot, is valid timeStamp structure
+ bool attach(PVFieldPtr const &pvField);
+ void detach();
+ bool isAttached();
+ // following throw logic_error if not attached to PVField
+ // a set returns false if field is immutable
+ void get(TimeStamp &) const;
+ bool set(TimeStamp const & timeStamp);
+};
+
+where
+An alarm structure is defined as follows:
+structure alarm + int severity + int status + string message+ +
Note that neither severity or status is defined as an enumerated structure. +The reason is performance, i. e. prevent passing the array of choice strings +everywhere. The file alarm.h provides the choice strings. Thus all code that +needs to know about alarms share the exact same choice strings.
+ +Two header files are provided for manipulating alarms:
+enum AlarmSeverity {
+ noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
+};
+
+enum AlarmStatus {
+ noStatus,deviceStatus,driverStatus,recordStatus,
+ dbStatus,confStatus,undefinedStatus,clientStatus
+};
+
+
+class AlarmSeverityFunc {
+public:
+ static AlarmSeverity getSeverity(int value);
+ static StringArrayPtr getSeverityNames();
+};
+
+class AlarmStatusFunc {
+public:
+ static AlarmStatus getStatus(int value);
+ static StringArrayPtr getStatusNames();
+};
+
+class Alarm {
+public:
+ Alarm();
+ //default constructors and destructor are OK
+ String getMessage();
+ void setMessage(String const &value);
+ AlarmSeverity getSeverity() const;
+ void setSeverity(AlarmSeverity value);
+ AlarmStatus getStatus() const;
+ void setStatus(AlarmStatus value);
+};
+
+Alarm Severity defines the possible alarm severities:
+Alarm Status defines the possible choices for alarm status:
+Alarm has the methods:
+class PVAlarm {
+public:
+ PVAlarm() : pvSeverity(0),pvMessage(0) {}
+ //default constructors and destructor are OK
+ //returns (false,true) if pvField(isNot, is valid enumerated structure
+ //An automatic detach is issued if already attached.
+ bool attach(PVFieldPtr const &pvField);
+ void detach();
+ bool isAttached();
+ // each of the following throws logic_error is not attached to PVField
+ // set returns false if field is immutable
+ void get(Alarm & alarm) const;
+ bool set(Alarm const & alarm);
+};
+
+where
+Control information is represented by the following structure
+structure control + double limitLow + double limitHigh + double minStep+ +
Two header files are provided for manipulating control:
+class Control {
+public:
+ Control();
+ //default constructors and destructor are OK
+ double getLow() const;
+ double getHigh() const;
+ double getMinStep() const;
+ void setLow(double value);
+ void setHigh(double value);
+ void setMinStep(double value);
+};
+
+where
+class PVControl {
+public:
+ PVControl();
+ //default constructors and destructor are OK
+ //returns (false,true) if pvField(isNot, is valid enumerated structure
+ //An automatic detach is issued if already attached.
+ bool attach(PVFieldPtr const &pvField);
+ void detach();
+ bool isAttached();
+ // each of the following throws logic_error is not attached to PVField
+ // set returns false if field is immutable
+ void get(Control &) const;
+ bool set(Control const & control);
+};
+
+where
+Display information is represented by the following structure
+structure display + double limitLow + double limitHigh + string description + string format + string units+ +
Two header files are provided for manipulating display:
+class Display {
+public:
+ Display();
+ //default constructors and destructor are OK
+ double getLow() const;
+ double getHigh() const;
+ void setLow(double value);
+ void setHigh(double value);
+ String getDescription() const;
+ void setDescription(String const &value);
+ String getFormat() const;
+ void setFormat(String const &value);
+ String getUnits() const;
+ void setUnits(String const &value);
+};
+
+where
+class PVDisplay {
+public:
+ PVDisplay()
+ : pvDescription(0),pvFormat(),pvUnits(),pvLow(),pvHigh() {}
+ //default constructors and destructor are OK
+ //An automatic detach is issued if already attached.
+ bool attach(PVFieldPtr const&pvField);
+ void detach();
+ bool isAttached();
+ // each of the following throws logic_error is not attached to PVField
+ // a set returns false if field is immutable
+ void get(Display &) const;
+ bool set(Display const & display);
+};
+
+where
+An enumerated structure is a structure that has fields:
+structure + int index + string[] choices+ +
For enumerated structures a single header file pvEnumerted.h is available
+class PVEnumerated {
+public:
+ PVEnumerated();
+ //default constructors and destructor are OK
+ //This class should not be extended
+ //returns (false,true) if pvField(isNot, is valid enumerated structure
+ //An automatic detach is issued if already attached.
+ bool attach(PVFieldPtr const &pvField);
+ void detach();
+ bool isAttached();
+ // each of the following throws logic_error is not attached to PVField
+ // a set returns false if field is immutable
+ bool setIndex(int32 index);
+ int32 getIndex();
+ String getChoice();
+ bool choicesMutable();
+ StringArrayPtr const & getChoices();
+ int32 getNumberChoices();
+ bool setChoices(StringArray &choices,int32 numberChoices);
+};
+
+where
+Assume that code wants to print two fields from a PVStructure:
+The following code uses introspection to get the desired information.
+void getValueAndTimeStamp(PVStructurePtr pvStructure,StringBuilder buf) {
+ PVFieldPtr valuePV = pvStructure->getSubField(String("value"));
+ if(valuePV.get()==NULL) {
+ buf += "value field not found";
+ return;
+ }
+ buf += "value ";
+ valuePV->toString(&buf);
+ PVFieldPtr timeStampPV = pvStructure->getSubField(String("timeStamp"));
+ if(timeStampPV.get()==NULL) {
+ buf += "timeStamp field not found";
+ return;
+ }
+ buf += " timeStamp ";
+ timeStampPV->toString(&buf);
+}
+
+Example of creating a scalar field.
+PVDataCreatePtr pvDataCreate = getPVDataCreate(); + PVDoublePtr pvValue = static_pointer_cast<PVDouble>( + pvDataCreate->createPVScalar(pvDouble));+ +
Create a structure with a value and an alarm the hard way
+FieldCreatePtr fieldCreate = getFieldCreate(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + FieldConstPtrArray fields; + StringArray names; + fields.resize(3); + names.resize(3); + fields[0] = fieldCreate->createScalar(pvInt); + fields[1] = fieldCreate->createScalar(pvInt); + fields[2] = fieldCreate->createScalar(pvString); + names[0] = "severity"; + names[0] = "status"; + names[0] = "message"; + StructureConstPtr alarmField = + fieldCreate->createStructure(names,fields); + fields.resize(2); + names.resize(2); + fields[0] = fieldCreate->createScalar(pvDouble); + fields[1] = alarmField; + names[0] = "value"; + names[0] = "alarm"; + StructureConstPtr structure = + fieldCreate->createStructure(names,fields); + PVStructurePtr pv = pvDataCreate->createPVStructure(structure);+ +
Create an alarm structure the easy way.
+StandardPVFieldPtr standardPVField = getStandardPVField(); + PVStructurePtr pv = standardPVField->scalar(pvDouble,"alarm");+ +
Create a PVStructure with field name example that has a double value field , +timeStamp, alarm, and display. Do it the easy way.
+StandardPVFieldPtr standardPVField = getStandardPVField(); + PVStructurePtr pvStructure = standardPVField->scalar( + pvDouble,"timeStamp,alarm.display");+ +
Directory factory has code that implements everything described by the files +in directory pv
+ +TypeFunc.cpp implements the functions for the enums defined in +pvIntrospecct.h
+ +FieldCreateFactory.cpp automatically creates a single instance of +FieldCreate and implements getFieldCreate.
+ +PVDataCreateFactory.cpp automatically creates a single instance of +PVDataCreate and implements getPVDataCreate.
+ +PVAuxInfoImpl.cpp implements auxInfo.
+ +Convert.cpp automatically creates a single instance of Convert and +implements getConvert.
+ +Other files implement PVData base classes
+ +This package provides utility code:
+Note that directory testApp/misc has test code for all the classes in misc. +The test code also can be used as examples.
+ +This is adapted from the java.util.BitSet. bitSet.h is:
+class BitSet : public Serializable {
+public:
+ static BitSet::shared_pointer create(uint32 nbits);
+ BitSet();
+ BitSet(uint32 nbits);
+ virtual ~BitSet();
+ void flip(uint32 bitIndex);
+ void set(uint32 bitIndex);
+ void clear(uint32 bitIndex);
+ void set(uint32 bitIndex, bool value);
+ bool get(uint32 bitIndex) const;
+ void clear();
+ int32 nextSetBit(uint32 fromIndex) const;
+ int32 nextClearBit(uint32 fromIndex) const;
+ bool isEmpty() const;
+ uint32 cardinality() const;
+ uint32 size() const;
+ BitSet& operator&=(const BitSet& set);
+ BitSet& operator|=(const BitSet& set);
+ BitSet& operator^=(const BitSet& set);
+ BitSet& operator-=(const BitSet& set);
+ BitSet& operator=(const BitSet &set);
+ void or_and(const BitSet& set1, const BitSet& set2);
+ bool operator==(const BitSet &set) const;
+ bool operator!=(const BitSet &set) const;
+ void toString(StringBuilder buffer);
+ void toString(StringBuilder buffer, int indentLevel) const;
+private:
+};
+
+where
+Clears all of the bits in this bitSet whose corresponding bit is set + in the specified bitSet.
+A ByteBuffer is used to serialize and deserialize primitive data. File +byteBuffer.h is:
+class ByteBuffer {
+public:
+ ByteBuffer(std::size_t size, int byteOrder = EPICS_BYTE_ORDER)
+ ~ByteBuffer();
+ void setEndianess(int byteOrder);
+ const char* getBuffer();
+ void clear();
+ void flip();
+ void rewind();
+ std::size_t getPosition();
+ void setPosition(std::size_t pos);
+ std::size_t getLimit();
+ void setLimit(std::size_t limit);
+ std::size_t getRemaining();
+ std::size_t getSize();
+ template<typename T>
+ void put(T value)
+ template<typename T>
+ void put(std::size_t index, T value);
+ template<typename T>
+ T get()
+ template<typename T>
+ T get(std::size_t index)
+ void put(const char* src, std::size_t src_offset, std::size_t count);
+ void get(char* dest, std::size_t dest_offset, std::size_t count);
+ template<typename T>
+ inline void putArray(T* values, std::size_t count)
+ template<typename T>
+ inline void getArray(T* values, std::size_t count)
+ template<typename T>
+ inline bool reverse();
+ inline void align(std::size_t size)
+ void putBoolean( bool value);
+ void putByte ( int8 value);
+ void putShort ( int16 value);
+ void putInt ( int32 value);
+ void putLong ( int64 value);
+ void putFloat ( float value);
+ void putDouble (double value);
+ void putBoolean(std::size_t index, bool value);
+ void putByte (std::size_t index, int8 value);
+ void putShort (std::size_t index, int16 value);
+ void putInt (std::size_t index, int32 value);
+ void putFloat (std::size_t index, float value);
+ void putDouble (std::size_t index, double value);
+ bool getBoolean();
+ int8 getByte ();
+ int16 getShort ();
+ int32 getInt ();
+ int64 getLong ();
+ float getFloat ();
+ double getDouble ();
+ bool getBoolean(std::size_t index);
+ int8 getByte (std::size_t index);
+ int16 getShort (std::size_t index);
+ int32 getInt (std::size_t index);
+ int64 getLong (std::size_t index);
+ float getFloat (std::size_t index);
+ double getDouble (std::size_t index);
+ const char* getArray();
+ ...
+};
+
+class Destroyable {
+public:
+ POINTER_DEFINITIONS(Destroyable);
+ virtual void destroy() = 0;
+ virtual ~Destroyable() {};
+};
+
+/*
+ * Throwing exceptions w/ file+line# and, when possibly, a stack trace
+ *
+ * THROW_EXCEPTION1( std::bad_alloc );
+ *
+ * THROW_EXCEPTION2( std::logic_error, "my message" );
+ *
+ * THROW_EXCEPTION( mySpecialException("my message", 42, "hello", ...) );
+ *
+ * Catching exceptions
+ *
+ * catch(std::logic_error& e) {
+ * fprintf(stderr, "%s happened\n", e.what());
+ * PRINT_EXCEPTION2(e, stderr);
+ * cout<<SHOW_EXCEPTION(e);
+ * }
+ *
+ * If the exception was not thrown with the above THROW_EXCEPTION*
+ * the nothing will be printed.
+ */
+
+This class provides coordinates activity between threads. One thread can +wait for the event and the other signals the event.
+class Event;
+typedef std::tr1::shared_ptr<Event> EventPtr;
+
+class Event {
+public:
+ POINTER_DEFINITIONS(Event);
+ explicit Event(bool = false);
+ ~Event();
+ void signal();
+ bool wait (); /* blocks until full */
+ bool wait ( double timeOut ); /* false if empty at time out */
+ bool tryWait (); /* false if empty */
+private:
+ epicsEventId id;
+};
+
+where
+An Executor is a thread that can execute commands. The user can request that +a single command be executed.
+class Command;
+class Executor;
+typedef std::tr1::shared_ptr<Command> CommandPtr;
+typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
+
+class Command {
+public:
+ POINTER_DEFINITIONS(Command);
+ virtual ~Command(){}
+ virtual void command() = 0;
+private:
+ CommandPtr next;
+ friend class Executor;
+};
+
+class Executor : public Runnable{
+public:
+ POINTER_DEFINITIONS(Executor);
+ Executor(String threadName,ThreadPriority priority);
+ ~Executor();
+ void execute(CommandPtr const &node);
+ virtual void run();
+ ...
+};
+
+Command is a class that must be implemented by the code that calls execute. +It contains the single virtual method command, which is the command to +execute.
+ +Executor has the methods:
+typedef epicsMutex Mutex;
+
+class Lock : private NoDefaultMethods {
+public:
+ explicit Lock(Mutex &pm);
+ ~Lock();
+ void lock();
+ void unlock();
+ bool tryLock();
+ bool ownsLock() ;
+ ...
+};
+
+Lock is as easy to use as Java synchronize. To protect some object just +create a Mutex for the object and then in any method to be synchronized just +have code like:
+class SomeClass {
+private
+ Mutex mutex;
+ ...
+public
+ SomeClass() : mutex(Mutex()) {}
+ ...
+ void method()
+ {
+ Lock xx(mutex);
+ ...
+ }
+
+The method will take the lock when xx is created and release the lock when +the current code block completes.
+ +Another example of Lock is initialization code that must initialize only +once. This can be implemented as follows:
+ static void init(void) {
+ static Mutex mutex;
+ Lock xx(mutex);
+ if(alreadyInitialized) return;
+ // initialization
+ }
+
+A messageQueue is for use by code that wants to handle messages without +blocking higher priority threads.
+class MessageNode;
+class MessageQueue;
+typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
+typedef std::vector<MessageNodePtr> MessageNodePtrArray;
+typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
+
+class MessageNode {
+public:
+ String getMessage() const;
+ MessageType getMessageType() const;
+ void setMessageNull();
+};
+
+class MessageQueue : public Queue<MessageNode> {
+public:
+ POINTER_DEFINITIONS(MessageQueue);
+ static MessageQueuePtr create(int size);
+ MessageQueue(MessageNodePtrArray &nodeArray);
+ virtual ~MessageQueue();
+ MessageNodePtr &get();
+ // must call release before next get
+ void release();
+ // return (false,true) if message (was not, was) put into queue
+ bool put(String message,MessageType messageType,bool replaceLast);
+ bool isEmpty() ;
+ bool isFull() ;
+ int getClearOverrun();
+ ...
+};
+
+A messageNode is a class with two public data members:
+A messageQueue is an interface with public methods:
+Look at miscTest/testMessageQueue.cpp for an example.
+ +If a class privately extends this class then the compiler can not create any +of the following: default constructor, default copy constructror, or default +assignment contructor.
+/* This is based on Item 6 of
+ * Effective C++, Third Edition, Scott Meyers
+ */
+ class NoDefaultMethods {
+ protected:
+ // allow by derived objects
+ NoDefaultMethods(){};
+ ~NoDefaultMethods(){}
+ private:
+ // do not implment
+ NoDefaultMethods(const NoDefaultMethods&);
+ NoDefaultMethods & operator=(const NoDefaultMethods &);
+ };
+
+This provides a queue which has an immutable capacity. When the queue is +full the user code is expected to keep using the current element until a new +free element becomes avalable.
+template <typename T>
+class Queue
+{
+public:
+ POINTER_DEFINITIONS(Queue);
+ typedef std::tr1::shared_ptr<T> queueElementPtr;
+ typedef std::vector<queueElementPtr> queueElementPtrArray;
+ Queue(queueElementPtrArray &);
+ virtual ~Queue();
+ void clear();
+ int capacity();
+ int getNumberFree();
+ int getNumberUsed();
+ queueElementPtr & getFree();
+ void setUsed(queueElementPtr &element);
+ queueElementPtr & getUsed();
+ void releaseUsed(queueElementPtr &element);
+ ...
+};
+
+testApp/misc/testQueue.cpp provides an example of how to define a queue.
+ +The queue methods are:
+A queue is created as follows:
+ class MyClass;
+ typedef MyQueueElement<MyClass> MyElement;
+ typedef MyQueue<MyClass> MyQueue;
+ int numElement = 5;
+ ...
+ MyClass *array[numElements];
+ for(int i=0; i<numElements; i++) {
+ array[i] = new MyClass();
+ }
+ MyQueue *queue = new MyQueue(array,numElements);
+
+A producer calls getFree and setUsed via code like the following:
+ MyClass *getFree() {
+ MyElement *element = queue->getFree();
+ if(element==0) return 0;
+ return element->getObject();
+ }
+
+A consumer calls getUsed and releaseUsed via code like the following:
+ while(true) {
+ MyElement *element = queue->getUsed();
+ if(element==0) break;
+ MyClass *myClass = element->getObject();
+ // do something with myClass
+ queue->releaseUsed(element);
+ }
+
+A PVField extends Requester. Requester is present so that when database +errors are found there is someplace to send a message.
+enum MessageType {
+ infoMessage,warningMessage,errorMessage,fatalErrorMessage
+};
+
+extern String getMessageTypeName(MessageType messageType);
+extern const size_t messageTypeCount;
+class Requester {
+public:
+ POINTER_DEFINITIONS(Requester);
+ virtual ~Requester(){}
+ virtual String getRequesterName() = 0;
+ virtual void message(String const & message,MessageType messageType) = 0;
+};
+
+where
+ class SerializableControl;
+ class DeserializableControl;
+ class Serializable;
+ class BitSetSerializable;
+ class SerializableArray;
+ class BitSet;
+ class Field;
+
+ class SerializableControl {
+ public:
+ virtual ~SerializableControl(){}
+ virtual void flushSerializeBuffer() =0;
+ virtual void ensureBuffer(std::size_t size) =0;
+ virtual void alignBuffer(std::size_t alignment) =0;
+ virtual void cachedSerialize(
+ std::tr1::shared_ptr<const Field> const & field,
+ ByteBuffer* buffer) = 0;
+ };
+
+ class DeserializableControl {
+ public:
+ virtual ~DeserializableControl(){}
+ virtual void ensureData(std::size_t size) =0;
+ virtual void alignData(std::size_t alignment) =0;
+ virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer) = 0;
+ };
+
+ class Serializable {
+ public:
+ virtual ~Serializable(){}
+ virtual void serialize(ByteBuffer *buffer,
+ SerializableControl *flusher) const = 0;
+ virtual void deserialize(ByteBuffer *buffer,
+ DeserializableControl *flusher) = 0;
+ };
+
+ class BitSetSerializable {
+ public:
+ virtual ~BitSetSerializable(){}
+ virtual void serialize(ByteBuffer *buffer,
+ SerializableControl *flusher,BitSet *bitSet) const = 0;
+ virtual void deserialize(ByteBuffer *buffer,
+ DeserializableControl *flusher,BitSet *bitSet) = 0;
+ };
+
+
+ class SerializableArray : virtual public Serializable {
+ public:
+ virtual ~SerializableArray(){}
+ virtual void serialize(ByteBuffer *buffer,
+ SerializableControl *flusher, std::size_t offset, std::size_t count) const = 0;
+ };
+
+This is a helper class for serialization, which is required for sending and +receiving pvData over the nerwork.
+class SerializeHelper : public NoDefaultMethods {
+public:
+ static void writeSize(int s, ByteBuffer* buffer,
+ SerializableControl* flusher);
+ static int readSize(ByteBuffer* buffer,
+ DeserializableControl* control);
+ static void serializeString(const String& value,
+ ByteBuffer* buffer,SerializableControl* flusher);
+ static void serializeSubstring(const String& value, int offset,
+ int count, ByteBuffer* buffer,
+ SerializableControl* flusher);
+ static String deserializeString(ByteBuffer* buffer,
+ DeserializableControl* control);
+ ...
+};
+
+where
+#define POINTER_DEFINITIONS(clazz) \ + typedef std::tr1::shared_ptr<clazz> shared_pointer; \ + typedef std::tr1::shared_ptr<const clazz> const_shared_pointer; \ + typedef std::tr1::weak_ptr<clazz> weak_pointer; \ + typedef std::tr1::weak_ptr<const clazz> const_weak_pointer;+ +
Status provides a way to pass status back to client code:
+class Status : public epics::pvData::Serializable {
+ public:
+ enum StatusType {
+ /** Operation completed successfully. */
+ STATUSTYPE_OK,
+ /** Operation completed successfully, but there is a warning message. */
+ STATUSTYPE_WARNING,
+ /** Operation failed due to an error. */
+ STATUSTYPE_ERROR,
+ /** Operation failed due to an unexpected error. */
+ STATUSTYPE_FATAL
+ };
+ static const char* StatusTypeName[];
+ static Status OK;
+ Status();
+ Status(StatusType type, epics::pvData::String const & message);
+ Status(StatusType type, epics::pvData::String const & message, epics::pvData::String stackDump);
+ ~Status()
+ StatusType getType() const;
+ String getMessage() const;
+ String getStackDump() const;
+ bool isOK() const;
+ bool isSuccess() const;
+ String toString() const;
+ void toString(StringBuilder buffer, int indentLevel = 0) const;
+ void serialize(ByteBuffer *buffer, SerializableControl *flusher) const;
+ void serialize(ByteBuffer *buffer, SerializableControl *flusher) const;
+};
+
+The Status methods are:
+The StatusCreate methods are:
+enum ThreadPriority {
+ lowestPriority,
+ lowerPriority,
+ lowPriority,
+ middlePriority,
+ highPriority,
+ higherPriority,
+ highestPriority
+};
+
+class Runnable {
+public:
+ virtual void run() = 0;
+};
+
+class Thread;
+
+class Thread : public epicsThread, private NoDefaultMethods {
+public:
+ Thread(
+ String name,
+ ThreadPriority priority,
+ Runnable *runnableReady,
+ epicsThreadStackSizeClass stkcls=epicsThreadStackSmall);
+ ~Thread();
+ ...
+};
+
+Runnable must be implement by code that wants to be run via a thread. It has +one virtual method: run. Run is the code that is run as a thread. When run +compeletes it can not be restarted. If code wants to delete a thread then it +MUST arrange that the run returns before the thread can be deleted. An +exception is thrown if run remains active when delete is called.
+ +Thread has the methods:
+delete pthread;+
TimeFunction is a facility that measures the average number of seconds a +function call requires. When timeCall is called, it calls function in a loop. +It starts with a loop of one iteration. If the total elapsed time is less then +.1 seconds it increases the number of iterrations by a factor of 10. It keeps +repeating until the elapsed time is greater than .1 seconds. It returns the +average number of seconds per call.
+class TimeFunctionRequester;
+class TimeFunction;
+typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
+typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
+
+class TimeFunctionRequester {
+public:
+ POINTER_DEFINITIONS(TimeFunctionRequester);
+ virtual ~TimeFunctionRequester(){}
+ virtual void function() = 0;
+};
+
+
+class TimeFunction {
+public:
+ POINTER_DEFINITIONS(TimeFunction);
+ TimeFunction(TimeFunctionRequesterPtr const & requester);
+ ~TimeFunction();
+ double timeCall();
+ ...
+};
+
+TimeFunctionRequester must be implemented by code that wants to time how +long a function takes. It has the single method:
+TimeFunction has the methods:
+This provides a general purpose timer. It allows a user callback to be +called after a delay or periodically.
+class TimerCallback;
+class Timer;
+typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
+typedef std::tr1::shared_ptr<Timer> TimerPtr;
+
+
+class TimerCallback {
+public:
+ POINTER_DEFINITIONS(TimerCallback);
+ TimerCallback();
+ virtual ~TimerCallback(){}
+ virtual void callback() = 0;
+ virtual void timerStopped() = 0;
+};
+
+class Timer : private Runnable {
+public:
+ POINTER_DEFINITIONS(Timer);
+ Timer(String threadName, ThreadPriority priority);
+ virtual ~Timer();
+ virtual void run();
+ void scheduleAfterDelay(
+ TimerCallbackPtr const &timerCallback,
+ double delay);
+ void schedulePeriodic(
+ TimerCallbackPtr const &timerCallback,
+ double delay,
+ double period));
+ void cancel(TimerCallbackPtr const &timerCallback);
+ bool isScheduled(TimerCallbackPtr const &timerCallback);
+ void toString(StringBuilder builder);
+ ...
+};
+
+TimerCallback must be implemented by the user. It has the following methods: +
+In order to schedule a callback client code must allocate a TimerNode It can +be used to schedule multiple callbacks. It has the methods:
+delete timerNode;+
Timer has the methods:
+The following is also provided:
+class BitSetUtil : private NoDefaultMethods {
+public:
+ static bool compress(BitSet *bitSet,PVStructure *pvStructure);
+};
+
+This provides functions that operate on a BitSet for a PVStructure. It +currently has only one method:
+