From fd36bd47ad0291d0abf8677220a351aef6a47485 Mon Sep 17 00:00:00 2001
From: Marty Kraimer TODOEPICS pvDataCPP
+2010.12.03
Overview
-2010.12.02
@@ -137,1325 +137,159 @@ appear under pvDataApp:
This section describes a meta language for describing pvData. Currently +there are no plans for any software, e.g. a parser, for the meta language. It +is only meant for documentation.
-All include and definition files in project pvDataCPP appear in namespace: -
-namespace epics { namespace pvData {
- // ...
-}}
+PVData supports structured data. All data appears as a top level +structure. A structure has an ordered set of fields where each field has a +fieldDef defined as follows:
+type fieldName = value // comment-
Directory misc has an include file pvTypes.h:
-typedef signed char int8; -typedef short int16; -typedef int int32; -typedef long long int64; -typedef unsigned int uint32; -typedef unsigned long long uint64; +- -where = value is optional and +// indicates the the rest of the +line is a comment.
-typedef std::string String; -typedef std::string * StringBuilder; -typedef String* StringArray;
The integer typedefs provide the definitions for various sizes of integer -values. The relationship between these definitions and the ScalarType -description is:
+type is one of the following:
It is hoped that all modern C++ compilers will properly handle the integer -typedefs but if not than there is a good chance that it can be supported by -changes to pvInterspect.h.
- -std::string is used to implement pvString. This works because std::string -implement COW (Copy On Write) semantics. Thus once created a String can be -treated like an immutable object, which is what pvData require.
- -The remaining definitions are:
-File pvInterspect.h, which is described in the next section has the -typedefs:
-typedef Field const * FieldConstPtr; -typedef FieldConstPtr * FieldConstPtrArray; -typedef Scalar const * ScalarConstPtr; -typedef ScalarArray const * ScalarArrayConstPtr; -typedef Structure const * StructureConstPtr; -typedef StructureArray const * StructureArrayConstPtr;- -
These are definitions for introspection objects. All introspecton objects -are immutable and always accessed via pointers.
- -File pvData.h, which is also described in the next section has the -typedefs:
-typedef std::map<String,PVScalar * > PVScalarMap; -typedef PVScalarMap::const_iterator PVScalarMapIter; -typedef PVStructure * PVStructurePtr; -typedef PVStructurePtr* PVStructurePtrArray; -typedef PVField* PVFieldPtr; -typedef PVFieldPtr * PVFieldPtrArray; -typedef bool * BooleanArray; -typedef int8 * ByteArray; -typedef int16 * ShortArray; -typedef int32 * IntArray; -typedef int64 * LongArray; -typedef float * FloatArray; -typedef double * DoubleArray; -typedef String * StringArray;- -
where
-Any class that does not allow the compiler to generate default methods can -privately extend the following class which is defined in file -noDefaultMethods.h:
-class NoDefaultMethods {
-protected:
- // allow by derived objects
- NoDefaultMethods(){};
- ~NoDefaultMethods(){}
-private:
- // do not implment
- NoDefaultMethods(const NoDefaultMethods&);
- NoDefaultMethods & operator=(const NoDefaultMethods &);
-};
-
-Introspection objects are meant to be shared. The constructors and -destructors are all private so that an introspection object can only be -created via a call to one of the FieldCreate methods described below. The -introspection implementation, together with AbstractPVField keeps reference -counts and automatically deletes objects when the reference count goes to 0. -Code that uses introspection objects always accesses introspection objects -via pointers never via references or direct access to the object. When a -PVData data object is destroyed then pointers to the introspection objects -associated with the data object are no longer valid.
- -All PVData data objects must publically extend AbstractPVField, which does -not allow default methods but does have a virtual destructor. It is expected -that each data object is "owned" by some entity. For example a pvIOC (not -implemented) database will own all records and thus all PVData data objects -in the database. It is the ONLY entity that will create and destroy the data -objects. All other code only receives pointers to the data objects. Before a -record is deleted any code that is connected to a record is notified before -the record is deleted. After deletion all pointers to data in the record are -invalid. Similarly pvAccess creates and destroys PVData objects and notifies -clients before destroying PVData data objects.
- -If a class is pure data, e. g. TimeStamp, then it acts list like a -primitive object.
- -Other clases privately extend NoDefaultClasses and are not normally meant -to be extended. Thus they can only be created via "new" and must be destroyed -via "delete". These classes normally implement the static method:
-static ConstructDestructCallback *getConstructDestructCallback();- -
This provides access to how many objects have been constructed and -destructed. This can be used to monitor memory usage.
- --
This package provides utility code:
-This is adapted from the java.util.BitSet. bitSet.h is:
-class BitSet /*: public Serializable*/ {
-public:
- 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;
- 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(int size = 32, int byteOrder = EPICS_BYTE_ORDER);
- ~ByteBuffer();
- ByteBuffer* clear();
- ByteBuffer* flip();
- ByteBuffer* rewind();
- bool getBoolean();
- int8 getByte();
- int16 getShort();
- int32 getInt();
- int64 getLong();
- float getFloat();
- double getDouble();
- void get(char* dst, int offset, int count);
- ByteBuffer* put(const char* src, int offset, int count);
- ByteBuffer* putBoolean(bool value);
- ByteBuffer* putByte(int8 value);
- ByteBuffer* putShort(int16 value);
- ByteBuffer* putInt(int32 value);
- ByteBuffer* putLong(int64 value);
- ByteBuffer* putFloat(float value);
- ByteBuffer* putDouble(double value);
- inline int getSize() const;
- inline int getArrayOffset() const;
- inline int getPosition() const;
- inline int getLimit() const;
- inline int getRemaining() const;
- inline int getByteOrder() const;
- inline const char* getArray() const;
- // TODO must define arrays
-private:
-};
-
-x
- -This class provides coordinates activity between threads. One thread can -wait for the event and the other signals the event.
-class Event : private NoDefaultMethods {
-public:
- Event(bool full);
- ~Event();
- static ConstructDestructCallback *getConstructDestructCallback();
- 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
-File epicsException.h describes:
-class BaseException : public std::exception {
-public:
- BaseException(const char* message, const char* file,
- int line, std::exception* cause = 0);
- virtual ~BaseException();
- virtual const char* what();
- void toString(std::string& str, unsigned int depth = 0);
- static inline void getStackTrace(
- std::string* trace, unsigned int skip_frames = 0, unsigned int max_frames = 63)
-private:
- // ...
-}
-
-x
- -An Executor is a thread that can execute commands. The user can request -that a single command be executed.
-class ExecutorNode;
-
-class Command {
-public:
- virtual void command() = 0;
-};
-
-class Executor : private NoDefaultMethods {
-public:
- Executor(String threadName,ThreadPriority priority);
- ~Executor();
- static ConstructDestructCallback *getConstructDestructCallback();
- ExecutorNode * createNode(Command *command);
- void execute(ExecutorNode *node);
-private:
- class ExecutorPvt *pImpl;
-};
-
-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:
-LinkedList implements a double linked list that requires a user to -allocate the nodes. It is more efficent that std::list. linkedList.h is -template that is both a complete description and definition. It uses -linkedListVoid for method definitions. linkedListVoid is not\ meant for use -except via linkedList. Note, however, that linkedListVoid does have both a -node and a list static method getConstructDestructCallback, which allows -access to how many nodes and lists have been created and destroyed.
- -A node can only be on one list at a time but can be put, at different -times, on different lists as long as they all hold the same type of objects. -An exception is thrown if an attempt is made to put a node on a list if the -node is already on a list.
-template <typename T>
-class LinkedList;
-
-template <typename T>
-class LinkedListNode : private LinkedListVoidNode {
-public:
- LinkedListNode(T *object);
- ~LinkedListNode();
- T *getObject();
- bool isOnList();
-};
-template <typename T>
-class LinkedList : private LinkedListVoid {
-public:
- LinkedList();
- ~LinkedList();
- int getLength();
- void addTail(LinkedListNode<T> *node);
- void addHead(LinkedListNode<T> *node);
- void insertAfter(LinkedListNode<T> *node,
- LinkedListNode<T> *addNode);
- void insertBefore(LinkedListNode<T> *node,
- LinkedListNode<T> *addNode);
- LinkedListNode<T> *removeTail();
- LinkedListNode<T> *removeHead();
- void remove(LinkedListNode<T> *listNode);
- void remove(T *object);
- LinkedListNode<T> *getHead();
- LinkedListNode<T> *getTail();
- LinkedListNode<T> *getNext(LinkedListNode<T> *node);
- LinkedListNode<T> *getPrev(LinkedListNode<T> *node;
- bool isEmpty();
- bool contains(T *object);
-};
-
-LinkedListNode has the methods:
-LinkedList has the methods:
-lock.h contains:
-class Mutex {
-public:
- Mutex();
- ~Mutex();
- void lock();
- void unlock();
-private:
-};
-
-
-class Lock : private NoDefaultMethods {
-public:
- explicit Lock(Mutex *pm);
- ~Lock();
-private:
-};
-
-This is a complete description and definition of lock and mutex. These -make it easy to have a lock that 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 = Mutex();
- Lock xx(&mutex);
- if(alreadyInitialized) return;
- // initialization
- }
-
-NOT IMPLEMENTED- -
This is for use by code that wants to handle messages without blocking -higher priority threads.
- -A messageNode is a class with two public data members:
-A messageQueue is an interface with methods:
-MessageQueueFactory provides the public method:
-An example is:
- private ExecutorNode executorNode;
- ...
- executorNode = executor.createNode(this);
- ...
-
- public void message(final String message, MessageType messageType) {
- boolean execute = false;
- synchronized(messageQueue) {
- if(messageQueue.isEmpty()) execute = true;
- if(messageQueue.isFull()) {
- messageQueue.replaceLast(message, messageType);
- } else {
- messageQueue.put(message, messageType);
- }
- }
- if(syncExec) {
- iocExecutor.execute(executorNode);
- }
- }
- ...
- public run() { // handle messages
- while(true) {
- String message = null;
- int numOverrun = 0;
- synchronized(messageQueue) {
- MessageNode messageNode = messageQueue.get();
- numOverrun = messageQueue.getClearOverrun();
- if(messageNode==null && numOverrun==0) break;
- message = messageNode.message;
- }
- if(numOverrun>0) {
- System.out.printf(String.format("%n%d missed messages&n", numOverrun));
- }
- if(message!=null) {
- System.out.printf(String.format("%s%n",message));
- }
- }
- }
-
-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 typedefs for integers and String.
-typedef signed char int8; -typedef short int16; -typedef int int32; -typedef long long int64; -typedef unsigned int uint32; -typedef unsigned long long uint64; - -typedef std::string String; -typedef std::string * StringBuilder; -typedef String* StringArray;- -
where
-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 StringArray messageTypeName;
-
-class Requester {
-public:
- virtual String getRequesterName() = 0;
- virtual void message(String message,MessageType messageType) = 0;
-};
-
-where
-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);
-private:
-};
-
-class SerializableControl {
-public:
- virtual void flushSerializeBuffer() =0;
- virtual void ensureBuffer(int size) =0;
-};
-class DeserializableControl {
-
-public:
- virtual void ensureData(int size) =0;
-};
-class Serializable {
-public:
- virtual void serialize(ByteBuffer *buffer,
- SerializableControl *flusher) = 0;
- virtual void deserialize(ByteBuffer *buffer,
- DeserializableControl *flusher) = 0;
-};
-class BitSetSerializable {
-public:
- virtual void serialize(ByteBuffer *buffer,
- SerializableControl *flusher,BitSet *bitSet) = 0;
- virtual void deserialize(ByteBuffer *buffer,
- DeserializableControl *flusher,BitSet *bitSet) = 0;
-};
-class SerializableArray : public Serializable {
-public:
- virtual void serialize(ByteBuffer *buffer,
- SerializableControl *flusher, int offset, int count) = 0;
-};
-
-where
-The following interfaces are called by pvAccess for transporting data over -the network. The abstract and base classes ensure that these methods are -properly implemented.
-x- -
x
- -This is a facility that allows a class to report how many objects of that -class have been created and destroyed. This can help find memory leaks.
-typedef int64 (*getTotal)();
-
-class ConstructDestructCallback : private NoDefaultMethods {
-public:
- ConstructDestructCallback(
- String name,
- getTotal construct,
- getTotal destruct,
- getTotal reference);
- String getConstructName();
- int64 getTotalConstruct();
- int64 getTotalDestruct();
- int64 getTotalReferenceCount();
-private:
- ~ConstructDestructCallback();
- String name;
- getTotal construct;
- getTotal destruct;
- getTotal reference;
-};
-
-class ShowConstructDestruct : private NoDefaultMethods {
-public:
- static void constuctDestructTotals(FILE *fd);
- static void registerCallback(ConstructDestructCallback *callback);
-private:
- ShowConstructDestruct();
- friend ShowConstructDestruct* getShowConstructDestruct();
-};
-
-extern ShowConstructDestruct* getShowConstructDestruct();
-
-ConstructDestructCallback is implemented by a class that keeps track of -how many instances of the class has been created and how many destroyed. The -clas must implement this class and register it with ShowConstructDestruct. To -see an example of how this is implemented look at misc/thread.cpp.
- -Classes that implement this class also include a static method that makes -ConstructDestructCallback available to code that wants look at the memory -usage of a particular class.
- -ShowConstructDestruct is the class that reports the memory uasge of all -registered classes. It can be called as folows:
-getShowConstructDestruct()->constuctDestructTotals(fd);- -
Status provides a way to pass status back to client code. It is new and -not currently used by pvData but may be in the future. It is used by code -that uses pvData.
-NOT IMPLEMENTED- -
The Status methods are:
-The StatusCreate methods are:
-enum ThreadPriority {
- lowestPriority,
- lowerPriority,
- lowPriority,
- middlePriority,
- highPriority,
- higherPriority,
- highestPriority
-};
-
-class ThreadPriorityFunc {
-public:
- static unsigned int const * const getEpicsPriorities();
- static int getEpicsPriority(ThreadPriority threadPriority);
-};
-
-class Runnable {
-public:
- virtual void run() = 0;
-};
-
-class Thread;
-
-class Thread : private NoDefaultMethods {
-public:
- Thread(String name,ThreadPriority priority,Runnable *runnableReady);
- ~Thread();
- static ConstructDestructCallback *getConstructDestructCallback();
- String getName();
- ThreadPriority getPriority();
- static void showThreads(StringBuilder buf);
- static void sleep(double seconds);
-private:
-};
-
-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;+
structure fieldName + fieldDef + ... ++ or +
structureName fieldName = {values}
+
+ For structure fieldName each
+ fieldDef must have a unique
+ fieldName within the structure For structureName fieldName the structureName must be the fieldName of a previously defined
+ top level structure structure[] structureName fieldName = {values}
+
+ where structureName must be
+ fieldName of a previously
+ defined top level structure
+ Thus a structure array is an array where each element is a structure
+ but all elements have the same introspection interface. 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 {
-public:
- virtual void function() = 0;
-};
-
-class TimeFunction : private NoDefaultMethods {
-public:
- TimeFunction(TimeFunctionRequester *requester);
- ~TimeFunction();
- double timeCall();
-private:
- TimeFunctionRequester *requester;
-};
-
-TimeFunctionRequester must be implemented by code that wants to time how -long a function takes. It has the single method:
+Each field can optionally have data values assigned to it. The definition +of the data values depends on the type. For scalars the data value is +whatever is valid for the type.
TimeFunction has the methods:
-For arrays the syntax is:
+= [value,...,value]-
where each value is a valid +scalar data value depending on the type. Thus it is a comma separated set of +values enclosed in [] White space +is permitted surrounding each comma.
-This provides a general purpose timer. It allows a user callback to be -called after a delay or periodically.
-class TimerCallback {
-public:
- virtual void callback() = 0;
- virtual void timerStopped() = 0;
-};
+For a structure the syntax is:
+ { fieldValue,...,fieldValue }
-class TimerNode : private NoDefaultMethods {
-public:
- TimerNode(TimerCallback *timerCallback);
- ~TimerNode();
- static ConstructDestructCallback *getConstructDestructCallback();
- void cancel();
- bool isScheduled();
-private:
-};
+where each fieldValueY is a
+valid field value depending on the type. Thus it is a comma separated set of
+values enclosed in {} White space
+is permitted surrounding each comma.
-class Timer : private NoDefaultMethods {
-public:
- Timer(String threadName, ThreadPriority priority);
- ~Timer();
- static ConstructDestructCallback *getConstructDestructCallback();
- void scheduleAfterDelay(TimerNode *timerNode,double delay);
- void schedulePeriodic(TimerNode *timerNode,double delay,double period);
-private:
-};
+A structureArray was the form:
+ [ {structureValue},...,{structureValue}]
-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;-
Define the following top level structure:
+structure timeStamp + long secondsPastEpoch + int nanoSeconds-
Timer has the methods:
-Then the following can be defined
+structure scalarDoubleExample + double value = 1.0 + timeStamp timeStamp -TimeStamp
+scalar arrayDoubleExample + double[] value = {1.0,2.0} + timeStamp timeStamp -TimeStamp is a class for accessing a timeStamp that consists of the number -of seconds since the epoch and the number of nanoseconds within the current -second. The epoch is the posix epoch which is Jan 1, 1970 at 00:00:00 -Universal Time Coordinated.
+structure point + double x + double y -The seconds since the epoch is kept as an int64 and the nano seconds is -kept as in int32.
+structure lineExample + point begin = {0,0} + point end = {10,10} -The implementation of some of the methods (getCurrent, fromTime_t, and -toTime_t) use epicsTime from EPICS base and will thus have a problem when the -epics secPastEpoch overflows, which will happen in about 2126.
- -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 measure time - endTime.getCurrent(); - double time = TimeStamp::diff(endTime,startTime);- -TimeStamp is described as:
-extern int32 milliSecPerSec; -extern int32 microSecPerSec; -extern int32 nanoSecPerSec; -extern int64 posixEpochAtEpicsEpoch; - -class TimeStamp { -public: - TimeStamp(); - TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 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; - int64 getEpicsSecondsPastEpoch() const; - int32 getNanoSeconds() const; - void put(int64 secondsPastEpoch,int32 nanoSeconds = 0); - 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 -private: -};- -TimeStamp has the methods:
-
TimeStamp current; - current.getCurrent(); - time_t tt; - current.toTime_t(tt); - struct tm ctm; - memcpy(&ctm,localtime(&tt),sizeof(struct tm)); - fprintf(auxfd, - "%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d nanoSeconds isDst %s\n", - ctm.tm_year+1900,ctm.tm_mon + 1,ctm.tm_mday, - ctm.tm_hour,ctm.tm_min,ctm.tm_sec, - current.getNanoSeconds(), - (ctm.tm_isdst==0) ? "false" : "true");-
prints something like:
-2010.12.01 07:39:48 807264972 nanoSeconds isDst false-
This provides a queue which has an immutable capacity, which is specified -when the queue is created. When the queue is full the user code is expected -to keep using the current el;ement until a new free element becomes avalable. -This is used by pvData.monitor.
-NOT IMPLEMENTED- -
A queueCreate instance is created via a call like the following:
-QueueCreate<MyObject> queueCreate = new QueueCreate<MyObject>();- -
Once a queueCreate is available a queue instance is created via code like -the following:
-Queue<MyObject> queue create(MyObject[] myObjects) {
- QueueElement<MyObject>[] queueElements = new QueueElement[length];
- for(int i=0; i<length; i++) {
- QueueElement<MonitorElement> queueElement =
- queueCreate.createQueueElement(myObjects[i);
- queueElements[i] = queueElement;
- }
- return queueCreate.create(queueElements);
-}
-
-The queue methods are:
-A producer calls getFree and setUsed via code like the following:
- MyObject getFree() {
- QueueElement<MyObject> queueElement = queue.getFree();
- if(queueElement==null) return null;
- return queueElement.getObject();
- }
-
-A consumer calls getUsed and releaseUsed via code like the following:
- while(true) {
- QueueElement<MyObject> queueElement = queue.getUsed();
- if(queueElement==null) break;
- MyObject myObject = queueElement.getObject();
- // do something with myObject
- queue.releaseUsed(queueElement);
- }
+structure structureArrayExample
+ stucture[] point points =
+ [
+ {0,0},
+ {10,10}
+ ]
All include and definition files in project pvDataCPP appear in namespace: +
+namespace epics { namespace pvData {
+ // ...
+}}
+
+Directory misc has an include file pvTypes.h:
+typedef signed char int8; +typedef short int16; +typedef int int32; +typedef long long int64; +typedef unsigned int uint32; +typedef unsigned long long uint64; + +typedef std::string String; +typedef std::string * StringBuilder; +typedef String* StringArray;+ +
The integer typedefs provide the definitions for various sizes of integer +values. The relationship between these definitions and the ScalarType +description is:
+It is hoped that all modern C++ compilers will properly handle the integer +typedefs but if not than there is a good chance that it can be supported by +changes to pvInterspect.h.
+ +std::string is used to implement pvString. This works because std::string +implement COW (Copy On Write) semantics. Thus once created a String can be +treated like an immutable object, which is what pvData require.
+ +The remaining definitions are:
+File pvInterspect.h, which is described in the next section has the +typedefs:
+typedef Field const * FieldConstPtr; +typedef FieldConstPtr * FieldConstPtrArray; +typedef Scalar const * ScalarConstPtr; +typedef ScalarArray const * ScalarArrayConstPtr; +typedef Structure const * StructureConstPtr; +typedef StructureArray const * StructureArrayConstPtr;+ +
These are definitions for introspection objects. All introspecton objects +are immutable and always accessed via pointers.
+ +File pvData.h, which is also described in the next section has the +typedefs:
+typedef std::map<String,PVScalar * > PVScalarMap; +typedef PVScalarMap::const_iterator PVScalarMapIter; +typedef PVStructure * PVStructurePtr; +typedef PVStructurePtr* PVStructurePtrArray; +typedef PVField* PVFieldPtr; +typedef PVFieldPtr * PVFieldPtrArray; +typedef bool * BooleanArray; +typedef int8 * ByteArray; +typedef int16 * ShortArray; +typedef int32 * IntArray; +typedef int64 * LongArray; +typedef float * FloatArray; +typedef double * DoubleArray; +typedef String * StringArray;+ +
where
+Any class that does not allow the compiler to generate default methods can +privately extend the following class which is defined in file +noDefaultMethods.h:
+class NoDefaultMethods {
+protected:
+ // allow by derived objects
+ NoDefaultMethods(){};
+ ~NoDefaultMethods(){}
+private:
+ // do not implment
+ NoDefaultMethods(const NoDefaultMethods&);
+ NoDefaultMethods & operator=(const NoDefaultMethods &);
+};
+
+Introspection objects are meant to be shared. The constructors and +destructors are all private so that an introspection object can only be +created via a call to one of the FieldCreate methods described below. The +introspection implementation, together with AbstractPVField keeps reference +counts and automatically deletes objects when the reference count goes to 0. +Code that uses introspection objects always accesses introspection objects +via pointers never via references or direct access to the object. When a +PVData data object is destroyed then pointers to the introspection objects +associated with the data object are no longer valid.
+ +All PVData data objects must publically extend AbstractPVField, which does +not allow default methods but does have a virtual destructor. It is expected +that each data object is "owned" by some entity. For example a pvIOC (not +implemented) database will own all records and thus all PVData data objects +in the database. It is the ONLY entity that will create and destroy the data +objects. All other code only receives pointers to the data objects. Before a +record is deleted any code that is connected to a record is notified before +the record is deleted. After deletion all pointers to data in the record are +invalid. Similarly pvAccess creates and destroys PVData objects and notifies +clients before destroying PVData data objects.
+ +If a class is pure data, e. g. TimeStamp, then it acts list like a +primitive object.
+ +Other clases privately extend NoDefaultClasses and are not normally meant +to be extended. Thus they can only be created via "new" and must be destroyed +via "delete". These classes normally implement the static method:
+static ConstructDestructCallback *getConstructDestructCallback();+ +
This provides access to how many objects have been constructed and +destructed. This can be used to monitor memory usage.
+The following is also provided:
-NOT DONE- -
This provides functions that operate of a BitSet for a PVStructure. It -currently has only one method:
-MultiChoice defines an array of strings and a bit set that selects an -arbitrary set of the choices.
-NOT DONE- -
where
-This package provides utility code:
+This is adapted from the java.util.BitSet. bitSet.h is:
+class BitSet /*: public Serializable*/ {
+public:
+ 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;
+ 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(int size = 32, int byteOrder = EPICS_BYTE_ORDER);
+ ~ByteBuffer();
+ ByteBuffer* clear();
+ ByteBuffer* flip();
+ ByteBuffer* rewind();
+ bool getBoolean();
+ int8 getByte();
+ int16 getShort();
+ int32 getInt();
+ int64 getLong();
+ float getFloat();
+ double getDouble();
+ void get(char* dst, int offset, int count);
+ ByteBuffer* put(const char* src, int offset, int count);
+ ByteBuffer* putBoolean(bool value);
+ ByteBuffer* putByte(int8 value);
+ ByteBuffer* putShort(int16 value);
+ ByteBuffer* putInt(int32 value);
+ ByteBuffer* putLong(int64 value);
+ ByteBuffer* putFloat(float value);
+ ByteBuffer* putDouble(double value);
+ inline int getSize() const;
+ inline int getArrayOffset() const;
+ inline int getPosition() const;
+ inline int getLimit() const;
+ inline int getRemaining() const;
+ inline int getByteOrder() const;
+ inline const char* getArray() const;
+ // TODO must define arrays
+private:
+};
+
+x
+ +This class provides coordinates activity between threads. One thread can +wait for the event and the other signals the event.
+class Event : private NoDefaultMethods {
+public:
+ Event(bool full);
+ ~Event();
+ static ConstructDestructCallback *getConstructDestructCallback();
+ 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
+File epicsException.h describes:
+class BaseException : public std::exception {
+public:
+ BaseException(const char* message, const char* file,
+ int line, std::exception* cause = 0);
+ virtual ~BaseException();
+ virtual const char* what();
+ void toString(std::string& str, unsigned int depth = 0);
+ static inline void getStackTrace(
+ std::string* trace, unsigned int skip_frames = 0, unsigned int max_frames = 63)
+private:
+ // ...
+}
+
+x
+ +An Executor is a thread that can execute commands. The user can request +that a single command be executed.
+class ExecutorNode;
+
+class Command {
+public:
+ virtual void command() = 0;
+};
+
+class Executor : private NoDefaultMethods {
+public:
+ Executor(String threadName,ThreadPriority priority);
+ ~Executor();
+ static ConstructDestructCallback *getConstructDestructCallback();
+ ExecutorNode * createNode(Command *command);
+ void execute(ExecutorNode *node);
+private:
+ class ExecutorPvt *pImpl;
+};
+
+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:
+LinkedList implements a double linked list that requires a user to +allocate the nodes. It is more efficent that std::list. linkedList.h is +template that is both a complete description and definition. It uses +linkedListVoid for method definitions. linkedListVoid is not\ meant for use +except via linkedList. Note, however, that linkedListVoid does have both a +node and a list static method getConstructDestructCallback, which allows +access to how many nodes and lists have been created and destroyed.
+ +A node can only be on one list at a time but can be put, at different +times, on different lists as long as they all hold the same type of objects. +An exception is thrown if an attempt is made to put a node on a list if the +node is already on a list.
+template <typename T>
+class LinkedList;
+
+template <typename T>
+class LinkedListNode : private LinkedListVoidNode {
+public:
+ LinkedListNode(T *object);
+ ~LinkedListNode();
+ T *getObject();
+ bool isOnList();
+};
+template <typename T>
+class LinkedList : private LinkedListVoid {
+public:
+ LinkedList();
+ ~LinkedList();
+ int getLength();
+ void addTail(LinkedListNode<T> *node);
+ void addHead(LinkedListNode<T> *node);
+ void insertAfter(LinkedListNode<T> *node,
+ LinkedListNode<T> *addNode);
+ void insertBefore(LinkedListNode<T> *node,
+ LinkedListNode<T> *addNode);
+ LinkedListNode<T> *removeTail();
+ LinkedListNode<T> *removeHead();
+ void remove(LinkedListNode<T> *listNode);
+ void remove(T *object);
+ LinkedListNode<T> *getHead();
+ LinkedListNode<T> *getTail();
+ LinkedListNode<T> *getNext(LinkedListNode<T> *node);
+ LinkedListNode<T> *getPrev(LinkedListNode<T> *node;
+ bool isEmpty();
+ bool contains(T *object);
+};
+
+LinkedListNode has the methods:
+LinkedList has the methods:
+lock.h contains:
+class Mutex {
+public:
+ Mutex();
+ ~Mutex();
+ void lock();
+ void unlock();
+private:
+};
+
+
+class Lock : private NoDefaultMethods {
+public:
+ explicit Lock(Mutex *pm);
+ ~Lock();
+private:
+};
+
+This is a complete description and definition of lock and mutex. These +make it easy to have a lock that 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 = Mutex();
+ Lock xx(&mutex);
+ if(alreadyInitialized) return;
+ // initialization
+ }
+
+NOT IMPLEMENTED+ +
This is for use by code that wants to handle messages without blocking +higher priority threads.
+ +A messageNode is a class with two public data members:
+A messageQueue is an interface with methods:
+MessageQueueFactory provides the public method:
+An example is:
+ private ExecutorNode executorNode;
+ ...
+ executorNode = executor.createNode(this);
+ ...
+
+ public void message(final String message, MessageType messageType) {
+ boolean execute = false;
+ synchronized(messageQueue) {
+ if(messageQueue.isEmpty()) execute = true;
+ if(messageQueue.isFull()) {
+ messageQueue.replaceLast(message, messageType);
+ } else {
+ messageQueue.put(message, messageType);
+ }
+ }
+ if(syncExec) {
+ iocExecutor.execute(executorNode);
+ }
+ }
+ ...
+ public run() { // handle messages
+ while(true) {
+ String message = null;
+ int numOverrun = 0;
+ synchronized(messageQueue) {
+ MessageNode messageNode = messageQueue.get();
+ numOverrun = messageQueue.getClearOverrun();
+ if(messageNode==null && numOverrun==0) break;
+ message = messageNode.message;
+ }
+ if(numOverrun>0) {
+ System.out.printf(String.format("%n%d missed messages&n", numOverrun));
+ }
+ if(message!=null) {
+ System.out.printf(String.format("%s%n",message));
+ }
+ }
+ }
+
+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 typedefs for integers and String.
+typedef signed char int8; +typedef short int16; +typedef int int32; +typedef long long int64; +typedef unsigned int uint32; +typedef unsigned long long uint64; + +typedef std::string String; +typedef std::string * StringBuilder; +typedef String* StringArray;+ +
where
+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 StringArray messageTypeName;
+
+class Requester {
+public:
+ virtual String getRequesterName() = 0;
+ virtual void message(String message,MessageType messageType) = 0;
+};
+
+where
+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);
+private:
+};
+
+class SerializableControl {
+public:
+ virtual void flushSerializeBuffer() =0;
+ virtual void ensureBuffer(int size) =0;
+};
+class DeserializableControl {
+
+public:
+ virtual void ensureData(int size) =0;
+};
+class Serializable {
+public:
+ virtual void serialize(ByteBuffer *buffer,
+ SerializableControl *flusher) = 0;
+ virtual void deserialize(ByteBuffer *buffer,
+ DeserializableControl *flusher) = 0;
+};
+class BitSetSerializable {
+public:
+ virtual void serialize(ByteBuffer *buffer,
+ SerializableControl *flusher,BitSet *bitSet) = 0;
+ virtual void deserialize(ByteBuffer *buffer,
+ DeserializableControl *flusher,BitSet *bitSet) = 0;
+};
+class SerializableArray : public Serializable {
+public:
+ virtual void serialize(ByteBuffer *buffer,
+ SerializableControl *flusher, int offset, int count) = 0;
+};
+
+where
+The following interfaces are called by pvAccess for transporting data over +the network. The abstract and base classes ensure that these methods are +properly implemented.
+x+ +
x
+ +This is a facility that allows a class to report how many objects of that +class have been created and destroyed. This can help find memory leaks.
+typedef int64 (*getTotal)();
+
+class ConstructDestructCallback : private NoDefaultMethods {
+public:
+ ConstructDestructCallback(
+ String name,
+ getTotal construct,
+ getTotal destruct,
+ getTotal reference);
+ String getConstructName();
+ int64 getTotalConstruct();
+ int64 getTotalDestruct();
+ int64 getTotalReferenceCount();
+private:
+ ~ConstructDestructCallback();
+ String name;
+ getTotal construct;
+ getTotal destruct;
+ getTotal reference;
+};
+
+class ShowConstructDestruct : private NoDefaultMethods {
+public:
+ static void constuctDestructTotals(FILE *fd);
+ static void registerCallback(ConstructDestructCallback *callback);
+private:
+ ShowConstructDestruct();
+ friend ShowConstructDestruct* getShowConstructDestruct();
+};
+
+extern ShowConstructDestruct* getShowConstructDestruct();
+
+ConstructDestructCallback is implemented by a class that keeps track of +how many instances of the class has been created and how many destroyed. The +clas must implement this class and register it with ShowConstructDestruct. To +see an example of how this is implemented look at misc/thread.cpp.
+ +Classes that implement this class also include a static method that makes +ConstructDestructCallback available to code that wants look at the memory +usage of a particular class.
+ +ShowConstructDestruct is the class that reports the memory uasge of all +registered classes. It can be called as folows:
+getShowConstructDestruct()->constuctDestructTotals(fd);+ +
Status provides a way to pass status back to client code. It is new and +not currently used by pvData but may be in the future. It is used by code +that uses pvData.
+NOT IMPLEMENTED+ +
The Status methods are:
+The StatusCreate methods are:
+enum ThreadPriority {
+ lowestPriority,
+ lowerPriority,
+ lowPriority,
+ middlePriority,
+ highPriority,
+ higherPriority,
+ highestPriority
+};
+
+class ThreadPriorityFunc {
+public:
+ static unsigned int const * const getEpicsPriorities();
+ static int getEpicsPriority(ThreadPriority threadPriority);
+};
+
+class Runnable {
+public:
+ virtual void run() = 0;
+};
+
+class Thread;
+
+class Thread : private NoDefaultMethods {
+public:
+ Thread(String name,ThreadPriority priority,Runnable *runnableReady);
+ ~Thread();
+ static ConstructDestructCallback *getConstructDestructCallback();
+ String getName();
+ ThreadPriority getPriority();
+ static void showThreads(StringBuilder buf);
+ static void sleep(double seconds);
+private:
+};
+
+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 {
+public:
+ virtual void function() = 0;
+};
+
+class TimeFunction : private NoDefaultMethods {
+public:
+ TimeFunction(TimeFunctionRequester *requester);
+ ~TimeFunction();
+ double timeCall();
+private:
+ TimeFunctionRequester *requester;
+};
+
+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 {
+public:
+ virtual void callback() = 0;
+ virtual void timerStopped() = 0;
+};
+
+class TimerNode : private NoDefaultMethods {
+public:
+ TimerNode(TimerCallback *timerCallback);
+ ~TimerNode();
+ static ConstructDestructCallback *getConstructDestructCallback();
+ void cancel();
+ bool isScheduled();
+private:
+};
+
+class Timer : private NoDefaultMethods {
+public:
+ Timer(String threadName, ThreadPriority priority);
+ ~Timer();
+ static ConstructDestructCallback *getConstructDestructCallback();
+ void scheduleAfterDelay(TimerNode *timerNode,double delay);
+ void schedulePeriodic(TimerNode *timerNode,double delay,double period);
+private:
+};
+
+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:
+TimeStamp is a class for accessing a timeStamp that consists of the number +of seconds since the epoch and the number of nanoseconds within the current +second. The epoch is the posix epoch which is Jan 1, 1970 at 00:00:00 +Universal Time Coordinated.
+ +The seconds since the epoch is kept as an int64 and the nano seconds is +kept as in int32.
+ +The implementation of some of the methods (getCurrent, fromTime_t, and +toTime_t) use epicsTime from EPICS base and will thus have a problem when the +epics secPastEpoch overflows, which will happen in about 2126.
+ +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 measure time + endTime.getCurrent(); + double time = TimeStamp::diff(endTime,startTime);+ +
TimeStamp is described as:
+extern int32 milliSecPerSec;
+extern int32 microSecPerSec;
+extern int32 nanoSecPerSec;
+extern int64 posixEpochAtEpicsEpoch;
+
+class TimeStamp {
+public:
+ TimeStamp();
+ TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 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;
+ int64 getEpicsSecondsPastEpoch() const;
+ int32 getNanoSeconds() const;
+ void put(int64 secondsPastEpoch,int32 nanoSeconds = 0);
+ 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
+private:
+};
+
+TimeStamp has the methods:
+TimeStamp current; + current.getCurrent(); + time_t tt; + current.toTime_t(tt); + struct tm ctm; + memcpy(&ctm,localtime(&tt),sizeof(struct tm)); + fprintf(auxfd, + "%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d nanoSeconds isDst %s\n", + ctm.tm_year+1900,ctm.tm_mon + 1,ctm.tm_mday, + ctm.tm_hour,ctm.tm_min,ctm.tm_sec, + current.getNanoSeconds(), + (ctm.tm_isdst==0) ? "false" : "true");+
prints something like:
+2010.12.01 07:39:48 807264972 nanoSeconds isDst false+
This provides a queue which has an immutable capacity, which is specified +when the queue is created. When the queue is full the user code is expected +to keep using the current el;ement until a new free element becomes avalable. +This is used by pvData.monitor.
+NOT IMPLEMENTED+ +
A queueCreate instance is created via a call like the following:
+QueueCreate<MyObject> queueCreate = new QueueCreate<MyObject>();+ +
Once a queueCreate is available a queue instance is created via code like +the following:
+Queue<MyObject> queue create(MyObject[] myObjects) {
+ QueueElement<MyObject>[] queueElements = new QueueElement[length];
+ for(int i=0; i<length; i++) {
+ QueueElement<MonitorElement> queueElement =
+ queueCreate.createQueueElement(myObjects[i);
+ queueElements[i] = queueElement;
+ }
+ return queueCreate.create(queueElements);
+}
+
+The queue methods are:
+A producer calls getFree and setUsed via code like the following:
+ MyObject getFree() {
+ QueueElement<MyObject> queueElement = queue.getFree();
+ if(queueElement==null) return null;
+ return queueElement.getObject();
+ }
+
+A consumer calls getUsed and releaseUsed via code like the following:
+ while(true) {
+ QueueElement<MyObject> queueElement = queue.getUsed();
+ if(queueElement==null) break;
+ MyObject myObject = queueElement.getObject();
+ // do something with myObject
+ queue.releaseUsed(queueElement);
+ }
+The following is also provided:
+NOT DONE+ +
This provides functions that operate of a BitSet for a PVStructure. It +currently has only one method:
+MultiChoice defines an array of strings and a bit set that selects an +arbitrary set of the choices.
+NOT DONE+ +
where
+Copyright (c) 2008 Martin R. Kraimer