diff --git a/documentation/pvDataCpp.html b/documentation/pvDataCpp.html
index 1bc27ea..002ccc8 100644
--- a/documentation/pvDataCpp.html
+++ b/documentation/pvDataCpp.html
@@ -15,8 +15,8 @@ Overview
TODO
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+
This provides a queue which has an immutable capacit. 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 QueueElement : private QueueElementVoid {
+public:
+ QueueElement(T *object) : QueueElementVoid(static_cast<void *>(object)){}
+ ~QueueElement() {}
+ T *getObject() { return static_cast<T *>(QueueElementVoid::getObject());}
+ friend class Queue<T>;
+};
-A queueCreate instance is created via a call like the following:
- QueueCreate<MyObject> queueCreate = new QueueCreate<MyObject>();
+template <typename T>
+class Queue : private QueueVoid {
+public:
+ Queue(QueueElement<T> **array,int number)
+ : QueueVoid((QueueElementVoid**)array,number)
+ //: QueueVoid(static_cast<QueueElementVoid**>(array),number)
+ {}
+ ~Queue() {}
+ void clear() {QueueVoid::clear();}
+ int getNumberFree() {return QueueVoid::getNumberFree();}
+ int capacity() {return QueueVoid::capacity();}
+ QueueElement<T> *getFree() {
+ return static_cast<QueueElement<T> *>(QueueVoid::getFree());}
+ void setUsed(QueueElement<T> *queueElement) {
+ QueueVoid::setUsed(static_cast<QueueElementVoid *>(queueElement));}
+ QueueElement<T> *getUsed() {
+ return static_cast<QueueElement<T> *>(QueueVoid::getUsed());}
+ void releaseUsed(QueueElement<T> *queueElement) {
+ QueueVoid::releaseUsed(static_cast<QueueElementVoid *>(queueElement));}
+};
-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);
-}
+miscTest/queueTest.cpp provides an example of how to define queueElements +and a queue.
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();
+ MyObject *getFree() {
+ QueueElement<MyObject> *queueElement = queue->getFree();
+ if(queueElement==0) return 0;
+ 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();
+ QueueElement<MyObject> *queueElement = queue->getUsed();
+ if(queueElement==0) break;
+ MyObject *myObject = queueElement->getObject();
// do something with myObject
- queue.releaseUsed(queueElement);
+ queue->releaseUsed(queueElement);
}
diff --git a/pvDataApp/misc/Makefile b/pvDataApp/misc/Makefile
index 1d44f01..91fc38a 100644
--- a/pvDataApp/misc/Makefile
+++ b/pvDataApp/misc/Makefile
@@ -20,6 +20,8 @@ INC += showConstructDestruct.h
INC += timeStamp.h
INC += timeFunction.h
INC += timer.h
+INC += queueVoid.h
+INC += queue.h
LIBSRCS += byteBuffer.cpp
LIBSRCS += bitSet.cpp
@@ -33,6 +35,7 @@ LIBSRCS += executor.cpp
LIBSRCS += timeStamp.cpp
LIBSRCS += timeFunction.cpp
LIBSRCS += timer.cpp
+LIBSRCS += queueVoid.cpp
LIBRARY=pvMisc
diff --git a/pvDataApp/misc/queue.h b/pvDataApp/misc/queue.h
new file mode 100644
index 0000000..d7ac146
--- /dev/null
+++ b/pvDataApp/misc/queue.h
@@ -0,0 +1,53 @@
+/* queue.h */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvDataCPP is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+#ifndef QUEUE_H
+#define QUEUE_H
+#include "queueVoid.h"
+namespace epics { namespace pvData {
+
+template
+class Queue;
+
+template
+class QueueElement;
+
+template
+class QueueElement : private QueueElementVoid {
+public:
+ QueueElement(T *object) : QueueElementVoid(static_cast(object)){}
+ ~QueueElement() {}
+ T *getObject() { return static_cast(QueueElementVoid::getObject());}
+ friend class Queue;
+};
+
+template
+class Queue : private QueueVoid {
+public:
+ Queue(QueueElement **array,int number)
+ : QueueVoid((QueueElementVoid**)array,number)
+ //: QueueVoid(static_cast(array),number)
+ {}
+ ~Queue() {}
+ void clear() {QueueVoid::clear();}
+ int getNumberFree() {return QueueVoid::getNumberFree();}
+ int capacity() {return QueueVoid::capacity();}
+ QueueElement *getFree() {
+ return static_cast *>(QueueVoid::getFree());}
+ void setUsed(QueueElement *queueElement) {
+ QueueVoid::setUsed(static_cast(queueElement));}
+ QueueElement *getUsed() {
+ return static_cast *>(QueueVoid::getUsed());}
+ void releaseUsed(QueueElement *queueElement) {
+ QueueVoid::releaseUsed(static_cast(queueElement));}
+};
+
+
+}}
+#endif /* QUEUE_H */
+
+
+
diff --git a/pvDataApp/misc/queueVoid.cpp b/pvDataApp/misc/queueVoid.cpp
new file mode 100644
index 0000000..6a5af79
--- /dev/null
+++ b/pvDataApp/misc/queueVoid.cpp
@@ -0,0 +1,175 @@
+/* queueVoid.cpp */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvDataCPP is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "lock.h"
+#include "pvType.h"
+#include "queueVoid.h"
+
+namespace epics { namespace pvData {
+
+static volatile int64 totalElementConstruct = 0;
+static volatile int64 totalElementDestruct = 0;
+static volatile int64 totalQueueConstruct = 0;
+static volatile int64 totalQueueDestruct = 0;
+static Mutex *globalMutex = 0;
+
+static int64 getTotalNodeConstruct()
+{
+ Lock xx(globalMutex);
+ return totalElementConstruct;
+}
+
+static int64 getTotalNodeDestruct()
+{
+ Lock xx(globalMutex);
+ return totalElementDestruct;
+}
+
+static int64 getTotalListConstruct()
+{
+ Lock xx(globalMutex);
+ return totalQueueConstruct;
+}
+
+static int64 getTotalListDestruct()
+{
+ Lock xx(globalMutex);
+ return totalQueueDestruct;
+}
+
+static ConstructDestructCallback *pCDCallbackQueueNode;
+static ConstructDestructCallback *pCDCallbackQueue;
+
+static void initPvt()
+{
+ static Mutex mutex = Mutex();
+ Lock xx(&mutex);
+ if(globalMutex==0) {
+ globalMutex = new Mutex();
+ pCDCallbackQueueNode = new ConstructDestructCallback(
+ "queueElement",
+ getTotalNodeConstruct,getTotalNodeDestruct,0);
+
+ pCDCallbackQueue = new ConstructDestructCallback(
+ "queue",
+ getTotalListConstruct,getTotalListDestruct,0);
+ }
+}
+
+
+QueueElementVoid::QueueElementVoid(void *object)
+: object(object)
+{
+ initPvt();
+ Lock xx(globalMutex);
+ totalElementConstruct++;
+}
+
+
+QueueElementVoid::~QueueElementVoid()
+{
+ Lock xx(globalMutex);
+ totalElementDestruct++;
+}
+
+ConstructDestructCallback *QueueElementVoid::getConstructDestructCallback()
+{
+ initPvt();
+ return pCDCallbackQueueNode;
+}
+
+void *QueueElementVoid::getObject() {
+ return object;
+}
+
+QueueVoid::QueueVoid(QueueElementVoidPtrArray array,int number)
+: array(array),number(number),
+ numberFree(number),numberUsed(0),
+ nextGetFree(0),nextSetUsed(),
+ nextGetUsed(0),nextReleaseUsed(0)
+{
+ initPvt();
+ Lock xx(globalMutex);
+ totalQueueConstruct++;
+}
+
+QueueVoid::~QueueVoid()
+{
+ Lock xx(globalMutex);
+ totalQueueDestruct++;
+}
+
+ConstructDestructCallback *QueueVoid::getConstructDestructCallback()
+{
+ initPvt();
+ return pCDCallbackQueue;
+}
+
+void QueueVoid::clear()
+{
+ numberFree = number;
+ numberUsed = 0;
+ nextGetFree = 0;
+ nextSetUsed = 0;
+ nextGetUsed = 0;
+ nextReleaseUsed = 0;
+}
+
+int QueueVoid::getNumberFree()
+{
+ return numberFree;
+}
+
+int QueueVoid::capacity()
+{
+ return number;
+}
+
+QueueElementVoid * QueueVoid::getFree()
+{
+ if(numberFree==0) return 0;
+ numberFree--;
+ QueueElementVoid *queueElement = array[nextGetFree++];
+ if(nextGetFree>=number) nextGetFree = 0;
+ return queueElement;
+}
+
+void QueueVoid::setUsed(QueueElementVoid *queueElement)
+{
+ if(queueElement!=array[nextSetUsed++]) {
+ throw std::logic_error(String("not correcect queueElement"));
+ }
+ numberUsed++;
+ if(nextSetUsed>=number) nextSetUsed = 0;
+}
+
+QueueElementVoid * QueueVoid::getUsed()
+{
+ if(numberUsed==0) return 0;
+ QueueElementVoid *queueElement = array[nextGetUsed++];
+ if(nextGetUsed>=number) nextGetUsed = 0;
+ return queueElement;
+}
+
+void QueueVoid::releaseUsed(QueueElementVoid *queueElement)
+{
+ if(queueElement!=array[nextReleaseUsed++]) {
+ throw std::logic_error(String(
+ "not queueElement returned by last call to getUsed"));
+ }
+ if(nextReleaseUsed>=number) nextReleaseUsed = 0;
+ numberUsed--;
+ numberFree++;
+}
+
+}}
diff --git a/pvDataApp/misc/queueVoid.h b/pvDataApp/misc/queueVoid.h
new file mode 100644
index 0000000..859e57d
--- /dev/null
+++ b/pvDataApp/misc/queueVoid.h
@@ -0,0 +1,62 @@
+/* queueVoid.h */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvDataCPP is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+#include "showConstructDestruct.h"
+#ifndef QUEUEVOID_H
+#define QUEUEVOID_H
+namespace epics { namespace pvData {
+
+class QueueVoid;
+class QueueElementVoid;
+
+typedef QueueElementVoid * QueueElementVoidPtr;
+typedef QueueElementVoidPtr * QueueElementVoidPtrArray;
+
+class QueueElementVoid {
+public:
+ ~QueueElementVoid();
+ static ConstructDestructCallback *getConstructDestructCallback();
+ void *getObject();
+protected:
+ QueueElementVoid(void *object);
+private:
+ void *object;
+ friend class QueueVoid;
+};
+
+typedef class QueueElementVoid * QueueElementVoidArray;
+
+class QueueVoid {
+public:
+ ~QueueVoid();
+ static ConstructDestructCallback *getConstructDestructCallback();
+ void clear();
+ int getNumberFree();
+ int capacity();
+ QueueElementVoid *getFree();
+ void setUsed(QueueElementVoid *queueElement);
+ QueueElementVoid *getUsed();
+ void releaseUsed(QueueElementVoid *queueElement);
+protected:
+ QueueVoid(QueueElementVoidPtrArray array,int number);
+private:
+ friend class QueueElementVoid;
+ QueueElementVoidPtrArray array;
+ int number;
+ int numberFree;
+ int numberUsed;
+ int nextGetFree;
+ int nextSetUsed;
+ int nextGetUsed;
+ int nextReleaseUsed;
+};
+
+
+}}
+#endif /* QUEUEVOID_H */
+
+
+
diff --git a/pvDataApp/miscTest/Makefile b/pvDataApp/miscTest/Makefile
index e41f91c..3192a46 100644
--- a/pvDataApp/miscTest/Makefile
+++ b/pvDataApp/miscTest/Makefile
@@ -10,6 +10,10 @@ PROD_HOST += testLinkedList
testLinkedList_SRCS += testLinkedList.cpp
testLinkedList_LIBS += pvMisc Com
+PROD_HOST += testQueue
+testQueue_SRCS += testQueue.cpp
+testQueue_LIBS += pvMisc Com
+
PROD_HOST += testThread
testThread_SRCS += testThread.cpp
testThread_LIBS += pvMisc Com
diff --git a/pvDataApp/miscTest/testQueue.cpp b/pvDataApp/miscTest/testQueue.cpp
new file mode 100644
index 0000000..c0ab94f
--- /dev/null
+++ b/pvDataApp/miscTest/testQueue.cpp
@@ -0,0 +1,162 @@
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvDataCPP is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+/*
+ * testQueue.cpp
+ *
+ * Created on: 2010.12
+ * Author: Marty Kraimer
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "lock.h"
+#include "timeStamp.h"
+#include "queue.h"
+#include "showConstructDestruct.h"
+#include "event.h"
+#include "thread.h"
+#include "executor.h"
+
+
+using namespace epics::pvData;
+
+struct Data {
+ int a;
+ int b;
+};
+
+
+static int numElements = 5;
+typedef QueueElement DataElement;
+typedef Queue DataQueue;
+
+class Sink : public Runnable {
+public:
+ Sink(DataQueue *queue,FILE *auxfd);
+ ~Sink();
+ void stop();
+ void look();
+ virtual void run();
+private:
+ DataQueue *queue;
+ FILE *auxfd;
+ bool isStopped;
+ Event *wait;
+ Event *stopped;
+ Event *waitReturn;
+ Event *waitEmpty;
+ Thread *thread;
+};
+
+Sink::Sink(DataQueue *queue,FILE *auxfd)
+: queue(queue),
+ auxfd(auxfd),
+ isStopped(false),
+ wait(new Event()),
+ stopped(new Event()),
+ waitReturn(new Event()),
+ waitEmpty(new Event()),
+ thread(new Thread(String("sink"),middlePriority,this))
+{
+}
+
+Sink::~Sink() {
+ delete thread;
+ delete waitEmpty;
+ delete waitReturn;
+ delete stopped;
+ delete wait;
+}
+
+void Sink::stop()
+{
+ isStopped = true;
+ wait->signal();
+ stopped->wait();
+}
+
+void Sink::look()
+{
+ wait->signal();
+ waitEmpty->wait();
+}
+
+void Sink::run()
+{
+ while(!isStopped) {
+ wait->wait();
+ if(isStopped) break;
+ while(true) {
+ DataElement *element = queue->getUsed();
+ if(element==0) {
+ waitEmpty->signal();
+ break;
+ }
+ Data *data = element->getObject();
+ fprintf(auxfd," sink a %d b %d\n",data->a,data->b);
+ queue->releaseUsed(element);
+ }
+ }
+ stopped->signal();
+}
+
+static void testBasic(FILE * fd,FILE *auxfd ) {
+ Data dataArray[numElements];
+ DataElement *array[numElements];
+ for(int i=0; igetFree();
+ if(element==0) break;
+ Data *data = element->getObject();
+ fprintf(auxfd,"source a %d b %d\n",data->a,data->b);
+ queue->setUsed(element);
+ }
+ sink->look();
+ // now alternate
+ for(int i=0; igetFree();
+ assert(element!=0);
+ Data *data = element->getObject();
+ fprintf(auxfd,"source a %d b %d\n",data->a,data->b);
+ queue->setUsed(element);
+ sink->look();
+ }
+ sink->stop();
+ delete sink;
+ delete queue;
+ for(int i=0; i1) fileName = argv[1];
+ FILE * fd = stdout;
+ if(fileName!=0 && fileName[0]!=0) {
+ fd = fopen(fileName,"w+");
+ }
+ char *auxFileName = 0;
+ if(argc>2) auxFileName = argv[2];
+ FILE *auxfd = stdout;
+ if(auxFileName!=0 && auxFileName[0]!=0) {
+ auxfd = fopen(auxFileName,"w+");
+ }
+ testBasic(fd,auxfd);
+ getShowConstructDestruct()->constuctDestructTotals(fd);
+ return (0);
+}
+
diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h
index d190038..7b5bd5c 100644
--- a/pvDataApp/pv/pvData.h
+++ b/pvDataApp/pv/pvData.h
@@ -57,7 +57,7 @@ typedef int32 * IntArray;
typedef int64 * LongArray;
typedef float * FloatArray;
typedef double * DoubleArray;
-//typedef String * StringArray; alreadt defined in pvType.h
+//typedef String * StringArray; already defined in pvType.h
class PVAuxInfo : private NoDefaultMethods {
public: