diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index 3342815..2675fe5 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -3,6 +3,7 @@ include $(TOP)/configure/CONFIG DIRS += misc DIRS += pv DIRS += factory +DIRS += property DIRS += miscTest DIRS += pvTest include $(TOP)/configure/RULES_DIRS diff --git a/pvDataApp/factory/AbstractPVField.h b/pvDataApp/factory/AbstractPVField.h index ee9373d..e38aa3c 100644 --- a/pvDataApp/factory/AbstractPVField.h +++ b/pvDataApp/factory/AbstractPVField.h @@ -12,6 +12,58 @@ namespace epics { namespace pvData { static String notImplemented("not implemented"); +static volatile int64 totalConstruct = 0; +static volatile int64 totalDestruct = 0; +static Mutex *globalMutex = 0; + +class CDCallbackPVField : public ConstructDestructCallback { +public: + CDCallbackPVField(); + virtual String getConstructName(); + virtual int64 getTotalConstruct(); + virtual int64 getTotalDestruct(); + virtual int64 getTotalReferenceCount(); +private: + String name; +}; + +CDCallbackPVField::CDCallbackPVField() +: name("pvField") +{ + getShowConstructDestruct()->registerCallback(this); +} + +String CDCallbackPVField::getConstructName() {return name;} + +int64 CDCallbackPVField::getTotalConstruct() +{ + Lock xx(globalMutex); + return totalConstruct; +} + +int64 CDCallbackPVField::getTotalDestruct() +{ + Lock xx(globalMutex); + return totalDestruct; +} + +int64 CDCallbackPVField::getTotalReferenceCount() +{ + return 0; +} + +static ConstructDestructCallback *pConstructDestructCallback; + +static void init() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { + globalMutex = new Mutex(); + pConstructDestructCallback = new CDCallbackPVField(); + } +} + class PVFieldPvt { public: PVFieldPvt(PVStructure *parent,FieldConstPtr field); @@ -42,31 +94,11 @@ PVFieldPvt::~PVFieldPvt() } -static volatile int64 totalConstruct = 0; -static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; - -void PVField::init() -{ - globalMutex = new Mutex(); -} - -int64 PVField::getTotalConstruct() -{ - Lock xx(globalMutex); - return totalConstruct; -} - -int64 PVField::getTotalDestruct() -{ - Lock xx(globalMutex); - return totalDestruct; -} - PVField::PVField(PVStructure *parent,FieldConstPtr field) : pImpl(new PVFieldPvt(parent,field)) { + init(); Lock xx(globalMutex); totalConstruct++; } @@ -78,6 +110,13 @@ PVField::~PVField() delete pImpl; } +ConstructDestructCallback *PVField::getConstructDestructCallback() +{ + init(); + return pConstructDestructCallback; +} + + String PVField::getRequesterName() { static String none("none"); diff --git a/pvDataApp/factory/FieldCreateFactory.cpp b/pvDataApp/factory/FieldCreateFactory.cpp index 572b3fe..65c4043 100644 --- a/pvDataApp/factory/FieldCreateFactory.cpp +++ b/pvDataApp/factory/FieldCreateFactory.cpp @@ -9,270 +9,307 @@ namespace epics { namespace pvData { - static DebugLevel debugLevel = lowDebug; - static void newLine(StringBuilder buffer, int indentLevel) - { - *buffer += "\n"; - for(int i=0; iregisterCallback(this); +} - Field::Field(String fieldName,Type type) - : pImpl(new FieldPvt(fieldName,type)) - { - Lock xx(globalMutex); - totalConstruct++; - } +String CDCallbackPVIntrospect::getConstructName() +{ + return name; +} - Field::~Field() { - Lock xx(globalMutex); - totalDestruct++; - // note that compiler automatically calls destructor for fieldName - delete pImpl; - if(debugLevel==highDebug) printf("~Field %s\n",pImpl->fieldName.c_str()); - } +int64 CDCallbackPVIntrospect::getTotalConstruct() +{ + Lock xx(globalMutex); + return totalConstruct; +} - int Field::getReferenceCount() const { - Lock xx(globalMutex); - return pImpl->referenceCount; - } - String Field::getFieldName() const {return pImpl->fieldName;} - Type Field::getType() const {return pImpl->type;} +int64 CDCallbackPVIntrospect::getTotalDestruct() +{ + Lock xx(globalMutex); + return totalDestruct; +} - void Field::incReferenceCount() const { - Lock xx(globalMutex); - pImpl->referenceCount++; - totalReferenceCount++; - } +int64 CDCallbackPVIntrospect::getTotalReferenceCount() +{ + return totalReferenceCount; +} - void Field::decReferenceCount() const { - Lock xx(globalMutex); - if(pImpl->referenceCount<=0) { - String message("logicError field "); - message += pImpl->fieldName; - throw std::logic_error(message); - } - pImpl->referenceCount--; - totalReferenceCount--; - if(pImpl->referenceCount==0) delete this; - } +static ConstructDestructCallback *pConstructDestructCallback; - - void Field::toString(StringBuilder buffer,int indentLevel) const{ - *buffer += " "; - *buffer += pImpl->fieldName.c_str(); - } - - Scalar::Scalar(String fieldName,ScalarType scalarType) - : Field(fieldName,scalar),scalarType(scalarType){} - - Scalar::~Scalar(){} - - void Scalar::toString(StringBuilder buffer,int indentLevel) const{ - ScalarTypeFunc::toString(buffer,scalarType); - Field::toString(buffer,indentLevel); - } - - - ScalarArray::ScalarArray - (String fieldName,ScalarType elementType) - : Field(fieldName,scalarArray),elementType(elementType){} - ScalarArray::~ScalarArray() {} - - void ScalarArray::toString(StringBuilder buffer,int indentLevel) const{ - String temp = String(); - ScalarTypeFunc::toString(&temp,elementType); - temp += "Array"; - *buffer += temp; - Field::toString(buffer,indentLevel); - } - - StructureArray::StructureArray(String fieldName,StructureConstPtr structure) - : Field(fieldName,structureArray),pstructure(structure) - { - pstructure->incReferenceCount(); - } - - StructureArray::~StructureArray() { - if(debugLevel==highDebug) printf("~StructureArray\n"); - pstructure->decReferenceCount(); - } - - void StructureArray::toString(StringBuilder buffer,int indentLevel) const { - *buffer += " structureArray "; - Field::toString(buffer,indentLevel); - newLine(buffer,indentLevel + 1); - pstructure->toString(buffer,indentLevel + 1); - } - - - Structure::Structure (String fieldName, - int numberFields, FieldConstPtrArray infields) - : Field(fieldName,structure), - numberFields(numberFields), - fields(new FieldConstPtr[numberFields]) - { - for(int i=0; igetFieldName(); - // look for duplicates - for(int j=i+1; jgetFieldName(); - int result = name.compare(otherName); - if(result==0) { - String message("duplicate fieldName "); - message += name; - throw std::invalid_argument(message); - } - } - // inc reference counter - fields[i]->incReferenceCount(); - } - } - - Structure::~Structure() { - if(debugLevel==highDebug) - printf("~Structure %s\n",Field::getFieldName().c_str()); - for(int i=0; idecReferenceCount(); - } - delete[] fields; - } - - FieldConstPtr Structure::getField(String fieldName) const { - for(int i=0; igetFieldName()); - if(result==0) return pfield; - } - return 0; - } - - int Structure::getFieldIndex(String fieldName) const { - for(int i=0; igetFieldName()); - if(result==0) return i; - } - return -1; - } - - void Structure::toString(StringBuilder buffer,int indentLevel) const{ - *buffer += "structure"; - Field::toString(buffer,indentLevel); - newLine(buffer,indentLevel+1); - for(int i=0; itoString(buffer,indentLevel+1); - if(igetType(); - switch(type) { - case scalar: { - ScalarConstPtr pscalar = dynamic_cast(pfield); - return createScalar(fieldName,pscalar->getScalarType()); - } - case scalarArray: { - ScalarArrayConstPtr pscalarArray = dynamic_cast(pfield); - return createScalarArray(fieldName,pscalarArray->getElementType()); - } - case structure: { - StructureConstPtr pstructure = dynamic_cast(pfield); - return createStructure(fieldName,pstructure->getNumberFields(),pstructure->getFields()); - } - case structureArray: { - StructureArrayConstPtr pstructureArray = dynamic_cast(pfield); - return createStructureArray(fieldName,pstructureArray->getStructure()); - } - } - String message("field "); - message += fieldName; - throw std::logic_error(message); - } - - static FieldCreate* fieldCreate = 0; - - FieldCreate::FieldCreate() - { +static void init() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { globalMutex = new Mutex(); - } + pConstructDestructCallback = new CDCallbackPVIntrospect(); + } +} - FieldCreate * getFieldCreate() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(fieldCreate==0) fieldCreate = new FieldCreate(); - return fieldCreate; - } +Field::Field(String fieldName,Type type) + : pImpl(new FieldPvt(fieldName,type)) +{ + Lock xx(globalMutex); + totalConstruct++; +} + +Field::~Field() { + Lock xx(globalMutex); + totalDestruct++; + // note that compiler automatically calls destructor for fieldName + delete pImpl; + if(debugLevel==highDebug) printf("~Field %s\n",pImpl->fieldName.c_str()); +} + +int Field::getReferenceCount() const { + Lock xx(globalMutex); + return pImpl->referenceCount; +} + +String Field::getFieldName() const {return pImpl->fieldName;} + +Type Field::getType() const {return pImpl->type;} + +void Field::incReferenceCount() const { + Lock xx(globalMutex); + pImpl->referenceCount++; + totalReferenceCount++; +} + +void Field::decReferenceCount() const { + Lock xx(globalMutex); + if(pImpl->referenceCount<=0) { + String message("logicError field "); + message += pImpl->fieldName; + throw std::logic_error(message); + } + pImpl->referenceCount--; + totalReferenceCount--; + if(pImpl->referenceCount==0) delete this; +} + + +void Field::toString(StringBuilder buffer,int indentLevel) const{ + *buffer += " "; + *buffer += pImpl->fieldName.c_str(); +} + +Scalar::Scalar(String fieldName,ScalarType scalarType) + : Field(fieldName,scalar),scalarType(scalarType){} + +Scalar::~Scalar(){} + +void Scalar::toString(StringBuilder buffer,int indentLevel) const{ + ScalarTypeFunc::toString(buffer,scalarType); + Field::toString(buffer,indentLevel); +} + + +ScalarArray::ScalarArray(String fieldName,ScalarType elementType) +: Field(fieldName,scalarArray),elementType(elementType){} + +ScalarArray::~ScalarArray() {} + +void ScalarArray::toString(StringBuilder buffer,int indentLevel) const{ + String temp = String(); + ScalarTypeFunc::toString(&temp,elementType); + temp += "Array"; + *buffer += temp; + Field::toString(buffer,indentLevel); +} + +StructureArray::StructureArray(String fieldName,StructureConstPtr structure) +: Field(fieldName,structureArray),pstructure(structure) +{ + pstructure->incReferenceCount(); +} + +StructureArray::~StructureArray() { + if(debugLevel==highDebug) printf("~StructureArray\n"); + pstructure->decReferenceCount(); +} + +void StructureArray::toString(StringBuilder buffer,int indentLevel) const { + *buffer += " structureArray "; + Field::toString(buffer,indentLevel); + newLine(buffer,indentLevel + 1); + pstructure->toString(buffer,indentLevel + 1); +} + + +Structure::Structure (String fieldName, + int numberFields, FieldConstPtrArray infields) +: Field(fieldName,structure), + numberFields(numberFields), + fields(new FieldConstPtr[numberFields]) +{ + for(int i=0; igetFieldName(); + // look for duplicates + for(int j=i+1; jgetFieldName(); + int result = name.compare(otherName); + if(result==0) { + String message("duplicate fieldName "); + message += name; + throw std::invalid_argument(message); + } + } + // inc reference counter + fields[i]->incReferenceCount(); + } +} + +Structure::~Structure() { + if(debugLevel==highDebug) + printf("~Structure %s\n",Field::getFieldName().c_str()); + for(int i=0; idecReferenceCount(); + } + delete[] fields; +} + +FieldConstPtr Structure::getField(String fieldName) const { + for(int i=0; igetFieldName()); + if(result==0) return pfield; + } + return 0; +} + +int Structure::getFieldIndex(String fieldName) const { + for(int i=0; igetFieldName()); + if(result==0) return i; + } + return -1; +} + +void Structure::toString(StringBuilder buffer,int indentLevel) const{ + *buffer += "structure"; + Field::toString(buffer,indentLevel); + newLine(buffer,indentLevel+1); + for(int i=0; itoString(buffer,indentLevel+1); + if(igetType(); + switch(type) { + case scalar: { + ScalarConstPtr pscalar = dynamic_cast(pfield); + return createScalar(fieldName,pscalar->getScalarType()); + } + case scalarArray: { + ScalarArrayConstPtr pscalarArray = dynamic_cast(pfield); + return createScalarArray(fieldName,pscalarArray->getElementType()); + } + case structure: { + StructureConstPtr pstructure = dynamic_cast(pfield); + return createStructure(fieldName,pstructure->getNumberFields(),pstructure->getFields()); + } + case structureArray: { + StructureArrayConstPtr pstructureArray = dynamic_cast(pfield); + return createStructureArray(fieldName,pstructureArray->getStructure()); + } + } + String message("field "); + message += fieldName; + throw std::logic_error(message); +} + +static FieldCreate* fieldCreate = 0; + +FieldCreate::FieldCreate() +{ + init(); +} + +FieldCreate * getFieldCreate() { + static Mutex mutex = Mutex(); + Lock xx(&mutex); + + if(fieldCreate==0) fieldCreate = new FieldCreate(); + return fieldCreate; +} }} diff --git a/pvDataApp/factory/PVAuxInfoImpl.cpp b/pvDataApp/factory/PVAuxInfoImpl.cpp index 0bb6809..1f9d257 100644 --- a/pvDataApp/factory/PVAuxInfoImpl.cpp +++ b/pvDataApp/factory/PVAuxInfoImpl.cpp @@ -11,6 +11,56 @@ namespace epics { namespace pvData { +static volatile int64 totalConstruct = 0; +static volatile int64 totalDestruct = 0; +static Mutex *globalMutex = 0; + +class CDCallbackPVAuxInfo : public ConstructDestructCallback { +public: + CDCallbackPVAuxInfo(); + virtual String getConstructName(); + virtual int64 getTotalConstruct(); + virtual int64 getTotalDestruct(); + virtual int64 getTotalReferenceCount(); +private: + String name; +}; + +CDCallbackPVAuxInfo::CDCallbackPVAuxInfo() +: name("pvAuxInfo") +{ + getShowConstructDestruct()->registerCallback(this); +} +String CDCallbackPVAuxInfo::getConstructName() {return name;} +int64 CDCallbackPVAuxInfo::getTotalConstruct() +{ + Lock xx(globalMutex); + return totalConstruct; +} +int64 CDCallbackPVAuxInfo::getTotalDestruct() +{ + Lock xx(globalMutex); + return totalDestruct; +} +int64 CDCallbackPVAuxInfo::getTotalReferenceCount() +{ + return 0; +} + +static ConstructDestructCallback *pConstructDestructCallback; + +static void init() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { + globalMutex = new Mutex(); + pConstructDestructCallback = new CDCallbackPVAuxInfo(); + } +} + +typedef std::map::const_iterator map_iterator; + class PVAuxInfoPvt { public: PVAuxInfoPvt(PVField *pvField) @@ -21,33 +71,10 @@ public: std::map theMap; }; -static volatile int64 totalConstruct = 0; -static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; - -typedef std::map::const_iterator map_iterator; - -void PVAuxInfo::init() -{ - globalMutex = new Mutex(); -} - -int64 PVAuxInfo::getTotalConstruct() -{ - Lock xx(globalMutex); - return totalConstruct; -} - -int64 PVAuxInfo::getTotalDestruct() -{ - Lock xx(globalMutex); - return totalDestruct; -} - - PVAuxInfo::PVAuxInfo(PVField *pvField) : pImpl(new PVAuxInfoPvt(pvField)) { + init(); Lock xx(globalMutex); totalConstruct++; } @@ -68,6 +95,11 @@ PVField * PVAuxInfo::getPVField() { return pImpl->pvField; } +ConstructDestructCallback *PVAuxInfo::getConstructDestructCallback() +{ + init(); + return pConstructDestructCallback; +} PVScalar * PVAuxInfo::createInfo(String key,ScalarType scalarType) { diff --git a/pvDataApp/factory/PVDataCreateFactory.cpp b/pvDataApp/factory/PVDataCreateFactory.cpp index 4529d84..a9e3378 100644 --- a/pvDataApp/factory/PVDataCreateFactory.cpp +++ b/pvDataApp/factory/PVDataCreateFactory.cpp @@ -38,10 +38,7 @@ static Convert* convert = 0; static FieldCreate * fieldCreate = 0; static PVDataCreate* pvDataCreate = 0; -PVDataCreate::PVDataCreate(){ - PVField::init(); - PVAuxInfo::init(); -} +PVDataCreate::PVDataCreate(){ } PVField *PVDataCreate::createPVField(PVStructure *parent, FieldConstPtr field) diff --git a/pvDataApp/misc/Makefile b/pvDataApp/misc/Makefile index 189f26e..a5c6b43 100644 --- a/pvDataApp/misc/Makefile +++ b/pvDataApp/misc/Makefile @@ -13,11 +13,23 @@ INC += bitSet.h INC += byteBuffer.h INC += epicsException.h INC += serializeHelper.h +INC += event.h +INC += thread.h +INC += executor.h +INC += showConstructDestruct.h +INC += timeStamp.h +INC += timeFunction.h LIBSRCS += byteBuffer.cpp LIBSRCS += bitSet.cpp LIBSRCS += serializeHelper.cpp LIBSRCS += linkedListVoid.cpp +LIBSRCS += event.cpp +LIBSRCS += thread.cpp +LIBSRCS += executor.cpp +LIBSRCS += showConstructDestruct.cpp +LIBSRCS += timeStamp.cpp +LIBSRCS += timeFunction.cpp LIBRARY=pvMisc diff --git a/pvDataApp/misc/event.cpp b/pvDataApp/misc/event.cpp new file mode 100644 index 0000000..c9a0687 --- /dev/null +++ b/pvDataApp/misc/event.cpp @@ -0,0 +1,114 @@ +/* event.cpp */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "noDefaultMethods.h" +#include "pvType.h" +#include "lock.h" +#include "event.h" + +namespace epics { namespace pvData { + +static volatile int64 totalConstruct = 0; +static volatile int64 totalDestruct = 0; +static Mutex *globalMutex = 0; +static String alreadyOn("already on list"); + +class ConstructDestructCallbackEvent : public ConstructDestructCallback { +public: + ConstructDestructCallbackEvent(); + virtual String getConstructName(); + virtual int64 getTotalConstruct(); + virtual int64 getTotalDestruct(); + virtual int64 getTotalReferenceCount(); +private: + String name; +}; + +ConstructDestructCallbackEvent::ConstructDestructCallbackEvent() +: name("event") +{ + getShowConstructDestruct()->registerCallback(this); +} + +String ConstructDestructCallbackEvent::getConstructName() {return name;} + +int64 ConstructDestructCallbackEvent::getTotalConstruct() +{ + Lock xx(globalMutex); + return totalConstruct; +} + +int64 ConstructDestructCallbackEvent::getTotalDestruct() +{ + Lock xx(globalMutex); + return totalDestruct; +} + +int64 ConstructDestructCallbackEvent::getTotalReferenceCount() +{ + return 0; +} + +static ConstructDestructCallback *pConstructDestructCallback; + +static void init() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { + globalMutex = new Mutex(); + pConstructDestructCallback = new ConstructDestructCallbackEvent(); + } +} + +Event::~Event() { + epicsEventDestroy(id); + totalDestruct++; +} + +Event::Event(EventInitialState initial) +: id(epicsEventCreate((initial==eventEmpty)?epicsEventEmpty : epicsEventFull)) +{ + init(); + totalConstruct++; +} + +ConstructDestructCallback *Event::getConstructDestructCallback() +{ + init(); + return pConstructDestructCallback; +} + +void Event::signal() +{ + epicsEventSignal(id); +} + +bool Event::wait () +{ + epicsEventWaitStatus status = epicsEventWait(id); + return status==epicsEventWaitOK ? true : false; +} + +bool Event::wait ( double timeOut ) +{ + epicsEventWaitStatus status = epicsEventWaitWithTimeout(id,timeOut); + return status==epicsEventWaitOK ? true : false; +} + +bool Event::tryWait () +{ + epicsEventWaitStatus status = epicsEventTryWait(id); + return status==epicsEventWaitOK ? true : false; +} + +}} diff --git a/pvDataApp/misc/event.h b/pvDataApp/misc/event.h new file mode 100644 index 0000000..96a3ff5 --- /dev/null +++ b/pvDataApp/misc/event.h @@ -0,0 +1,40 @@ +/* event.h */ +#ifndef EVENT_H +#define EVENT_H +#include +#include +#include +#include +#include "noDefaultMethods.h" +#include "pvType.h" +#include "showConstructDestruct.h" + +namespace epics { namespace pvData { + +enum EventWaitStatus { + eventWaitOK, + eventWaitTimeout, + eventWaitError +}; + +enum EventInitialState { + eventEmpty, + eventFull +}; + + +class Event : private NoDefaultMethods { +public: + ~Event(); + Event(EventInitialState initial); + 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; +}; + +}} +#endif /* EVENT_H */ diff --git a/pvDataApp/misc/executor.cpp b/pvDataApp/misc/executor.cpp new file mode 100644 index 0000000..ad21048 --- /dev/null +++ b/pvDataApp/misc/executor.cpp @@ -0,0 +1,223 @@ +/* executor.h */ +#include +#include +#include +#include +#include + +#include +#include +#include "linkedList.h" +#include "lock.h" +#include "thread.h" +#include "event.h" +#include "executor.h" + +namespace epics { namespace pvData { + +static volatile int64 totalConstruct = 0; +static volatile int64 totalDestruct = 0; +static Mutex *globalMutex = 0; + +class ConstructDestructCallbackExecutor : public ConstructDestructCallback { +public: + ConstructDestructCallbackExecutor(); + virtual String getConstructName(); + virtual int64 getTotalConstruct(); + virtual int64 getTotalDestruct(); + virtual int64 getTotalReferenceCount(); +private: + String name; +}; + +ConstructDestructCallbackExecutor::ConstructDestructCallbackExecutor() +: name("executor") +{ + getShowConstructDestruct()->registerCallback(this); +} + +String ConstructDestructCallbackExecutor::getConstructName() {return name;} + +int64 ConstructDestructCallbackExecutor::getTotalConstruct() +{ + Lock xx(globalMutex); + return totalConstruct; +} + +int64 ConstructDestructCallbackExecutor::getTotalDestruct() +{ + Lock xx(globalMutex); + return totalDestruct; +} +int64 ConstructDestructCallbackExecutor::getTotalReferenceCount() + +{ + return 0; +} + + +static ConstructDestructCallback *pConstructDestructCallback; + +static void init() { + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { + globalMutex = new Mutex(); + pConstructDestructCallback = new ConstructDestructCallbackExecutor(); + } +} + + +typedef LinkedListNode ExecutorListNode; +typedef LinkedList ExecutorList; + +class ExecutorNode { +public: + ExecutorNode(Command *command); + ~ExecutorNode(); + + Command *command; + ExecutorListNode *node; + ExecutorListNode *runNode; +}; + +ExecutorNode::ExecutorNode(Command *command) +: command(command), + node(new ExecutorListNode(this)), + runNode(new ExecutorListNode(this)) +{} + +ExecutorNode::~ExecutorNode() +{ + delete node; + delete runNode; +} + +ConstructDestructCallback *Executor::getConstructDestructCallback() +{ + init(); + return pConstructDestructCallback; +} + +class ExecutorPvt : public RunnableReady { +public: + ExecutorPvt(String threadName,ThreadPriority priority); + ~ExecutorPvt(); + ExecutorNode * createNode(Command *command); + void execute(ExecutorNode *node); + void destroy(); + virtual void run(ThreadReady *threadReady); +private: + ExecutorList *executorList; + ExecutorList *runList; + Event *moreWork; + Event *stopped; + Mutex mutex; + volatile bool alive; + Thread *thread; +}; + +ExecutorPvt::ExecutorPvt(String threadName,ThreadPriority priority) +: executorList(new ExecutorList()), + runList(new ExecutorList()), + moreWork(new Event(eventEmpty)), + stopped(new Event(eventEmpty)), + mutex(Mutex()), + alive(true), + thread(new Thread(threadName,priority,this)) +{ + thread->start(); +} + +ExecutorPvt::~ExecutorPvt() +{ + ExecutorListNode *node; + while((node=executorList->removeHead())!=0) { + delete node->getObject(); + } + delete stopped; + delete moreWork; + delete runList; + delete executorList; + delete thread; +} + +void ExecutorPvt::run(ThreadReady *threadReady) +{ + bool firstTime = true; + while(alive) { + ExecutorListNode * executorListNode = 0; + if(firstTime) { + firstTime = false; + threadReady->ready(); + } + while(alive && runList->isEmpty()) { + moreWork->wait(); + } + if(alive) { + Lock xx(&mutex); + executorListNode = runList->removeHead(); + } + if(alive && executorListNode!=0) { + executorListNode->getObject()->command->command(); + } + } + stopped->signal(); +} + +ExecutorNode * ExecutorPvt::createNode(Command *command) +{ + Lock xx(&mutex); + ExecutorNode *executorNode = new ExecutorNode(command); + executorList->addTail(executorNode->node); + return executorNode; +} + +void ExecutorPvt::execute(ExecutorNode *node) +{ + Lock xx(&mutex); + if(!alive || node->runNode->isOnList()) return; + bool isEmpty = runList->isEmpty(); + runList->addTail(node->runNode); + if(isEmpty) moreWork->signal(); +} + +void ExecutorPvt::destroy() +{ + { + Lock xx(&mutex); + alive = false; + } + moreWork->signal(); + { + Lock xx(&mutex); + stopped->wait(); + } + delete this; +} + +Executor::Executor(String threadName,ThreadPriority priority) +: pImpl(new ExecutorPvt(threadName,priority)) +{ + init(); + Lock xx(globalMutex); + totalConstruct++; +} + +Executor::~Executor() { + Lock xx(globalMutex); + totalDestruct++; +} + + +ExecutorNode * Executor::createNode(Command*command) +{return pImpl->createNode(command);} + +void Executor::execute(ExecutorNode *node) {pImpl->execute(node);} +void Executor::destroy() { + pImpl->destroy(); + delete this; +} + + +}} diff --git a/pvDataApp/misc/executor.h b/pvDataApp/misc/executor.h new file mode 100644 index 0000000..bb4be4a --- /dev/null +++ b/pvDataApp/misc/executor.h @@ -0,0 +1,33 @@ +/* executor.h */ +#ifndef EXECUTOR_H +#define EXECUTOR_H +#include +#include +#include "noDefaultMethods.h" +#include "pvType.h" +#include "thread.h" + +namespace epics { namespace pvData { + +// This is created by Executor.createNode and passed to Executor.execute +class ExecutorNode; + +class Command { +public: + virtual void command() = 0; +}; + +class Executor : private NoDefaultMethods { +public: + Executor(String threadName,ThreadPriority priority); + static ConstructDestructCallback *getConstructDestructCallback(); + ExecutorNode * createNode(Command *command); + void execute(ExecutorNode *node); + void destroy(); +private: + ~Executor(); + class ExecutorPvt *pImpl; +}; + +}} +#endif /* EXECUTOR_H */ diff --git a/pvDataApp/misc/linkedListVoid.cpp b/pvDataApp/misc/linkedListVoid.cpp index 6840850..22b32aa 100644 --- a/pvDataApp/misc/linkedListVoid.cpp +++ b/pvDataApp/misc/linkedListVoid.cpp @@ -19,41 +19,97 @@ static volatile int64 totalListDestruct = 0; static Mutex *globalMutex = 0; static String alreadyOnList("already on list"); -int64 LinkedListVoidNode::getTotalConstruct() +class CDCallbackLinkedListNode : public ConstructDestructCallback { +public: + CDCallbackLinkedListNode(); + virtual String getConstructName(); + virtual int64 getTotalConstruct(); + virtual int64 getTotalDestruct(); + virtual int64 getTotalReferenceCount(); +private: + String name; +}; + +CDCallbackLinkedListNode::CDCallbackLinkedListNode() +: name("linkedListNode") +{ + getShowConstructDestruct()->registerCallback(this); +} + +String CDCallbackLinkedListNode::getConstructName() {return name;} + +int64 CDCallbackLinkedListNode::getTotalConstruct() { Lock xx(globalMutex); return totalNodeConstruct; } -int64 LinkedListVoidNode::getTotalDestruct() +int64 CDCallbackLinkedListNode::getTotalDestruct() { Lock xx(globalMutex); return totalNodeDestruct; } -int64 LinkedListVoid::getTotalConstruct() +int64 CDCallbackLinkedListNode::getTotalReferenceCount() { - Lock xx(globalMutex); - return totalListConstruct; + return 0; } -int64 LinkedListVoid::getTotalDestruct() -{ - Lock xx(globalMutex); - return totalListDestruct; +class CDCallbackLinkedList : public ConstructDestructCallback { +public: + CDCallbackLinkedList(); + virtual String getConstructName(); + virtual int64 getTotalConstruct(); + virtual int64 getTotalDestruct(); + virtual int64 getTotalReferenceCount(); +private: + String name; +}; + +CDCallbackLinkedList::CDCallbackLinkedList() +: name("linkedList") +{ + getShowConstructDestruct()->registerCallback(this); } +String CDCallbackLinkedList::getConstructName() {return name;} -void LinkedListVoid::init() { +int64 CDCallbackLinkedList::getTotalConstruct() +{ + Lock xx(globalMutex); + return totalNodeConstruct; +} + +int64 CDCallbackLinkedList::getTotalDestruct() +{ + Lock xx(globalMutex); + return totalNodeDestruct; +} + +int64 CDCallbackLinkedList::getTotalReferenceCount() +{ + return 0; +} + +static ConstructDestructCallback *pCDCallbackLinkedListNode; +static ConstructDestructCallback *pCDCallbackLinkedList; + +static void initPvt() +{ static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) globalMutex = new Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { + globalMutex = new Mutex(); + pCDCallbackLinkedListNode = new CDCallbackLinkedListNode(); + pCDCallbackLinkedList = new CDCallbackLinkedList(); + } } + LinkedListVoidNode::LinkedListVoidNode(void *object) : object(object),before(0),after(0) { - LinkedListVoid::init(); + initPvt(); Lock xx(globalMutex); totalNodeConstruct++; } @@ -61,17 +117,24 @@ LinkedListVoidNode::LinkedListVoidNode(void *object) LinkedListVoidNode::LinkedListVoidNode(bool isHead) : object(this),before(this),after(this) { - LinkedListVoid::init(); + initPvt(); Lock xx(globalMutex); totalNodeConstruct++; } + LinkedListVoidNode::~LinkedListVoidNode() { Lock xx(globalMutex); totalNodeDestruct++; } +ConstructDestructCallback *LinkedListVoidNode::getConstructDestructCallback() +{ + initPvt(); + return pCDCallbackLinkedListNode; +} + void *LinkedListVoidNode::getObject() { return object; } @@ -85,7 +148,7 @@ bool LinkedListVoidNode::isOnList() LinkedListVoid::LinkedListVoid() : head(new LinkedListVoidNode(true)),length(0) { - LinkedListVoid::init(); + initPvt(); Lock xx(globalMutex); totalListConstruct++; } @@ -97,6 +160,12 @@ LinkedListVoid::~LinkedListVoid() totalListDestruct++; } +ConstructDestructCallback *LinkedListVoid::getConstructDestructCallback() +{ + initPvt(); + return pCDCallbackLinkedList; +} + int LinkedListVoid::getLength() { return length; diff --git a/pvDataApp/misc/linkedListVoid.h b/pvDataApp/misc/linkedListVoid.h index e37e56d..3bedef2 100644 --- a/pvDataApp/misc/linkedListVoid.h +++ b/pvDataApp/misc/linkedListVoid.h @@ -1,6 +1,7 @@ /* linkedListVoid.h */ #include "pvType.h" +#include "showConstructDestruct.h" #ifndef LINKEDLISTVOID_H #define LINKEDLISTVOID_H namespace epics { namespace pvData { @@ -11,8 +12,7 @@ class LinkedListVoidNode; class LinkedListVoidNode { public: ~LinkedListVoidNode(); - static int64 getTotalConstruct(); - static int64 getTotalDestruct(); + static ConstructDestructCallback *getConstructDestructCallback(); void *getObject(); bool isOnList(); protected: @@ -31,8 +31,7 @@ private: class LinkedListVoid { public: ~LinkedListVoid(); - static int64 getTotalConstruct(); - static int64 getTotalDestruct(); + static ConstructDestructCallback *getConstructDestructCallback(); int getLength(); void addTail(LinkedListVoidNode *listNode); void addHead(LinkedListVoidNode *listNode); @@ -53,7 +52,6 @@ public: protected: LinkedListVoid(); private: - static void init(); friend class LinkedListVoidNode; LinkedListVoidNode *head; int length; diff --git a/pvDataApp/misc/lock.h b/pvDataApp/misc/lock.h index d362d1f..1e44562 100644 --- a/pvDataApp/misc/lock.h +++ b/pvDataApp/misc/lock.h @@ -11,12 +11,12 @@ namespace epics { namespace pvData { class Mutex { public: - Mutex() : lockPtr(new epicsMutex()){} - ~Mutex() { delete lockPtr;}; - void lock(){lockPtr->lock();}\ - void unlock(){lockPtr->unlock();} + Mutex() : id(epicsMutexMustCreate()){} + ~Mutex() { epicsMutexDestroy(id) ;}; + void lock(){epicsMutexMustLock(id);}\ + void unlock(){epicsMutexUnlock(id);} private: - epicsMutex *lockPtr; + epicsMutexId id; }; diff --git a/pvDataApp/misc/showConstructDestruct.cpp b/pvDataApp/misc/showConstructDestruct.cpp new file mode 100644 index 0000000..5482f83 --- /dev/null +++ b/pvDataApp/misc/showConstructDestruct.cpp @@ -0,0 +1,61 @@ +/* showConstructDestruct.cpp */ +#include +#include +#include +#include +#include + +#include "noDefaultMethods.h" +#include "lock.h" +#include "pvType.h" +#include "linkedList.h" +#include "showConstructDestruct.h" + +namespace epics { namespace pvData { + +static ShowConstructDestruct *pShowConstructDestruct = 0; +static Mutex *globalMutex = 0; +typedef LinkedListNode ListNode; +typedef LinkedList List; +static List *list; + +ShowConstructDestruct::ShowConstructDestruct() {} + +void ShowConstructDestruct::constuctDestructTotals(FILE *fd) +{ + Lock xx(globalMutex); + ListNode *node = list->getHead(); + while(node!=0) { + ConstructDestructCallback *callback = node->getObject(); + String name = callback->getConstructName(); + int64 reference = callback->getTotalReferenceCount(); + int64 construct = callback->getTotalConstruct(); + int64 destruct = callback->getTotalDestruct(); + fprintf(fd,"%s: totalConstruct %lli totalDestruct %lli", + name.c_str(),construct,destruct); + if(reference>0) fprintf(fd," totalReference %lli",reference); + fprintf(fd,"\n"); + node = list->getNext(node); + } +} + +void ShowConstructDestruct::registerCallback(ConstructDestructCallback *callback) +{ + Lock xx(globalMutex); + ListNode *listNode = new ListNode(callback); + list->addTail(listNode); +} + +ShowConstructDestruct * getShowConstructDestruct() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(pShowConstructDestruct==0) { + globalMutex = new Mutex(); + list = new List(); + pShowConstructDestruct = new ShowConstructDestruct(); + } + return pShowConstructDestruct; +} + +}} diff --git a/pvDataApp/misc/showConstructDestruct.h b/pvDataApp/misc/showConstructDestruct.h new file mode 100644 index 0000000..9640248 --- /dev/null +++ b/pvDataApp/misc/showConstructDestruct.h @@ -0,0 +1,35 @@ +/* showConstructDestruct.h */ +#ifndef SHOWCONSTRUCTDESTRUCT_H +#define SHOWCONSTRUCTDESTRUCT_H +#include +#include +#include +#include +#include + +#include "noDefaultMethods.h" +#include "pvType.h" + +namespace epics { namespace pvData { + +class ConstructDestructCallback { +public: + virtual String getConstructName() = 0; + virtual int64 getTotalConstruct() = 0; + virtual int64 getTotalDestruct() = 0; + virtual int64 getTotalReferenceCount() = 0; +}; + +class ShowConstructDestruct : private NoDefaultMethods { +public: + static void constuctDestructTotals(FILE *fd); + static void registerCallback(ConstructDestructCallback *callback); +private: + ShowConstructDestruct(); + friend ShowConstructDestruct* getShowConstructDestruct(); +}; + +extern ShowConstructDestruct* getShowConstructDestruct(); + +}} +#endif /* SHOWCONSTRUCTDESTRUCT_H */ diff --git a/pvDataApp/misc/thread.cpp b/pvDataApp/misc/thread.cpp new file mode 100644 index 0000000..01d6742 --- /dev/null +++ b/pvDataApp/misc/thread.cpp @@ -0,0 +1,255 @@ +/* thread.cpp */ +#include +#include +#include +#include +#include + +#include +#include +#include "lock.h" +#include "event.h" +#include "thread.h" +#include "linkedList.h" + +namespace epics { namespace pvData { + +static unsigned int epicsPriority[] = { + epicsThreadPriorityLow, + epicsThreadPriorityLow + 15, + epicsThreadPriorityMedium - 15, + epicsThreadPriorityMedium, + epicsThreadPriorityMedium + 15, + epicsThreadPriorityHigh - 15, + epicsThreadPriorityHigh +}; + +unsigned int const * const ThreadPriorityFunc::getEpicsPriorities() +{ + return epicsPriority; +} + + +static String threadPriorityNames[] = { + String("lowest"),String("lower"),String("low"), + String("middle"), + String("high"),String("higher"),String("highest") +}; + +class ThreadListElement; +typedef LinkedListNode ThreadListNode; +typedef LinkedList ThreadList; + +static volatile int64 totalConstruct = 0; +static volatile int64 totalDestruct = 0; +static Mutex *globalMutex = 0; +static void addThread(Thread *thread); +static void removeThread(Thread *thread); +static ThreadList *list; + +class ConstructDestructCallbackThread : public ConstructDestructCallback { +public: + ConstructDestructCallbackThread(); + virtual String getConstructName(); + virtual int64 getTotalConstruct(); + virtual int64 getTotalDestruct(); + virtual int64 getTotalReferenceCount(); +private: + String name; +}; + +ConstructDestructCallbackThread::ConstructDestructCallbackThread() +: name("thread") +{ + getShowConstructDestruct()->registerCallback(this); +} + +String ConstructDestructCallbackThread::getConstructName() {return name;} + +int64 ConstructDestructCallbackThread::getTotalConstruct() +{ + Lock xx(globalMutex); + return totalConstruct; +} + +int64 ConstructDestructCallbackThread::getTotalDestruct() +{ + Lock xx(globalMutex); + return totalDestruct; +} + +int64 ConstructDestructCallbackThread::getTotalReferenceCount() +{ + return 0; +} + +static ConstructDestructCallback *pConstructDestructCallback; + +static void init() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { + globalMutex = new Mutex(); + list = new ThreadList(); + pConstructDestructCallback = new ConstructDestructCallbackThread(); + } +} + + +class ThreadListElement { +public: + ThreadListElement(Thread *thread) : thread(thread),node(new ThreadListNode(this)){} + ~ThreadListElement(){delete node;} + Thread *thread; + ThreadListNode *node; +}; + + +int ThreadPriorityFunc::getEpicsPriority(ThreadPriority threadPriority) { + return epicsPriority[threadPriority]; +} + +extern "C" void myFunc ( void * pPvt ); + + +class Runnable : public ThreadReady { +public: + Runnable(Thread *thread,String name, + ThreadPriority priority, RunnableReady *runnable); + virtual ~Runnable(); + Thread *start(); + void ready(); +public: // only used within this source module + Thread *thread; + String name; + ThreadPriority priority; + RunnableReady *runnable; + Event waitStart; + bool isReady; + epicsThreadId id; +}; + +extern "C" void myFunc ( void * pPvt ) +{ + Runnable *runnable = (Runnable *)pPvt; + runnable->waitStart.signal(); + addThread(runnable->thread); + runnable->runnable->run(runnable); + removeThread(runnable->thread); +} + +Runnable::Runnable(Thread *thread,String name, + ThreadPriority priority, RunnableReady *runnable) +: thread(thread),name(name),priority(priority), + runnable(runnable), + waitStart(eventEmpty), + isReady(false), + id(epicsThreadCreate( + name.c_str(), + epicsPriority[priority], + epicsThreadGetStackSize(epicsThreadStackSmall), + myFunc,this)) +{ + init(); + Lock xx(globalMutex); + totalConstruct++; +} + +Runnable::~Runnable() +{ + Lock xx(globalMutex); + totalDestruct++; +} + + +Thread * Runnable::start() +{ + if(!waitStart.wait(10.0)) { + fprintf(stderr,"thread %s did not call ready\n",thread->getName().c_str()); + } + return thread; +} + + +void Runnable::ready() +{ + waitStart.signal(); +} + +Thread::Thread(String name,ThreadPriority priority,RunnableReady *runnableReady) +: pImpl(new Runnable(this,name,priority,runnableReady)) +{ +} + +Thread::~Thread() +{ + delete pImpl; +} + +ConstructDestructCallback *Thread::getConstructDestructCallback() +{ + init(); + return pConstructDestructCallback; +} + +void Thread::start() +{ + pImpl->start(); +} + + +void Thread::sleep(double seconds) +{ + epicsThreadSleep(seconds);; +} + +String Thread::getName() +{ + return pImpl->name; +} + +ThreadPriority Thread::getPriority() +{ + return pImpl->priority; +} + +void Thread::showThreads(StringBuilder buf) +{ + init(); + Lock xx(globalMutex); + ThreadListNode *node = list->getHead(); + while(node!=0) { + Thread *thread = node->getObject()->thread; + *buf += thread->getName(); + *buf += " "; + *buf += threadPriorityNames[thread->getPriority()]; + *buf += "\n"; + node = list->getNext(node); + } +} + +void addThread(Thread *thread) +{ + Lock xx(globalMutex); + ThreadListElement *element = new ThreadListElement(thread); + list->addTail(element->node); +} + +void removeThread(Thread *thread) +{ + Lock xx(globalMutex); + ThreadListNode *node = list->getHead(); + while(node!=0) { + if(node->getObject()->thread==thread) { + list->remove(node); + delete node; + return; + } + node = list->getNext(node); + } + fprintf(stderr,"removeThread but thread %s did not in list\n", + thread->getName().c_str()); +} + +}} diff --git a/pvDataApp/misc/thread.h b/pvDataApp/misc/thread.h new file mode 100644 index 0000000..7351729 --- /dev/null +++ b/pvDataApp/misc/thread.h @@ -0,0 +1,54 @@ +/* thread.h */ +#ifndef THREAD_H +#define THREAD_H +#include "noDefaultMethods.h" +#include "pvType.h" + +namespace epics { namespace pvData { + +enum ThreadPriority { + lowestPriority, + lowerPriority, + lowPriority, + middlePriority, + highPriority, + higherPriority, + highestPriority +}; + +class ThreadPriorityFunc { +public: + static unsigned int const * const getEpicsPriorities(); + static int getEpicsPriority(ThreadPriority threadPriority); +}; + + +class ThreadReady { +public: + virtual void ready() = 0; +}; + +class RunnableReady { +public: + virtual void run(ThreadReady *threadReady) = 0; +}; + +class Thread; + +class Thread : private NoDefaultMethods { +public: + Thread(String name,ThreadPriority priority,RunnableReady *runnableReady); + ~Thread(); + static ConstructDestructCallback *getConstructDestructCallback(); + void start(); + String getName(); + ThreadPriority getPriority(); + static void showThreads(StringBuilder buf); + static void sleep(double seconds); +private: + class Runnable *pImpl; + friend class Runnable; +}; + +}} +#endif /* THREAD_H */ diff --git a/pvDataApp/misc/timeFunction.cpp b/pvDataApp/misc/timeFunction.cpp new file mode 100644 index 0000000..0dd8846 --- /dev/null +++ b/pvDataApp/misc/timeFunction.cpp @@ -0,0 +1,49 @@ +/* timeFunction.cpp */ +#include "noDefaultMethods.h" +#include "pvType.h" +#include "timeStamp.h" + +namespace epics { namespace pvData { + +class TimeFunctionRequester { +public: + virtual void function() = 0; +}; + +class TimeFunction : private NoDefaultMethods { +public: + TimeFunction(TimeFunctionRequester *requester); + ~TimeFunction(); + double timeCall(); +private: + TimeFunctionRequester *requester; +}; + +TimeFunction::TimeFunction(TimeFunctionRequester *requester) +: requester(requester) {} + + +TimeFunction::~TimeFunction() {} + +double TimeFunction::timeCall() +{ + TimeStamp startTime(0,0); + TimeStamp endTime(0,0); + double perCall = 0.0; + long ntimes = 1; + while(true) { + startTime.getCurrent(); + for(long i=0; ifunction(); + endTime.getCurrent(); + double diff = TimeStamp::diffInSeconds(&endTime,&startTime); + if(diff>=1.0) { + perCall = diff/(double)ntimes; + break; + } + ntimes *= 2; + } + return perCall; + +} + +}} diff --git a/pvDataApp/misc/timeFunction.h b/pvDataApp/misc/timeFunction.h new file mode 100644 index 0000000..29c77b2 --- /dev/null +++ b/pvDataApp/misc/timeFunction.h @@ -0,0 +1,25 @@ +/* timeFunction.h */ +#ifndef TIMEFUNCTION_H +#define TIMEFUNCTION_H +#include "noDefaultMethods.h" +#include "pvType.h" + +namespace epics { namespace pvData { + +class TimeFunctionRequester { +public: + virtual void function() = 0; +}; + +class TimeFunction : private NoDefaultMethods { +public: + TimeFunction(TimeFunctionRequester *requester); + ~TimeFunction(); + double timeCall(); +private: + TimeFunctionRequester *requester; +}; + + +}} +#endif /* TIMEFUNCTION_H */ diff --git a/pvDataApp/misc/timeStamp.cpp b/pvDataApp/misc/timeStamp.cpp new file mode 100644 index 0000000..7fe8746 --- /dev/null +++ b/pvDataApp/misc/timeStamp.cpp @@ -0,0 +1,58 @@ +/* timeStamp.cpp */ +#include +#include "noDefaultMethods.h" +#include "pvType.h" +#include "timeStamp.h" + +namespace epics { namespace pvData { + +static uint64 TS_EPOCH_SEC_PAST_1970=7305*86400; + +TimeStamp::TimeStamp(uint64 secondsPastEpoch,uint32 nanoSeconds) +: secondsPastEpoch(secondsPastEpoch),nanoSeconds(nanoSeconds) +{} + +TimeStamp::~TimeStamp() {} + +int64 TimeStamp::getEpicsSecondsPastEpoch() +{ + return secondsPastEpoch - TS_EPOCH_SEC_PAST_1970; +} + +void TimeStamp::put(uint64 seconds,uint32 nano) +{ + secondsPastEpoch = seconds; + nanoSeconds = nano; +} + +void TimeStamp::getCurrent() +{ + epicsTimeStamp epicsTime; + epicsTimeGetCurrent(&epicsTime); + secondsPastEpoch = epicsTime.secPastEpoch; + secondsPastEpoch += TS_EPOCH_SEC_PAST_1970; + nanoSeconds = epicsTime.nsec; +} + +double TimeStamp::diffInSeconds(TimeStamp *left,TimeStamp *right) +{ + double diff = left->secondsPastEpoch - right->secondsPastEpoch; + int64 nano =left->nanoSeconds - right->nanoSeconds; + diff += ((double)nano)/1e9; + return diff; +} + +int64 TimeStamp::getMilliseconds() +{ + return secondsPastEpoch*1000 + nanoSeconds/1000000; +} + +void TimeStamp::put(int64 milliseconds) +{ + secondsPastEpoch = milliseconds/1000; + nanoSeconds = (milliseconds%1000)*1000000; +} + + + +}} diff --git a/pvDataApp/misc/timeStamp.h b/pvDataApp/misc/timeStamp.h new file mode 100644 index 0000000..0c767da --- /dev/null +++ b/pvDataApp/misc/timeStamp.h @@ -0,0 +1,29 @@ +/* timeStamp.h */ +#ifndef TIMESTAMP_H +#define TIMESTAMP_H +#include "noDefaultMethods.h" +#include "pvType.h" + +namespace epics { namespace pvData { + +class TimeStamp : private NoDefaultMethods { +public: + TimeStamp(uint64 secondsPastEpoch,uint32 nanoSeconds); + ~TimeStamp(); + int64 getSecondsPastEpoch(){return secondsPastEpoch;} + int32 getNanoSeconds() {return nanoSeconds;} + int64 getEpicsSecondsPastEpoch(); + void put(uint64 secondsPastEpoch,uint32 nanoSeconds); + void getCurrent(); + static double diffInSeconds(TimeStamp *left,TimeStamp *right); + // milliseconds since epoch + int64 getMilliseconds(); + void put(int64 milliseconds); +private: + int64 secondsPastEpoch; + int32 nanoSeconds; +}; + + +}} +#endif /* TIMESTAMP_H */ diff --git a/pvDataApp/miscTest/Makefile b/pvDataApp/miscTest/Makefile index 8835be7..340501a 100644 --- a/pvDataApp/miscTest/Makefile +++ b/pvDataApp/miscTest/Makefile @@ -6,6 +6,10 @@ PROD_HOST += testLinkedList testLinkedList_SRCS += testLinkedList.cpp testLinkedList_LIBS += pvMisc Com +PROD_HOST += testThread +testThread_SRCS += testThread.cpp +testThread_LIBS += pvMisc Com + PROD_HOST += testBitSet testBitSet_SRCS += testBitSet.cpp testBitSet_LIBS += pvMisc Com diff --git a/pvDataApp/miscTest/testLinkedList.cpp b/pvDataApp/miscTest/testLinkedList.cpp index 98cf849..022044f 100644 --- a/pvDataApp/miscTest/testLinkedList.cpp +++ b/pvDataApp/miscTest/testLinkedList.cpp @@ -1,9 +1,9 @@ /* - * * testLinkedList.cpp - * * - * * Created on: 2010.11 - * * Author: Marty Kraimer - * */ + * testLinkedList.cpp + * + * Created on: 2010.11 + * Author: Marty Kraimer + */ #include #include @@ -12,13 +12,12 @@ #include #include -#include #include #include "lock.h" +#include "timeStamp.h" #include "linkedList.h" -#include "pvIntrospect.h" -#include "pvData.h" +#include "showConstructDestruct.h" using namespace epics::pvData; @@ -271,8 +270,8 @@ static void testOrderedQueue(FILE * fd ) { } static void testTime(FILE *auxFd) { - epicsTimeStamp startTime; - epicsTimeStamp endTime; + TimeStamp startTime(0,0); + TimeStamp endTime(0,0); int numNodes = 1000; LinkedList *basicList = new BasicList(); @@ -282,15 +281,15 @@ static void testTime(FILE *auxFd) { } fprintf(auxFd,"\nTime test\n"); int ntimes = 1000; - epicsTimeGetCurrent(&startTime); + startTime.getCurrent(); for(int i=0; iaddTail(basics[j]->node); BasicListNode *basicNode = basicList->removeHead(); while(basicNode!=0) basicNode = basicList->removeHead(); } - epicsTimeGetCurrent(&endTime); - double diff = epicsTimeDiffInSeconds(&endTime,&startTime); - diff *= 1000.0; + endTime.getCurrent(); + double diff = TimeStamp::diffInSeconds(&endTime,&startTime); + diff /= 1000.0; fprintf(auxFd,"diff %f milliSeconds\n",diff); diff = diff/1000.0; // convert from milliseconds to seconds diff = diff/ntimes; // seconds per outer loop @@ -304,8 +303,8 @@ static void testTime(FILE *auxFd) { } static void testTimeLocked(FILE *auxFd) { - epicsTimeStamp startTime; - epicsTimeStamp endTime; + TimeStamp startTime(0,0); + TimeStamp endTime(0,0); Mutex *mutex = new Mutex(); int numNodes = 1000; @@ -316,7 +315,7 @@ static void testTimeLocked(FILE *auxFd) { } fprintf(auxFd,"\nTime test locked\n"); int ntimes = 1000; - epicsTimeGetCurrent(&startTime); + startTime.getCurrent(); for(int i=0; iremoveHead(); } } - epicsTimeGetCurrent(&endTime); - double diff = epicsTimeDiffInSeconds(&endTime,&startTime); + endTime.getCurrent(); + double diff = TimeStamp::diffInSeconds(&endTime,&startTime); diff *= 1000.0; fprintf(auxFd,"diff %f milliSeconds\n",diff); diff = diff/1000.0; // convert from milliseconds to seconds @@ -349,8 +348,8 @@ static void testTimeLocked(FILE *auxFd) { typedef std::list stdList; static void testArrayListTime(FILE *auxFd) { - epicsTimeStamp startTime; - epicsTimeStamp endTime; + TimeStamp startTime(0,0); + TimeStamp endTime(0,0); int numNodes = 1000; stdList basicList; @@ -360,7 +359,7 @@ static void testArrayListTime(FILE *auxFd) { } fprintf(auxFd,"\nTime ArrayList test\n"); int ntimes = 1000; - epicsTimeGetCurrent(&startTime); + startTime.getCurrent(); for(int i=0; i0) { @@ -368,8 +367,8 @@ static void testArrayListTime(FILE *auxFd) { basicList.pop_front(); } } - epicsTimeGetCurrent(&endTime); - double diff = epicsTimeDiffInSeconds(&endTime,&startTime); + endTime.getCurrent(); + double diff = TimeStamp::diffInSeconds(&endTime,&startTime); diff *= 1000.0; fprintf(auxFd,"diff %f milliSeconds\n",diff); diff = diff/1000.0; // convert from milliseconds to seconds @@ -382,8 +381,8 @@ static void testArrayListTime(FILE *auxFd) { } static void testArrayListTimeLocked(FILE *auxFd) { - epicsTimeStamp startTime; - epicsTimeStamp endTime; + TimeStamp startTime(0,0); + TimeStamp endTime(0,0); int numNodes = 1000; Mutex *mutex = new Mutex(); @@ -394,7 +393,7 @@ static void testArrayListTimeLocked(FILE *auxFd) { } fprintf(auxFd,"\nTime ArrayList test locked\n"); int ntimes = 1000; - epicsTimeGetCurrent(&startTime); + startTime.getCurrent(); for(int i=0; iconstuctDestructTotals(fd); return (0); } diff --git a/pvDataApp/miscTest/testThread.cpp b/pvDataApp/miscTest/testThread.cpp new file mode 100644 index 0000000..49d7836 --- /dev/null +++ b/pvDataApp/miscTest/testThread.cpp @@ -0,0 +1,115 @@ +/* + * testThread.cpp + * + * Created on: 2010.11 + * Author: Marty Kraimer + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "event.h" +#include "thread.h" +#include "executor.h" +#include "showConstructDestruct.h" +#include "timeFunction.h" + +using namespace epics::pvData; + + +class Basic : public Command { +public: + Basic(Executor *executor); + ~Basic(); + void run(); + virtual void command(); +private: + Executor *executor; + ExecutorNode *executorNode; + Event *wait; +}; + +Basic::Basic(Executor *executor) +: executor(executor), + executorNode(executor->createNode(this)), + wait(new Event(eventEmpty)) +{ +} + +Basic::~Basic() { + delete wait; +} + +void Basic::run() +{ + executor->execute(executorNode); + bool result = wait->wait(); + if(result==false) printf("basic::run wait returned true\n"); +} + +void Basic::command() +{ + wait->signal(); +} + + +static void testBasic(FILE *fd) { + Executor *executor = new Executor(String("basic"),middlePriority); + Basic *basic = new Basic(executor); + basic->run(); + delete basic; + String buf(""); + Thread::showThreads(&buf); + fprintf(fd,"threads\n%s\n",buf.c_str()); + executor->destroy(); +} + +class MyFunc : public TimeFunctionRequester { +public: + MyFunc(Basic *basic) + : basic(basic) + {} + virtual void function() + { + basic->run(); + } +private: + Basic *basic; +}; + +static void testThreadContext(FILE *fd,FILE *auxFd) { + Executor *executor = new Executor(String("basic"),middlePriority); + Basic *basic = new Basic(executor); + MyFunc myFunc(basic); + TimeFunction timeFunction(&myFunc); + double perCall = timeFunction.timeCall(); + perCall *= 1e6; + fprintf(auxFd,"time per call %f microseconds\n",perCall); + delete basic; + executor->destroy(); +} + +int main(int argc, char *argv[]) { + char *fileName = 0; + if(argc>1) 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); + testThreadContext(fd,auxFd); + getShowConstructDestruct()->constuctDestructTotals(fd); + return (0); +} diff --git a/pvDataApp/property/Makefile b/pvDataApp/property/Makefile new file mode 100644 index 0000000..9cac164 --- /dev/null +++ b/pvDataApp/property/Makefile @@ -0,0 +1,16 @@ +TOP=../.. + +include $(TOP)/configure/CONFIG + +INC += enumerated.h + +LIBSRCS += enumerated.cpp +enumerated_LIBS += pvFactory pvMisc Com + +LIBRARY=pvProperty + + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/pvDataApp/property/enumerated.cpp b/pvDataApp/property/enumerated.cpp new file mode 100644 index 0000000..aeb1d4a --- /dev/null +++ b/pvDataApp/property/enumerated.cpp @@ -0,0 +1,62 @@ +/* enumerated.cpp */ +#include +#include +#include "pvType.h" +#include "pvIntrospect.h" +#include "pvData.h" +#include "enumerated.h" +#include "noDefaultMethods.h" +namespace epics { namespace pvData { + + +static String notStructure("field is not a structure"); +static String notEqual2("structure does not have exactly two fields"); +static String badIndex("structure does not have field index of type int"); +static String badChoices("structure does not have field choices of type stringArray"); + +Enumerated* Enumerated::create(PVField *pvField){ + if(pvField->getField()->getType()!=structure) { + pvField->message(notStructure,errorMessage); + return 0; + } + PVStructure *pvStructure = (PVStructure*)pvField; + int numberFields = pvStructure->getNumberFields(); + if(numberFields!=2) { + pvField->message(notEqual2,errorMessage); + return 0; + } + PVFieldPtrArray pvFields = pvStructure->getPVFields(); + FieldConstPtrArray fields = pvStructure->getStructure()->getFields(); + FieldConstPtr field = fields[0]; + if(field->getFieldName().compare("index")!=0 || field->getType()!=scalar) { + pvField->message(badIndex,errorMessage); + return 0; + } + PVInt *pvInt = (PVInt *) pvFields[0]; + field = fields[1]; + if(field->getFieldName().compare("choices")!=0 || field->getType()!=scalarArray) { + pvField->message(badChoices,errorMessage); + return 0; + } + ScalarArrayConstPtr pscalarArray = (ScalarArrayConstPtr)field; + if(pscalarArray->getElementType()!=pvString) { + pvField->message(badChoices,errorMessage); + return 0; + } + PVStringArray *pvStringArray = (PVStringArray *) pvFields[1]; + return new Enumerated(pvStructure,pvInt,pvStringArray); +} + +Enumerated::~Enumerated() {} + +Enumerated::Enumerated( + PVStructure *pvStructure,PVInt *pvIndex,PVStringArray *pvChoices) +: pvStructure(pvStructure),pvIndex(pvIndex),pvChoices(pvChoices), + stringArrayData(StringArrayData()) {} + +String Enumerated::getChoice() { + pvChoices->get(0, pvChoices->getLength(), &stringArrayData); + return stringArrayData.data[pvIndex->get()]; +} + +}} diff --git a/pvDataApp/property/enumerated.h b/pvDataApp/property/enumerated.h new file mode 100644 index 0000000..49c807f --- /dev/null +++ b/pvDataApp/property/enumerated.h @@ -0,0 +1,29 @@ +/* enumerated.h */ +#include +#include +#ifndef ENUMERATED_H +#define ENUMERATED_H +#include "pvIntrospect.h" +#include "pvData.h" +#include "noDefaultMethods.h" +namespace epics { namespace pvData { + +class Enumerated : private NoDefaultMethods { +public: + static Enumerated* create(PVField *pvField); + ~Enumerated(); + PVInt *getIndex() { return pvIndex;} + String getChoice(); + PVStringArray *getChoices() { return pvChoices;} + PVStructure *getPV() { return pvStructure;} +private: + Enumerated(PVStructure *pvStructure, + PVInt *pvIndex,PVStringArray *pvChoices); + PVStructure *pvStructure; + PVInt *pvIndex; + PVStringArray *pvChoices; + StringArrayData stringArrayData; +}; + +}} +#endif /* ENUMERATED_H */ diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index 61262b7..acd54a2 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -9,6 +9,7 @@ #include "requester.h" #include "byteBuffer.h" #include "serialize.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { class PVAuxInfo; @@ -57,8 +58,7 @@ namespace epics { namespace pvData { public: PVAuxInfo(PVField *pvField); ~PVAuxInfo(); - static int64 getTotalConstruct(); - static int64 getTotalDestruct(); + static ConstructDestructCallback *getConstructDestructCallback(); PVField * getPVField(); PVScalar * createInfo(String key,ScalarType scalarType); PVScalarMap getInfos(); @@ -66,7 +66,6 @@ namespace epics { namespace pvData { void toString(StringBuilder buf); void toString(StringBuilder buf,int indentLevel); private: - static void init(); class PVAuxInfoPvt *pImpl; friend class PVDataCreate; }; @@ -76,11 +75,14 @@ namespace epics { namespace pvData { virtual void postPut() = 0; }; - class PVField : public Requester, public Serializable ,private NoDefaultMethods{ + class PVField + : public Requester, + public Serializable, + private NoDefaultMethods + { public: virtual ~PVField(); - static int64 getTotalConstruct(); - static int64 getTotalDestruct(); + static ConstructDestructCallback *getConstructDestructCallback(); String getRequesterName() ; virtual void message(String message,MessageType messageType) ; virtual void setRequester(Requester *prequester); @@ -107,7 +109,6 @@ namespace epics { namespace pvData { class PVFieldPvt *pImpl; static void computeOffset(PVField *pvField); static void computeOffset(PVField *pvField,int offset); - static void init(); friend class PVDataCreate; }; diff --git a/pvDataApp/pv/pvIntrospect.h b/pvDataApp/pv/pvIntrospect.h index df05c2b..8cf237c 100644 --- a/pvDataApp/pv/pvIntrospect.h +++ b/pvDataApp/pv/pvIntrospect.h @@ -5,6 +5,7 @@ #define PVINTROSPECT_H #include "noDefaultMethods.h" #include "pvType.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { class Field; @@ -52,13 +53,11 @@ namespace epics { namespace pvData { static void toString(StringBuilder buf,ScalarType scalarType); }; - class Field : private NoDefaultMethods { + class Field : private NoDefaultMethods { public: virtual ~Field(); Field(String fieldName,Type type); - static int getTotalReferenceCount(); - static int64 getTotalConstruct(); - static int64 getTotalDestruct(); + static ConstructDestructCallback *getConstructDestructCallback(); int getReferenceCount() const; String getFieldName() const; Type getType() const; @@ -124,7 +123,7 @@ namespace epics { namespace pvData { FieldConstPtrArray fields; }; - class FieldCreate { + class FieldCreate : NoDefaultMethods { public: FieldConstPtr create(String fieldName,FieldConstPtr field) const; ScalarConstPtr createScalar(String fieldName,ScalarType scalarType) const; diff --git a/pvDataApp/pv/standardField.h b/pvDataApp/pv/standardField.h index 4d26323..fa7f807 100644 --- a/pvDataApp/pv/standardField.h +++ b/pvDataApp/pv/standardField.h @@ -54,7 +54,7 @@ namespace epics { namespace pvData { StructureConstPtr doubleAlarm(); StructureConstPtr enumeratedAlarm(); private: - void init(); + static void init(); }; extern StandardField * getStandardField(); diff --git a/pvDataApp/pvTest/testIntrospect.cpp b/pvDataApp/pvTest/testIntrospect.cpp index a02d47c..302daeb 100644 --- a/pvDataApp/pvTest/testIntrospect.cpp +++ b/pvDataApp/pvTest/testIntrospect.cpp @@ -10,9 +10,11 @@ #include #include "requester.h" +#include "executor.h" #include "pvIntrospect.h" #include "pvData.h" #include "standardField.h" +#include "showConstructDestruct.h" using namespace epics::pvData; @@ -129,7 +131,6 @@ static void testStructureArray(FILE * fd) { int main(int argc,char *argv[]) { - int initialTotalReferences,finalTotalReferences; char *fileName = 0; if(argc>1) fileName = argv[1]; FILE * fd = stdout; @@ -139,34 +140,11 @@ int main(int argc,char *argv[]) fieldCreate = getFieldCreate(); pvDataCreate = getPVDataCreate(); standardField = getStandardField(); - initialTotalReferences = Field::getTotalReferenceCount(); testScalar(fd); - finalTotalReferences = Field::getTotalReferenceCount(); - assert(initialTotalReferences==finalTotalReferences); - initialTotalReferences = Field::getTotalReferenceCount(); testScalarArray(fd); - finalTotalReferences = Field::getTotalReferenceCount(); - assert(initialTotalReferences==finalTotalReferences); - initialTotalReferences = Field::getTotalReferenceCount(); testSimpleStructure(fd); - finalTotalReferences = Field::getTotalReferenceCount(); - assert(initialTotalReferences==finalTotalReferences); - initialTotalReferences = Field::getTotalReferenceCount(); testStructureArray(fd); - finalTotalReferences = Field::getTotalReferenceCount(); - assert(initialTotalReferences==finalTotalReferences); - initialTotalReferences = Field::getTotalReferenceCount(); - int64 totalConstruct = Field::getTotalConstruct(); - int64 totalDestruct = Field::getTotalDestruct(); - int totalReference = Field::getTotalReferenceCount(); - fprintf(fd,"Field: totalConstruct %lli totalDestruct %lli totalReferenceCount %i\n", - totalConstruct,totalDestruct,totalReference); - assert(totalConstruct==(totalDestruct+totalReference)); - totalConstruct = PVField::getTotalConstruct(); - totalDestruct = PVField::getTotalDestruct(); - fprintf(fd,"PVField: totalConstruct %lli totalDestruct %lli\n", - totalConstruct,totalDestruct); - assert(totalConstruct==totalDestruct); + getShowConstructDestruct()->constuctDestructTotals(fd); return(0); } diff --git a/pvDataApp/pvTest/testPVAuxInfo.cpp b/pvDataApp/pvTest/testPVAuxInfo.cpp index 74ef86a..86850d1 100644 --- a/pvDataApp/pvTest/testPVAuxInfo.cpp +++ b/pvDataApp/pvTest/testPVAuxInfo.cpp @@ -15,6 +15,7 @@ #include "convert.h" #include "standardField.h" #include "standardPVField.h" +#include "showConstructDestruct.h" using namespace epics::pvData; @@ -74,7 +75,6 @@ static void testPVAuxInfo(FILE * fd) { int main(int argc,char *argv[]) { - int initialTotalReferences,finalTotalReferences; char *fileName = 0; if(argc>1) fileName = argv[1]; FILE * fd = stdout; @@ -86,28 +86,8 @@ int main(int argc,char *argv[]) standardField = getStandardField(); standardPVField = getStandardPVField(); convert = getConvert(); - initialTotalReferences = Field::getTotalReferenceCount(); testPVAuxInfo(fd); - finalTotalReferences = Field::getTotalReferenceCount(); - fprintf(fd,"Field: initialTotalReferences %d finalTotalReferences %d\n", - initialTotalReferences,finalTotalReferences); - assert(initialTotalReferences==finalTotalReferences); - int64 totalConstruct = Field::getTotalConstruct(); - int64 totalDestruct = Field::getTotalDestruct(); - int totalReference = Field::getTotalReferenceCount(); - fprintf(fd,"Field: totalConstruct %lli totalDestruct %lli totalReferenceCount %i\n", - totalConstruct,totalDestruct,totalReference); - assert(totalConstruct==(totalDestruct+totalReference)); - totalConstruct = PVField::getTotalConstruct(); - totalDestruct = PVField::getTotalDestruct(); - fprintf(fd,"PVField: totalConstruct %lli totalDestruct %lli\n", - totalConstruct,totalDestruct); - assert(totalConstruct==totalDestruct); - totalConstruct = PVAuxInfo::getTotalConstruct(); - totalDestruct = PVAuxInfo::getTotalDestruct(); - fprintf(fd,"PVAuxInfo: totalConstruct %lli totalDestruct %lli\n", - totalConstruct,totalDestruct); - assert(totalConstruct==totalDestruct); + getShowConstructDestruct()->constuctDestructTotals(fd); return(0); } diff --git a/pvDataApp/pvTest/testPVData.cpp b/pvDataApp/pvTest/testPVData.cpp index b9d8498..3ed4ea1 100644 --- a/pvDataApp/pvTest/testPVData.cpp +++ b/pvDataApp/pvTest/testPVData.cpp @@ -15,6 +15,7 @@ #include "convert.h" #include "standardField.h" #include "standardPVField.h" +#include "showConstructDestruct.h" using namespace epics::pvData; @@ -247,7 +248,6 @@ static void testScalarArray(FILE * fd) { int main(int argc,char *argv[]) { - int initialTotalReferences,finalTotalReferences; char *fileName = 0; if(argc>1) fileName = argv[1]; FILE * fd = stdout; @@ -259,25 +259,9 @@ int main(int argc,char *argv[]) standardField = getStandardField(); standardPVField = getStandardPVField(); convert = getConvert(); - initialTotalReferences = Field::getTotalReferenceCount(); testPVScalar(fd); - finalTotalReferences = Field::getTotalReferenceCount(); - assert(initialTotalReferences==finalTotalReferences); - initialTotalReferences = Field::getTotalReferenceCount(); testScalarArray(fd); - finalTotalReferences = Field::getTotalReferenceCount(); - assert(initialTotalReferences==finalTotalReferences); - int64 totalConstruct = Field::getTotalConstruct(); - int64 totalDestruct = Field::getTotalDestruct(); - int totalReference = Field::getTotalReferenceCount(); - fprintf(fd,"Field: totalConstruct %lli totalDestruct %lli totalReferenceCount %i\n", - totalConstruct,totalDestruct,totalReference); - assert(totalConstruct==(totalDestruct+totalReference)); - totalConstruct = PVField::getTotalConstruct(); - totalDestruct = PVField::getTotalDestruct(); - fprintf(fd,"PVField: totalConstruct %lli totalDestruct %lli\n", - totalConstruct,totalDestruct); - assert(totalConstruct==totalDestruct); + getShowConstructDestruct()->constuctDestructTotals(fd); return(0); } diff --git a/pvDataApp/pvTest/testPVStructureArray.cpp b/pvDataApp/pvTest/testPVStructureArray.cpp index a873ff8..4ffa071 100644 --- a/pvDataApp/pvTest/testPVStructureArray.cpp +++ b/pvDataApp/pvTest/testPVStructureArray.cpp @@ -14,6 +14,7 @@ #include "pvData.h" #include "standardField.h" #include "standardPVField.h" +#include "showConstructDestruct.h" using namespace epics::pvData; @@ -69,17 +70,7 @@ int main(int argc,char *argv[]) standardField = getStandardField(); standardPVField = getStandardPVField(); testPowerSupplyArray(fd); - int64 totalConstruct = Field::getTotalConstruct(); - int64 totalDestruct = Field::getTotalDestruct(); - int totalReference = Field::getTotalReferenceCount(); - fprintf(fd,"Field: totalConstruct %lli totalDestruct %lli totalReferenceCount %i\n", - totalConstruct,totalDestruct,totalReference); - assert(totalConstruct==(totalDestruct+totalReference)); - totalConstruct = PVField::getTotalConstruct(); - totalDestruct = PVField::getTotalDestruct(); - fprintf(fd,"PVField: totalConstruct %lli totalDestruct %lli\n", - totalConstruct,totalDestruct); - assert(totalConstruct==totalDestruct); + getShowConstructDestruct()->constuctDestructTotals(fd); return(0); } diff --git a/pvDataApp/pvTest/testPVType.cpp b/pvDataApp/pvTest/testPVType.cpp index a4305da..7e02a7d 100644 --- a/pvDataApp/pvTest/testPVType.cpp +++ b/pvDataApp/pvTest/testPVType.cpp @@ -1,4 +1,4 @@ -/* testIntrospect.cpp */ +/* testPVType.cpp */ /* Author: Marty Kraimer Date: 2010.09 */ #include diff --git a/test/testIntrospect b/test/testIntrospect index d9943be..ae84a81 100644 --- a/test/testIntrospect +++ b/test/testIntrospect @@ -77,5 +77,5 @@ structure value structure timeStamp long secondsPastEpoch int nanoSeconds -Field: totalConstruct 156 totalDestruct 63 totalReferenceCount 93 -PVField: totalConstruct 55 totalDestruct 55 +field: totalConstruct 156 totalDestruct 63 totalReference 93 +pvField: totalConstruct 55 totalDestruct 55 diff --git a/test/testIntrospectGold b/test/testIntrospectGold index d9943be..ae84a81 100644 --- a/test/testIntrospectGold +++ b/test/testIntrospectGold @@ -77,5 +77,5 @@ structure value structure timeStamp long secondsPastEpoch int nanoSeconds -Field: totalConstruct 156 totalDestruct 63 totalReferenceCount 93 -PVField: totalConstruct 55 totalDestruct 55 +field: totalConstruct 156 totalDestruct 63 totalReference 93 +pvField: totalConstruct 55 totalDestruct 55 diff --git a/test/testLinkedList b/test/testLinkedList index 89316dc..68222d2 100644 --- a/test/testLinkedList +++ b/test/testLinkedList @@ -17,4 +17,5 @@ stack 4 3 2 1 0 Ordered Queue test list 0 1 2 3 4 -totalConstructList 8 totalDestructList 8 totalConstructListNode 4038 totalDestructListNode 4038 +linkedListNode: totalConstruct 4041 totalDestruct 4038 +linkedList: totalConstruct 4041 totalDestruct 4038 diff --git a/test/testLinkedListAux b/test/testLinkedListAux index d838e28..9135916 100644 --- a/test/testLinkedListAux +++ b/test/testLinkedListAux @@ -1,20 +1,20 @@ Time test -diff 23.646940 milliSeconds -time per iteration 23.646940 microseconds -time per addTail/removeHead 0.011823 microseconds +diff 0.000025 milliSeconds +time per iteration 0.000025 microseconds +time per addTail/removeHead 0.000000 microseconds Time test locked -diff 183.897825 milliSeconds -time per iteration 183.897825 microseconds -time per addTail/removeHead 0.091949 microseconds +diff 177.872050 milliSeconds +time per iteration 177.872050 microseconds +time per addTail/removeHead 0.088936 microseconds Time ArrayList test -diff 652.546057 milliSeconds -time per iteration 652.546057 microseconds -time per addTail/removeHead 0.326273 microseconds +diff 648.628783 milliSeconds +time per iteration 648.628783 microseconds +time per addTail/removeHead 0.324314 microseconds Time ArrayList test locked -diff 814.756660 milliSeconds -time per iteration 814.756660 microseconds -time per addTail/removeHead 0.407378 microseconds +diff 805.752571 milliSeconds +time per iteration 805.752571 microseconds +time per addTail/removeHead 0.402876 microseconds diff --git a/test/testLinkedListGold b/test/testLinkedListGold index 89316dc..68222d2 100644 --- a/test/testLinkedListGold +++ b/test/testLinkedListGold @@ -17,4 +17,5 @@ stack 4 3 2 1 0 Ordered Queue test list 0 1 2 3 4 -totalConstructList 8 totalDestructList 8 totalConstructListNode 4038 totalDestructListNode 4038 +linkedListNode: totalConstruct 4041 totalDestruct 4038 +linkedList: totalConstruct 4041 totalDestruct 4038 diff --git a/test/testPVAuxInfo b/test/testPVAuxInfo index f76fe81..533839c 100644 --- a/test/testPVAuxInfo +++ b/test/testPVAuxInfo @@ -33,7 +33,6 @@ units offset 11 next 12 number 1 limit offset 12 next 15 number 3 low offset 13 next 14 number 1 high offset 14 next 15 number 1 -Field: initialTotalReferences 93 finalTotalReferences 93 -Field: totalConstruct 111 totalDestruct 18 totalReferenceCount 93 -PVField: totalConstruct 17 totalDestruct 17 -PVAuxInfo: totalConstruct 1 totalDestruct 1 +field: totalConstruct 111 totalDestruct 18 totalReference 93 +pvField: totalConstruct 17 totalDestruct 17 +pvAuxInfo: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAuxInfoGold b/test/testPVAuxInfoGold index f76fe81..533839c 100644 --- a/test/testPVAuxInfoGold +++ b/test/testPVAuxInfoGold @@ -33,7 +33,6 @@ units offset 11 next 12 number 1 limit offset 12 next 15 number 3 low offset 13 next 14 number 1 high offset 14 next 15 number 1 -Field: initialTotalReferences 93 finalTotalReferences 93 -Field: totalConstruct 111 totalDestruct 18 totalReferenceCount 93 -PVField: totalConstruct 17 totalDestruct 17 -PVAuxInfo: totalConstruct 1 totalDestruct 1 +field: totalConstruct 111 totalDestruct 18 totalReference 93 +pvField: totalConstruct 17 totalDestruct 17 +pvAuxInfo: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVData b/test/testPVData index 68f74c8..ea8eb3d 100644 --- a/test/testPVData +++ b/test/testPVData @@ -281,5 +281,5 @@ structure string structure timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -Field: totalConstruct 388 totalDestruct 295 totalReferenceCount 93 -PVField: totalConstruct 279 totalDestruct 279 +field: totalConstruct 388 totalDestruct 295 totalReference 93 +pvField: totalConstruct 279 totalDestruct 279 diff --git a/test/testPVDataGold b/test/testPVDataGold index 68f74c8..ea8eb3d 100644 --- a/test/testPVDataGold +++ b/test/testPVDataGold @@ -281,5 +281,5 @@ structure string structure timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -Field: totalConstruct 388 totalDestruct 295 totalReferenceCount 93 -PVField: totalConstruct 279 totalDestruct 279 +field: totalConstruct 388 totalDestruct 295 totalReference 93 +pvField: totalConstruct 279 totalDestruct 279 diff --git a/test/testPVStructureArray b/test/testPVStructureArray index 722c326..2edafb6 100644 --- a/test/testPVStructureArray +++ b/test/testPVStructureArray @@ -56,5 +56,5 @@ structure powerSupply structure timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -Field: totalConstruct 153 totalDestruct 60 totalReferenceCount 93 -PVField: totalConstruct 56 totalDestruct 56 +field: totalConstruct 153 totalDestruct 60 totalReference 93 +pvField: totalConstruct 56 totalDestruct 56 diff --git a/test/testPVStructureArrayGold b/test/testPVStructureArrayGold index 722c326..2edafb6 100644 --- a/test/testPVStructureArrayGold +++ b/test/testPVStructureArrayGold @@ -56,5 +56,5 @@ structure powerSupply structure timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -Field: totalConstruct 153 totalDestruct 60 totalReferenceCount 93 -PVField: totalConstruct 56 totalDestruct 56 +field: totalConstruct 153 totalDestruct 60 totalReference 93 +pvField: totalConstruct 56 totalDestruct 56 diff --git a/test/testThread b/test/testThread new file mode 100644 index 0000000..6fd9ab7 --- /dev/null +++ b/test/testThread @@ -0,0 +1,8 @@ +threads +basic middle + +linkedListNode: totalConstruct 17 totalDestruct 10 +linkedList: totalConstruct 17 totalDestruct 10 +event: totalConstruct 8 totalDestruct 8 +thread: totalConstruct 2 totalDestruct 2 +executor: totalConstruct 2 totalDestruct 2 diff --git a/test/testThread.pl b/test/testThread.pl new file mode 100755 index 0000000..443b783 --- /dev/null +++ b/test/testThread.pl @@ -0,0 +1,12 @@ +eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*- + if $running_under_some_shell; # testThread.pl +use Env; +system ("rm testThread"); +system ("rm testThreadDiff"); +system ("../bin/${EPICS_HOST_ARCH}/testThread testThread testThreadAux"); +system ("diff testThread testThreadGold >> testThreadDiff"); +if(-z "testThreadDiff") { + print "testThread OK\n"; +} else { + print "testThread Failed\n"; +} diff --git a/test/testThreadAux b/test/testThreadAux new file mode 100644 index 0000000..b289f65 --- /dev/null +++ b/test/testThreadAux @@ -0,0 +1 @@ +time per call 25.290591 microseconds diff --git a/test/testThreadDiff b/test/testThreadDiff new file mode 100644 index 0000000..e69de29 diff --git a/test/testThreadGold b/test/testThreadGold new file mode 100644 index 0000000..6fd9ab7 --- /dev/null +++ b/test/testThreadGold @@ -0,0 +1,8 @@ +threads +basic middle + +linkedListNode: totalConstruct 17 totalDestruct 10 +linkedList: totalConstruct 17 totalDestruct 10 +event: totalConstruct 8 totalDestruct 8 +thread: totalConstruct 2 totalDestruct 2 +executor: totalConstruct 2 totalDestruct 2