diff --git a/documentation/pvDataCpp.html b/documentation/pvDataCpp.html index 0edca05..5e63a47 100644 --- a/documentation/pvDataCpp.html +++ b/documentation/pvDataCpp.html @@ -2906,7 +2906,7 @@ PVDataCreate.

Allows messages to be sent to a requester.
serialize.h
Support for serializing objects.
-
showConstructDestruct.h
+
CDRMonitor.h
Provides support monitoring memory usage for objects of a class.
status.h
A way to pass status information to a client.
diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index 8e3fcca..54de4b1 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -18,7 +18,7 @@ INC += serializeHelper.h INC += event.h INC += thread.h INC += executor.h -INC += showConstructDestruct.h +INC += CDRMonitor.h INC += timeFunction.h INC += timer.h INC += queueVoid.h @@ -27,7 +27,7 @@ INC += messageQueue.h INC += destroyable.h INC += status.h -LIBSRCS += showConstructDestruct.cpp +LIBSRCS += CDRMonitor.cpp LIBSRCS += byteBuffer.cpp LIBSRCS += bitSet.cpp LIBSRCS += requester.cpp diff --git a/pvDataApp/factory/FieldCreateFactory.cpp b/pvDataApp/factory/FieldCreateFactory.cpp index e74119b..e8164c4 100644 --- a/pvDataApp/factory/FieldCreateFactory.cpp +++ b/pvDataApp/factory/FieldCreateFactory.cpp @@ -12,7 +12,7 @@ #include "pvIntrospect.h" #include "convert.h" #include "factory.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { @@ -24,6 +24,8 @@ static void newLine(StringBuilder buffer, int indentLevel) for(int i=0; ifieldName.c_str()); delete pImpl; @@ -88,7 +55,7 @@ Field::~Field() { } int Field::getReferenceCount() const { - Lock xx(&globalMutex); + Lock xx(&refCountMutex); return pImpl->referenceCount; } @@ -102,9 +69,9 @@ void Field::renameField(String newName) } void Field::incReferenceCount() const { - Lock xx(&globalMutex); + field_node.incRef(); + Lock xx(&refCountMutex); pImpl->referenceCount++; - totalReferenceCount++; if(pImpl->type!=structure) return; StructureConstPtr structure = static_cast(this); FieldConstPtrArray fields = structure->getFields(); @@ -115,14 +82,14 @@ void Field::incReferenceCount() const { } void Field::decReferenceCount() const { - Lock xx(&globalMutex); + field_node.decRef(); + Lock xx(&refCountMutex); if(pImpl->referenceCount<=0) { String message("logicError field "); message += pImpl->fieldName; throw std::logic_error(message); } pImpl->referenceCount--; - totalReferenceCount--; if(pImpl->type!=structure) { if(pImpl->referenceCount==0) { delete this; @@ -435,7 +402,6 @@ static FieldCreate* fieldCreate = 0; FieldCreate::FieldCreate() { - init(); } FieldCreate * getFieldCreate() { diff --git a/pvDataApp/factory/PVAuxInfoImpl.cpp b/pvDataApp/factory/PVAuxInfoImpl.cpp index 0df4fff..57f9148 100644 --- a/pvDataApp/factory/PVAuxInfoImpl.cpp +++ b/pvDataApp/factory/PVAuxInfoImpl.cpp @@ -13,38 +13,11 @@ #include "convert.h" #include "factory.h" #include "lock.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { -static volatile int64 totalConstruct = 0; -static volatile int64 totalDestruct = 0; -static Mutex globalMutex; -static bool notInited = true; - -static int64 getTotalConstruct() -{ - Lock xx(&globalMutex); - return totalConstruct; -} - -static int64 getTotalDestruct() -{ - Lock xx(&globalMutex); - return totalDestruct; -} - -static void init() -{ - static Mutex mutex = Mutex(); - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - String("pvAuxInfo"), - getTotalConstruct,getTotalDestruct,0,0); - } -} +PVDATA_REFCOUNT_MONITOR_DEFINE(pvAuxInfo); typedef std::map::const_iterator map_iterator; @@ -61,14 +34,11 @@ public: PVAuxInfo::PVAuxInfo(PVField *pvField) : pImpl(new PVAuxInfoPvt(pvField)) { - init(); - Lock xx(&globalMutex); - totalConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(pvAuxInfo); } PVAuxInfo::~PVAuxInfo() { - Lock xx(&globalMutex); - totalDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(pvAuxInfo); map_iterator i = pImpl->theMap.begin(); while(i!=pImpl->theMap.end()) { PVScalar *value = i->second; diff --git a/pvDataApp/factory/PVField.cpp b/pvDataApp/factory/PVField.cpp index dc1c0bd..c7b66a9 100644 --- a/pvDataApp/factory/PVField.cpp +++ b/pvDataApp/factory/PVField.cpp @@ -8,41 +8,16 @@ #include #include #include +#include "lock.h" #include "pvData.h" #include "factory.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { static String notImplemented("not implemented"); -static volatile int64 totalConstruct = 0; -static volatile int64 totalDestruct = 0; -static Mutex globalMutex; -static bool notInited = true; - -static int64 getTotalConstruct() -{ - Lock xx(&globalMutex); - return totalConstruct; -} - -static int64 getTotalDestruct() -{ - Lock xx(&globalMutex); - return totalDestruct; -} - -static void init() -{ - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - String("pvField"), - getTotalConstruct,getTotalDestruct,0,0); - } -} +PVDATA_REFCOUNT_MONITOR_DEFINE(pvField); class PVFieldPvt { public: @@ -77,15 +52,12 @@ PVFieldPvt::~PVFieldPvt() PVField::PVField(PVStructure *parent,FieldConstPtr field) : pImpl(new PVFieldPvt(parent,field)) { - init(); - Lock xx(&globalMutex); - totalConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(pvField); } PVField::~PVField() { - Lock xx(&globalMutex); - totalDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(pvField); delete pImpl; } diff --git a/pvDataApp/factory/StandardField.cpp b/pvDataApp/factory/StandardField.cpp index 0289efb..4b422a9 100644 --- a/pvDataApp/factory/StandardField.cpp +++ b/pvDataApp/factory/StandardField.cpp @@ -7,15 +7,15 @@ #include #include #include +#include +#include #include #include "pvIntrospect.h" #include "standardField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { -static Mutex globalMutex; -static bool notInited = true; static StandardField* standardField = 0; static String notImplemented("not implemented"); @@ -462,7 +462,7 @@ StandardField::StandardField(){init();} StandardField::~StandardField(){ } -static void myDeleteStatic() +static void myDeleteStatic(void*) { int count = alarmField->getReferenceCount(); if(count!=1) printf("~StandardField() alarmField reference count %d\n",count); @@ -502,16 +502,18 @@ static void myDeleteStatic() enumeratedAlarmField->decReferenceCount(); } +static void myInitStatic(void*) +{ + standardField = new StandardField(); + fieldCreate = getFieldCreate(); + epicsAtExit(&myDeleteStatic,0); +} + +static +epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT; + StandardField * getStandardField() { - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - standardField = new StandardField(); - fieldCreate = getFieldCreate(); - ShowConstructDestruct::registerCallback( - "standardField", - 0,0,0,myDeleteStatic); - } + epicsThreadOnce(&myInitOnce,&myInitStatic,0); return standardField; } diff --git a/pvDataApp/factory/StandardPVField.cpp b/pvDataApp/factory/StandardPVField.cpp index a24cb20..1ba7cb1 100644 --- a/pvDataApp/factory/StandardPVField.cpp +++ b/pvDataApp/factory/StandardPVField.cpp @@ -6,18 +6,18 @@ */ #include #include +#include +#include #include #include "pvIntrospect.h" #include "pvData.h" #include "convert.h" #include "standardField.h" #include "standardPVField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { -static Mutex globalMutex; -static bool notInited = true; static StandardField *standardField = 0; static String notImplemented("not implemented"); @@ -329,23 +329,25 @@ public: StandardPVFieldExt(): StandardPVField(){}; }; -static void myDeleteStatic() +static void myDeleteStatic(void*) { delete standardPVField; } +static void myInitStatic(void*) +{ + fieldCreate = getFieldCreate(); + pvDataCreate = getPVDataCreate(); + standardField = getStandardField(); + standardPVField = new StandardPVFieldExt(); + epicsAtExit(&myDeleteStatic, 0); +} + +static +epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT; + StandardPVField * getStandardPVField() { - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - fieldCreate = getFieldCreate(); - pvDataCreate = getPVDataCreate(); - standardField = getStandardField(); - standardPVField = new StandardPVFieldExt(); - ShowConstructDestruct::registerCallback( - "standardPVField", - 0,0,0,myDeleteStatic); - } + epicsThreadOnce(&myInitOnce, &myInitStatic, 0); return standardPVField; } diff --git a/pvDataApp/misc/CDRMonitor.cpp b/pvDataApp/misc/CDRMonitor.cpp new file mode 100644 index 0000000..7d9c1a4 --- /dev/null +++ b/pvDataApp/misc/CDRMonitor.cpp @@ -0,0 +1,90 @@ +/* CDRMonitor.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 + +#include "noDefaultMethods.h" +#include "lock.h" +#include "pvType.h" +#include "linkedList.h" +#include "CDRMonitor.h" + +namespace epics { namespace pvData { + +static +epicsThreadOnceId monitorInit = EPICS_THREAD_ONCE_INIT; + +// Must use a pointer w/ lazy init due to lack of +// initialization order guarantees +CDRMonitor* CDRMonitor::theone = 0; + +CDRMonitor& +CDRMonitor::get() +{ + epicsThreadOnce(&monitorInit, &CDRMonitor::init, 0); + assert(theone); + return *theone; +} + +void +CDRMonitor::init(void *) +{ + //BUG: No idea how to handle allocation failure at this stage. + theone=new CDRMonitor; +} + +CDRMonitor::CDRMonitor() + :firstNode(0) +{} + +CDRCount +CDRMonitor::current() +{ + CDRCount total; + for(CDRNode *cur=first(); !!cur; cur=cur->next()) + { + total+=cur->get(); + } + return total; +} + +void +CDRMonitor::show(FILE *fd) +{ + for(CDRNode *cur=first(); !!cur; cur=cur->next()) + { + cur->show(fd); + } +} + +void +CDRNode::show(FILE *fd) +{ + Lock x(&guard); + if(!current.cons && !current.dtys && !current.refs) + return; + fprintf(fd,"%s: totalConstruct %lu totalDestruct %lu", + nodeName.c_str(), (unsigned long)current.cons, + (unsigned long)current.dtys); + ssize_t alive=current.cons; + alive-=current.dtys; + if(current.refs) + fprintf(fd," totalReference %ld", current.refs); + if(alive) + fprintf(fd," ACTIVE %ld\n", (long)alive); + else + fprintf(fd,"\n"); +} + + +}} diff --git a/pvDataApp/misc/CDRMonitor.h b/pvDataApp/misc/CDRMonitor.h new file mode 100644 index 0000000..cd3feb1 --- /dev/null +++ b/pvDataApp/misc/CDRMonitor.h @@ -0,0 +1,94 @@ +/* CDRMonitor.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 SHOWCONSTRUCTDESTRUCT_H +#define SHOWCONSTRUCTDESTRUCT_H +#include +#include +#include +#include +#include + +#include "noDefaultMethods.h" +#include "lock.h" +#include "pvType.h" + +namespace epics { namespace pvData { + +//! Used to pass around snapshots +struct CDRCount { // default copy and assignment are ok + size_t cons, dtys; + long refs; + CDRCount():cons(0),dtys(0),refs(0){} + CDRCount& operator+=(const CDRCount& o) + {cons+=o.cons; dtys+=o.dtys; refs+=o.refs; return *this;} + CDRCount& operator=(size_t count) // reset counters + {cons=count; dtys=count; refs=count; return *this;} +}; + +class CDRNode; + +//! @brief Global registrar for CDRNodes +class CDRMonitor : private NoDefaultMethods { +public: + static CDRMonitor& get(); + + CDRNode* addNode(CDRNode& next) + { + CDRNode *ret=firstNode; + firstNode=&next; + return ret; + } + + CDRCount current(); //!< current global count + + CDRNode* first(){return firstNode;} + + void show(FILE*); +private: + // Private ctor for singleton + CDRMonitor(); + CDRNode *firstNode; + + static CDRMonitor *theone; + static void init(void*); +}; + +//! Counters for Construction, Destruction, and References of one class +class CDRNode : private NoDefaultMethods { +public: + CDRNode(const String& name) + :nodeName(name) + ,current() + ,guard() + ,nextNode(CDRMonitor::get().addNode(*this)) + {} + void construct(){Lock x(&guard); current.cons++;} + void destruct(){Lock x(&guard); current.dtys++;} + void incRef(){Lock x(&guard); current.refs++;} + void decRef(){Lock x(&guard); current.refs--;} + + CDRNode* next() const{return nextNode;} + + CDRCount get() const{Lock x(&guard); return current;} + + void show(FILE*); +private: + const String nodeName; + CDRCount current; + mutable Mutex guard; + CDRNode * const nextNode; +}; + +#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME) static CDRNode NAME ## _node(#NAME) + +#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME) NAME ## _node.destruct() + +#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME) NAME ## _node.construct() + + +}} +#endif /* SHOWCONSTRUCTDESTRUCT_H */ diff --git a/pvDataApp/misc/StatusCreateFactory.cpp b/pvDataApp/misc/StatusCreateFactory.cpp index f78de6d..1df4157 100644 --- a/pvDataApp/misc/StatusCreateFactory.cpp +++ b/pvDataApp/misc/StatusCreateFactory.cpp @@ -11,7 +11,7 @@ #include "lock.h" #include "factory.h" #include "byteBuffer.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #include "status.h" #include "serializeHelper.h" diff --git a/pvDataApp/misc/bitSet.cpp b/pvDataApp/misc/bitSet.cpp index 83a81ca..353b42b 100644 --- a/pvDataApp/misc/bitSet.cpp +++ b/pvDataApp/misc/bitSet.cpp @@ -8,7 +8,7 @@ #include "stdio.h" #include "bitSet.h" #include "lock.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #include "serializeHelper.h" namespace epics { namespace pvData { diff --git a/pvDataApp/misc/event.cpp b/pvDataApp/misc/event.cpp index 52b5fa3..0ecb649 100644 --- a/pvDataApp/misc/event.cpp +++ b/pvDataApp/misc/event.cpp @@ -20,54 +20,24 @@ #include "pvType.h" #include "lock.h" #include "event.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { -static Mutex globalMutex; -static volatile int64 totalConstruct = 0; -static volatile int64 totalDestruct = 0; -static bool notInited = true; +PVDATA_REFCOUNT_MONITOR_DEFINE(event); static String alreadyOn("already on list"); - -static int64 getTotalConstruct() -{ - Lock xx(&globalMutex); - return totalConstruct; -} - -static int64 getTotalDestruct() -{ - Lock xx(&globalMutex); - return totalDestruct; -} - -static void init() -{ - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - String("event"), - getTotalConstruct,getTotalDestruct,0,0); - } -} - Event::~Event() { epicsEventDestroy(id); id = 0; - Lock xx(&globalMutex); - totalDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(event); } Event::Event(bool full) : id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty)) { - init(); - Lock xx(&globalMutex); - totalConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(event); } void Event::signal() diff --git a/pvDataApp/misc/executor.cpp b/pvDataApp/misc/executor.cpp index 7ec1e04..5e44b8d 100644 --- a/pvDataApp/misc/executor.cpp +++ b/pvDataApp/misc/executor.cpp @@ -17,37 +17,11 @@ #include "thread.h" #include "event.h" #include "executor.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { -static volatile int64 totalConstruct = 0; -static volatile int64 totalDestruct = 0; -static Mutex globalMutex; -static bool notInited = true; - -static int64 getTotalConstruct() -{ - Lock xx(&globalMutex); - return totalConstruct; -} - -static int64 getTotalDestruct() -{ - Lock xx(&globalMutex); - return totalDestruct; -} - -static void init() { - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - String("executor"), - getTotalConstruct,getTotalDestruct,0,0); - } -} - +PVDATA_REFCOUNT_MONITOR_DEFINE(executor); typedef LinkedListNode ExecutorListNode; typedef LinkedList ExecutorList; @@ -55,25 +29,18 @@ typedef LinkedList ExecutorList; class ExecutorNode { public: ExecutorNode(Command *command); - ~ExecutorNode(); Command *command; - ExecutorListNode *node; - ExecutorListNode *runNode; + ExecutorListNode node; + ExecutorListNode runNode; }; ExecutorNode::ExecutorNode(Command *command) : command(command), - node(new ExecutorListNode(this)), - runNode(new ExecutorListNode(this)) + node(this), + runNode(this) {} -ExecutorNode::~ExecutorNode() -{ - delete node; - delete runNode; -} - class ExecutorPvt : public Runnable{ public: ExecutorPvt(String threadName,ThreadPriority priority); @@ -82,23 +49,23 @@ public: void execute(ExecutorNode *node); virtual void run(); private: - ExecutorList *executorList; - ExecutorList *runList; - Event *moreWork; - Event *stopped; + ExecutorList executorList; + ExecutorList runList; + Event moreWork; + Event stopped; Mutex mutex; volatile bool alive; - Thread *thread; + Thread thread; }; ExecutorPvt::ExecutorPvt(String threadName,ThreadPriority priority) -: executorList(new ExecutorList()), - runList(new ExecutorList()), - moreWork(new Event(false)), - stopped(new Event(false)), - mutex(Mutex()), +: executorList(), + runList(), + moreWork(), + stopped(), + mutex(), alive(true), - thread(new Thread(threadName,priority,this)) + thread(threadName,priority,this) {} ExecutorPvt::~ExecutorPvt() @@ -107,69 +74,61 @@ ExecutorPvt::~ExecutorPvt() Lock xx(&mutex); alive = false; } - moreWork->signal(); + moreWork.signal(); { Lock xx(&mutex); - stopped->wait(); + stopped.wait(); } ExecutorListNode *node; - while((node=executorList->removeHead())!=0) { + while((node=executorList.removeHead())!=0) { delete node->getObject(); } - delete thread; - delete stopped; - delete moreWork; - delete runList; - delete executorList; } void ExecutorPvt::run() { while(alive) { ExecutorListNode * executorListNode = 0; - while(alive && runList->isEmpty()) { - moreWork->wait(); + while(alive && runList.isEmpty()) { + moreWork.wait(); } if(alive) { Lock xx(&mutex); - executorListNode = runList->removeHead(); + executorListNode = runList.removeHead(); } if(alive && executorListNode!=0) { executorListNode->getObject()->command->command(); } } - stopped->signal(); + stopped.signal(); } ExecutorNode * ExecutorPvt::createNode(Command *command) { Lock xx(&mutex); ExecutorNode *executorNode = new ExecutorNode(command); - executorList->addTail(executorNode->node); + 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(); + if(!alive || node->runNode.isOnList()) return; + bool isEmpty = runList.isEmpty(); + runList.addTail(&node->runNode); + if(isEmpty) moreWork.signal(); } Executor::Executor(String threadName,ThreadPriority priority) : pImpl(new ExecutorPvt(threadName,priority)) { - init(); - Lock xx(&globalMutex); - totalConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(executor); } Executor::~Executor() { delete pImpl; - Lock xx(&globalMutex); - totalDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(executor); } ExecutorNode * Executor::createNode(Command*command) diff --git a/pvDataApp/misc/linkedListVoid.cpp b/pvDataApp/misc/linkedListVoid.cpp index 7b1d6e4..a94c6b8 100644 --- a/pvDataApp/misc/linkedListVoid.cpp +++ b/pvDataApp/misc/linkedListVoid.cpp @@ -14,80 +14,31 @@ #include "lock.h" #include "pvType.h" #include "linkedListVoid.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { -static Mutex globalMutex; static String alreadyOnList("already on list"); -static volatile int64 totalNodeConstruct = 0; -static volatile int64 totalNodeDestruct = 0; -static volatile int64 totalListConstruct = 0; -static volatile int64 totalListDestruct = 0; -static bool notInited = true; - -static int64 getTotalNodeConstruct() -{ - Lock xx(&globalMutex); - return totalNodeConstruct; -} - -static int64 getTotalNodeDestruct() -{ - Lock xx(&globalMutex); - return totalNodeDestruct; -} - -static int64 getTotalListConstruct() -{ - Lock xx(&globalMutex); - return totalListConstruct; -} - -static int64 getTotalListDestruct() -{ - Lock xx(&globalMutex); - return totalListDestruct; -} - -static void initPvt() -{ - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - "linkedListNode", - getTotalNodeConstruct,getTotalNodeDestruct,0,0); - - ShowConstructDestruct::registerCallback( - "linkedList", - getTotalListConstruct,getTotalListDestruct,0,0); - } -} - +PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedListNode); +PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedList); LinkedListVoidNode::LinkedListVoidNode(void *object) : object(object),before(0),after(0),linkedListVoid(0) { - initPvt(); - Lock xx(&globalMutex); - totalNodeConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode); } LinkedListVoidNode::LinkedListVoidNode(bool isHead) : object(this),before(this),after(this) { - initPvt(); - Lock xx(&globalMutex); - totalNodeConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode); } LinkedListVoidNode::~LinkedListVoidNode() { - Lock xx(&globalMutex); - totalNodeDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedListNode); } void *LinkedListVoidNode::getObject() { @@ -103,16 +54,13 @@ bool LinkedListVoidNode::isOnList() LinkedListVoid::LinkedListVoid() : head(new LinkedListVoidNode(true)),length(0) { - initPvt(); - Lock xx(&globalMutex); - totalListConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedList); } LinkedListVoid::~LinkedListVoid() { - Lock xx(&globalMutex); delete head; - totalListDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedList); } int LinkedListVoid::getLength() diff --git a/pvDataApp/misc/lock.h b/pvDataApp/misc/lock.h index 70e7a2d..485dc84 100644 --- a/pvDataApp/misc/lock.h +++ b/pvDataApp/misc/lock.h @@ -6,6 +6,7 @@ */ #ifndef LOCK_H #define LOCK_H +#include #include #include "noDefaultMethods.h" /* This is based on item 14 of @@ -14,25 +15,101 @@ namespace epics { namespace pvData { +typedef epicsMutexId native_handle_type; + +/** @brief Acquires and holds a mutex until destructed + * + * Partial implementation of boost::lock_guard<> + */ +template +class lock_guard : private NoDefaultMethods { +public: + typedef Lockable mutex_type; + explicit lock_guard(Lockable &m) + : mutex(m) + {mutex.lock();} + explicit lock_guard(Lockable *pm) + : mutex(*pm) + {mutex.lock();} + ~lock_guard(){mutex.unlock();} +private: + Lockable& mutex; +}; + +/* Lock action tags. + * Used to select construction behaviour of locks + */ +struct defer_lock_t{}; +//struct adopt_lock_t{}; + +const defer_lock_t defer_lock={}; +//const adopt_lock_t adopt_lock={}; + +/** @brief Acquires a mutex. Always releases destructed + * + * May release and re-acquire. + * Partial implementation of boost::unique_lock<> + */ +template +class unique_lock : private NoDefaultMethods { +public: + typedef Lockable mutex_type; + explicit unique_lock(Lockable &m) + : mutexPtr(&m), locked(true) + {mutex->lock();} + unique_lock(Lockable &m, defer_lock_t) + : mutexPtr(m), locked(false) + {} + void swap(unique_lock& O) + { + Lockable *t=O.mutexPtr; + bool tl=O.locked; + O.mutexPtr=mutexPtr; + O.locked=locked; + mutexPtr=t; + locked=tl; + } + void lock() + { + if(!locked) + mutexPtr->lock(); + locked=true; + } + void unlock() + { + if(locked) + mutexPtr->unlock(); + locked=false; + } + bool owns_lock() const{return locked;} + + Lockable* mutex() const{return mutex;} + Lockable* release(){locked=false; return mutex;} + +private: + Lockable *mutexPtr; + bool locked; +}; + class Mutex { public: - Mutex() : id(epicsMutexMustCreate()){} + typedef unique_lock scoped_lock; + Mutex() : id(epicsMutexCreate()) + {if(!id) throw std::bad_alloc();} ~Mutex() { epicsMutexDestroy(id) ;} - void lock(){epicsMutexMustLock(id);} + void lock(){ + if(epicsMutexLock(id)!=epicsMutexLockOK) + throw std::logic_error("Failed to acquire Mutex"); + } void unlock(){epicsMutexUnlock(id);} + + native_handle_type native_handle(){return id;} private: epicsMutexId id; }; +typedef lock_guard Lock; + -class Lock : private NoDefaultMethods { -public: - explicit Lock(Mutex *pm) - : mutexPtr(pm) - {mutexPtr->lock();} - ~Lock(){mutexPtr->unlock();} -private: - Mutex *mutexPtr; -}; }} #endif /* LOCK_H */ diff --git a/pvDataApp/misc/messageQueue.cpp b/pvDataApp/misc/messageQueue.cpp index eea6deb..e2dc4bf 100644 --- a/pvDataApp/misc/messageQueue.cpp +++ b/pvDataApp/misc/messageQueue.cpp @@ -15,39 +15,13 @@ #include "lock.h" #include "requester.h" #include "noDefaultMethods.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #include "queue.h" #include "messageQueue.h" namespace epics { namespace pvData { -static volatile int64 totalQueueConstruct = 0; -static volatile int64 totalQueueDestruct = 0; -static Mutex globalMutex; -static bool notInited = true; - -static int64 getTotalQueueConstruct() -{ - Lock xx(&globalMutex); - return totalQueueConstruct; -} - -static int64 getTotalQueueDestruct() -{ - Lock xx(&globalMutex); - return totalQueueDestruct; -} - -static void initPvt() -{ - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - "messageQueue", - getTotalQueueConstruct,getTotalQueueDestruct,0,0); - } -} +PVDATA_REFCOUNT_MONITOR_DEFINE(messageQueue); typedef MessageNode * MessageNodePtr; typedef QueueElement MessageElement; @@ -79,9 +53,7 @@ public: MessageQueue::MessageQueue(int size) : pImpl(new MessageQueuePvt) { - initPvt(); - Lock xx(&globalMutex); - totalQueueConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(messageQueue); pImpl->size = size; pImpl->overrun = 0; pImpl->lastPut = 0; @@ -100,8 +72,7 @@ MessageQueue::~MessageQueue() delete pImpl->messageNodeArray[i]; } delete[] pImpl->messageNodeArray; - Lock xx(&globalMutex); - totalQueueDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(messageQueue); } MessageNode *MessageQueue::get() { diff --git a/pvDataApp/misc/queueVoid.cpp b/pvDataApp/misc/queueVoid.cpp index c8274eb..c263758 100644 --- a/pvDataApp/misc/queueVoid.cpp +++ b/pvDataApp/misc/queueVoid.cpp @@ -14,69 +14,23 @@ #include "lock.h" #include "pvType.h" #include "queueVoid.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.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; -static bool notInited = true; - -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 void initPvt() -{ - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - "queueElement", - getTotalNodeConstruct,getTotalNodeDestruct,0,0); - ShowConstructDestruct::registerCallback( - "queue", - getTotalListConstruct,getTotalListDestruct,0,0); - } -} - +PVDATA_REFCOUNT_MONITOR_DEFINE(queueElement); +PVDATA_REFCOUNT_MONITOR_DEFINE(queue); QueueElementVoid::QueueElementVoid(ObjectPtr object) : object(object) { - initPvt(); - Lock xx(&globalMutex); - totalElementConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(queueElement); } QueueElementVoid::~QueueElementVoid() { - Lock xx(&globalMutex); - totalElementDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(queueElement); } ObjectPtr QueueElementVoid::getObject() { @@ -94,9 +48,7 @@ QueueVoid::QueueVoid(ObjectPtr object[],int number) for(int i=0; i -#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; -static bool notInited = true; -typedef LinkedListNode ListNode; -typedef LinkedList List; -static List *list; - -/* list callbacks are special because showConstructDestruct creates a list - Thus list can be null when list calls registerCallback - The list callbacks are not put on the list but handled separately - */ -static ConstructDestructCallback *listCallback = 0; -static ConstructDestructCallback *listNodeCallback = 0; - -ConstructDestructCallback::ConstructDestructCallback( - String name, - getTotalFunc construct, - getTotalFunc destruct, - getTotalFunc reference, - deleteStaticFunc deleteFunc) -: name(name), construct(construct), destruct(destruct) ,reference(reference), - deleteFunc(deleteFunc) -{ } - -ConstructDestructCallback::~ConstructDestructCallback() {} - -String ConstructDestructCallback::getConstructName() -{ - return name; -} - -int64 ConstructDestructCallback::getTotalConstruct() -{ - if(construct==0) return 0; - return construct(); -} - -int64 ConstructDestructCallback:: getTotalDestruct() -{ - if(destruct==0) return 0; - return destruct(); -} - -int64 ConstructDestructCallback::getTotalReferenceCount() -{ - if(reference==0) return 0; - return reference(); -} - -void ConstructDestructCallback::deleteStatic() -{ - if(deleteFunc==0) return; - deleteFunc(); -} - -ShowConstructDestruct::ShowConstructDestruct() {} - -ShowConstructDestruct::~ShowConstructDestruct() { - delete listCallback; - delete listNodeCallback; - listCallback = 0; - listNodeCallback = 0; -} - -void ShowConstructDestruct::registerCallback( - String name, - getTotalFunc construct, - getTotalFunc destruct, - getTotalFunc reference, - deleteStaticFunc deleteFunc) -{ - getShowConstructDestruct(); // make it initialize - Lock xx(&globalMutex); - if(name.compare("linkedList")==0) { - listCallback = new ConstructDestructCallback( - name,construct,destruct,reference,deleteFunc); - return; - } else if(name.compare("linkedListNode")==0) { - listNodeCallback = new ConstructDestructCallback( - name,construct,destruct,reference,deleteFunc); - return; - } - if(list==0) { - throw std::logic_error(String( - "ShowConstructDestruct::registerCallback")); - } - ConstructDestructCallback *callback = new ConstructDestructCallback( - name,construct,destruct,reference,deleteFunc); - ListNode *listNode = new ListNode(callback); - list->addTail(listNode); -} -static void showOne(ConstructDestructCallback *callback,FILE *fd) -{ - String name = callback->getConstructName(); - int64 reference = callback->getTotalReferenceCount(); - int64 construct = callback->getTotalConstruct(); - int64 destruct = callback->getTotalDestruct(); - if(reference==0&&construct==0&&destruct==0) return; - fprintf(fd,"%s: ", name.c_str()); - if(construct>0 || destruct>0) { - fprintf(fd," totalConstruct %lli totalDestruct %lli", - construct,destruct); - } - if(reference>0) fprintf(fd," totalReference %lli",reference); - int64 diff = construct - destruct; - if(diff!=0) fprintf(fd," ACTIVE %lli",diff); - fprintf(fd,"\n"); -} - -ConstructDestructCallback* ShowConstructDestruct::getConstructDestructCallback( - String name) -{ - if(name.compare(listNodeCallback->getConstructName())==0) { - return listNodeCallback; - } - if(name.compare(listCallback->getConstructName())==0) { - return listCallback; - } - Lock xx(&globalMutex); - ListNode *node = list->getHead(); - while(node!=0) { - ConstructDestructCallback *callback = node->getObject(); - if(name.compare(callback->getConstructName())==0) { - return callback; - } - node = list->getNext(node); - } - return 0; -} - -void ShowConstructDestruct::constuctDestructTotals(FILE *fd) -{ - getShowConstructDestruct(); // make it initialize - Lock xx(&globalMutex); - ListNode *node = list->getHead(); - while(node!=0) { - ConstructDestructCallback *callback = node->getObject(); - showOne(callback,fd); - node = list->getNext(node); - } - showOne(listNodeCallback,fd); - showOne(listCallback,fd); -} - -void ShowConstructDestruct::showDeleteStaticExit(FILE *fd) -{ - getShowConstructDestruct(); // make it initialize - { - Lock xx(&globalMutex); - ListNode *node = list->getHead(); - while(node!=0) { - ConstructDestructCallback *callback = node->getObject(); - if(callback->deleteFunc!=0) callback->deleteFunc(); - node = list->getNext(node); - } - node = list->getHead(); - while(node!=0) { - ConstructDestructCallback *callback = node->getObject(); - showOne(callback,fd); - list->removeHead(); - delete callback; - delete node; - node = list->getHead(); - } - delete list; - if(listNodeCallback->deleteFunc!=0) listNodeCallback->deleteFunc(); - if(listCallback->deleteFunc!=0) listCallback->deleteFunc(); - showOne(listNodeCallback,fd); - showOne(listCallback,fd); - delete pShowConstructDestruct; - pShowConstructDestruct = 0; - } - exit( 0); -} - -ShowConstructDestruct * getShowConstructDestruct() -{ - static Mutex mutex; - Lock xx(&mutex); - if(notInited) { - notInited = false; - pShowConstructDestruct = new ShowConstructDestruct(); - List *listTemp; - listTemp = new List(); - list = listTemp; - } - return pShowConstructDestruct; -} - -}} diff --git a/pvDataApp/misc/showConstructDestruct.h b/pvDataApp/misc/showConstructDestruct.h deleted file mode 100644 index 643b9ac..0000000 --- a/pvDataApp/misc/showConstructDestruct.h +++ /dev/null @@ -1,109 +0,0 @@ -/* showConstructDestruct.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 SHOWCONSTRUCTDESTRUCT_H -#define SHOWCONSTRUCTDESTRUCT_H -#include -#include -#include -#include -#include - -#include "noDefaultMethods.h" -#include "pvType.h" - -namespace epics { namespace pvData { - -typedef int64 (*getTotalFunc)(); -typedef void (*deleteStaticFunc)(); - -class ConstructDestructCallback : private NoDefaultMethods { -public: - String getConstructName(); - int64 getTotalConstruct(); - int64 getTotalDestruct(); - int64 getTotalReferenceCount(); -private: - ConstructDestructCallback( - String name, - getTotalFunc construct, - getTotalFunc destruct, - getTotalFunc reference, - deleteStaticFunc deleteFunc); - ~ConstructDestructCallback(); - void deleteStatic(); - String name; - getTotalFunc construct; - getTotalFunc destruct; - getTotalFunc reference; - deleteStaticFunc deleteFunc; - friend class ShowConstructDestruct; -}; - -class ShowConstructDestruct : private NoDefaultMethods { -public: - static void registerCallback( - String name, - getTotalFunc construct, - getTotalFunc destruct, - getTotalFunc reference, - deleteStaticFunc deleteFunc); - ConstructDestructCallback* getConstructDestructCallback(String name); - void constuctDestructTotals(FILE *fd); - static void showDeleteStaticExit(FILE *fd); -private: - ShowConstructDestruct(); - ~ShowConstructDestruct(); - friend ShowConstructDestruct* getShowConstructDestruct(); -}; - -extern ShowConstructDestruct* getShowConstructDestruct(); - - - -/* convenience macros - no getTotalReferenceCount() support */ - -#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME) \ - static volatile int64 NAME ## _totalConstruct = 0; \ - static volatile int64 NAME ## _totalDestruct = 0; \ - static Mutex NAME ## _globalMutex; \ - \ - static bool NAME ## _notInited = true; \ - static int64 NAME ## _processTotalConstruct() \ - { \ - Lock xx(&NAME ## _globalMutex); \ - return NAME ## _totalConstruct; \ - } \ - \ - static int64 NAME ## _processTotalDestruct() \ - { \ - Lock xx(&NAME ## _globalMutex); \ - return NAME ## _totalDestruct; \ - } \ - \ - static void NAME ## _init() \ - { \ - Lock xx(&NAME ## _globalMutex); \ - if(NAME ## _notInited) { \ - NAME ## _notInited = false; \ - ShowConstructDestruct::registerCallback( \ - String(#NAME), \ - NAME ## _processTotalConstruct,NAME ## _processTotalDestruct,0,0); \ - } \ - } - -#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME) \ - Lock xx(&NAME ## _globalMutex); \ - NAME ## _totalDestruct++; - -#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME) \ - NAME ## _init(); \ - Lock xx(&NAME ## _globalMutex); \ - NAME ## _totalConstruct++; - - -}} -#endif /* SHOWCONSTRUCTDESTRUCT_H */ diff --git a/pvDataApp/misc/thread.cpp b/pvDataApp/misc/thread.cpp index feb10b8..587ec55 100644 --- a/pvDataApp/misc/thread.cpp +++ b/pvDataApp/misc/thread.cpp @@ -13,11 +13,12 @@ #include #include +#include #include "lock.h" #include "event.h" #include "thread.h" #include "linkedList.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" namespace epics { namespace pvData { @@ -47,41 +48,25 @@ class ThreadListElement; typedef LinkedListNode ThreadListNode; typedef LinkedList ThreadList; -static volatile int64 totalConstruct = 0; -static volatile int64 totalDestruct = 0; -static Mutex globalMutex; -static bool notInited = true; +PVDATA_REFCOUNT_MONITOR_DEFINE(thread); + +static Mutex listGuard; static ThreadList *threadList; -static int64 getTotalConstruct() -{ - Lock xx(&globalMutex); - return totalConstruct; -} - -static int64 getTotalDestruct() -{ - Lock xx(&globalMutex); - return totalDestruct; -} - -static void deleteStatic() +static void deleteStatic(void*) { delete threadList; } -static void init() +static void init(void*) { - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - threadList = new ThreadList(); - ShowConstructDestruct::registerCallback( - String("thread"), - getTotalConstruct,getTotalDestruct,0,deleteStatic); - } + threadList = new ThreadList(); + epicsAtExit(&deleteStatic,0); } +static +epicsThreadOnceId initOnce = EPICS_THREAD_ONCE_INIT; + class ThreadListElement { public: @@ -136,10 +121,10 @@ ThreadPvt::ThreadPvt(Thread *thread,String name, epicsThreadGetStackSize(epicsThreadStackSmall), myFunc,this)) { - init(); - Lock xx(&globalMutex); + epicsThreadOnce(&initOnce, &init, 0); + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(thread); + Lock x(&listGuard); threadList->addTail(threadListElement->node); - totalConstruct++; } ThreadPvt::~ThreadPvt() @@ -158,11 +143,11 @@ ThreadPvt::~ThreadPvt() message += " is not on threadlist"; throw std::logic_error(message); } + Lock x(&listGuard); threadList->remove(threadListElement->node); delete waitDone; delete threadListElement; - Lock xx(&globalMutex); - totalDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(thread); } Thread::Thread(String name,ThreadPriority priority,Runnable *runnable) @@ -192,8 +177,7 @@ ThreadPriority Thread::getPriority() void Thread::showThreads(StringBuilder buf) { - init(); - Lock xx(&globalMutex); + Lock x(&listGuard); ThreadListNode *node = threadList->getHead(); while(node!=0) { Thread *thread = node->getObject()->thread; diff --git a/pvDataApp/misc/timer.cpp b/pvDataApp/misc/timer.cpp index 9750246..dd5483f 100644 --- a/pvDataApp/misc/timer.cpp +++ b/pvDataApp/misc/timer.cpp @@ -14,7 +14,7 @@ #include "pvType.h" #include "lock.h" #include "noDefaultMethods.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #include "linkedList.h" #include "thread.h" #include "timeStamp.h" @@ -23,51 +23,8 @@ namespace epics { namespace pvData { - -static volatile int64 totalNodeConstruct = 0; -static volatile int64 totalNodeDestruct = 0; -static volatile int64 totalTimerConstruct = 0; -static volatile int64 totalTimerDestruct = 0; -static Mutex globalMutex; -static bool notInited = true; - -static int64 getTotalTimerNodeConstruct() -{ - Lock xx(&globalMutex); - return totalNodeConstruct; -} - -static int64 getTotalTimerNodeDestruct() -{ - Lock xx(&globalMutex); - return totalNodeDestruct; -} - -static int64 getTotalTimerConstruct() -{ - Lock xx(&globalMutex); - return totalTimerConstruct; -} - -static int64 getTotalTimerDestruct() -{ - Lock xx(&globalMutex); - return totalTimerDestruct; -} - -static void init() -{ - Lock xx(&globalMutex); - if(notInited) { - notInited = false; - ShowConstructDestruct::registerCallback( - "timerNode", - getTotalTimerNodeConstruct,getTotalTimerNodeDestruct,0,0); - ShowConstructDestruct::registerCallback( - "timer", - getTotalTimerConstruct,getTotalTimerDestruct,0,0); - } -} +PVDATA_REFCOUNT_MONITOR_DEFINE(timerNode); +PVDATA_REFCOUNT_MONITOR_DEFINE(timer); class TimerNodePvt; @@ -154,9 +111,7 @@ static void addElement(TimerPvt *timer,TimerNodePvt *node) TimerNode::TimerNode(TimerCallback *callback) : pImpl(new TimerNodePvt(this,callback)) { - init(); - Lock xx(&globalMutex); - totalNodeConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timerNode); } @@ -164,8 +119,7 @@ TimerNode::~TimerNode() { cancel(); delete pImpl; - Lock xx(&globalMutex); - totalNodeDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(timerNode); } void TimerNode::cancel() @@ -240,9 +194,7 @@ void TimerPvt::run() Timer::Timer(String threadName, ThreadPriority priority) : pImpl(new TimerPvt(threadName,priority)) { - init(); - Lock xx(&globalMutex); - totalTimerConstruct++; + PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timer); } Timer::~Timer() { @@ -258,8 +210,7 @@ Timer::~Timer() { node->getObject()->callback->timerStopped(); } delete pImpl; - Lock xx(&globalMutex); - totalTimerDestruct++; + PVDATA_REFCOUNT_MONITOR_DESTRUCT(timer); } void Timer::scheduleAfterDelay(TimerNode *timerNode,double delay) diff --git a/test/testIntrospect b/test/testIntrospect index 9c5f4e7..591b0fe 100644 --- a/test/testIntrospect +++ b/test/testIntrospect @@ -79,5 +79,3 @@ structure value int nanoSeconds field: totalConstruct 120 totalDestruct 120 pvField: totalConstruct 47 totalDestruct 47 -linkedListNode: totalConstruct 4 totalDestruct 4 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testIntrospectGold b/test/testIntrospectGold index 9c5f4e7..591b0fe 100644 --- a/test/testIntrospectGold +++ b/test/testIntrospectGold @@ -79,5 +79,3 @@ structure value int nanoSeconds field: totalConstruct 120 totalDestruct 120 pvField: totalConstruct 47 totalDestruct 47 -linkedListNode: totalConstruct 4 totalDestruct 4 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testLinkedList b/test/testLinkedList index e149909..af50c54 100644 --- a/test/testLinkedList +++ b/test/testLinkedList @@ -17,5 +17,5 @@ stack 4 3 2 1 0 Ordered Queue test list 0 1 2 3 4 -linkedListNode: totalConstruct 4039 totalDestruct 4039 -linkedList: totalConstruct 9 totalDestruct 9 +LinkedList: totalConstruct 8 totalDestruct 8 +LinkedListNode: totalConstruct 4038 totalDestruct 4038 diff --git a/test/testLinkedListGold b/test/testLinkedListGold index e149909..af50c54 100644 --- a/test/testLinkedListGold +++ b/test/testLinkedListGold @@ -17,5 +17,5 @@ stack 4 3 2 1 0 Ordered Queue test list 0 1 2 3 4 -linkedListNode: totalConstruct 4039 totalDestruct 4039 -linkedList: totalConstruct 9 totalDestruct 9 +LinkedList: totalConstruct 8 totalDestruct 8 +LinkedListNode: totalConstruct 4038 totalDestruct 4038 diff --git a/test/testMessageQueue b/test/testMessageQueue index 36d38b1..ff56a18 100644 --- a/test/testMessageQueue +++ b/test/testMessageQueue @@ -1,7 +1,5 @@ message 1 messageType info message 4 messageType info -messageQueue: totalConstruct 1 totalDestruct 1 -queueElement: totalConstruct 3 totalDestruct 3 queue: totalConstruct 1 totalDestruct 1 -linkedListNode: totalConstruct 4 totalDestruct 4 -linkedList: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 3 totalDestruct 3 +messageQueue: totalConstruct 1 totalDestruct 1 diff --git a/test/testMessageQueueGold b/test/testMessageQueueGold index 36d38b1..ff56a18 100644 --- a/test/testMessageQueueGold +++ b/test/testMessageQueueGold @@ -1,7 +1,5 @@ message 1 messageType info message 4 messageType info -messageQueue: totalConstruct 1 totalDestruct 1 -queueElement: totalConstruct 3 totalDestruct 3 queue: totalConstruct 1 totalDestruct 1 -linkedListNode: totalConstruct 4 totalDestruct 4 -linkedList: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 3 totalDestruct 3 +messageQueue: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAppend b/test/testPVAppend index d742b1f..f0643db 100644 --- a/test/testPVAppend +++ b/test/testPVAppend @@ -30,5 +30,3 @@ structure parent string Jane Bad Girl field: totalConstruct 108 totalDestruct 108 pvField: totalConstruct 15 totalDestruct 14 ACTIVE 1 -linkedListNode: totalConstruct 5 totalDestruct 5 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAppendGold b/test/testPVAppendGold index d742b1f..f0643db 100644 --- a/test/testPVAppendGold +++ b/test/testPVAppendGold @@ -30,5 +30,3 @@ structure parent string Jane Bad Girl field: totalConstruct 108 totalDestruct 108 pvField: totalConstruct 15 totalDestruct 14 ACTIVE 1 -linkedListNode: totalConstruct 5 totalDestruct 5 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAuxInfo b/test/testPVAuxInfo index 37c78f5..b132b12 100644 --- a/test/testPVAuxInfo +++ b/test/testPVAuxInfo @@ -33,8 +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 +pvAuxInfo: totalConstruct 1 totalDestruct 1 field: totalConstruct 97 totalDestruct 97 pvField: totalConstruct 17 totalDestruct 17 -pvAuxInfo: totalConstruct 1 totalDestruct 1 -linkedListNode: totalConstruct 6 totalDestruct 6 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAuxInfoGold b/test/testPVAuxInfoGold index 37c78f5..b132b12 100644 --- a/test/testPVAuxInfoGold +++ b/test/testPVAuxInfoGold @@ -33,8 +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 +pvAuxInfo: totalConstruct 1 totalDestruct 1 field: totalConstruct 97 totalDestruct 97 pvField: totalConstruct 17 totalDestruct 17 -pvAuxInfo: totalConstruct 1 totalDestruct 1 -linkedListNode: totalConstruct 6 totalDestruct 6 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVData b/test/testPVData index 029b329..a05b830 100644 --- a/test/testPVData +++ b/test/testPVData @@ -285,5 +285,3 @@ structure string int nanoSeconds 0 field: totalConstruct 135 totalDestruct 135 pvField: totalConstruct 281 totalDestruct 281 -linkedListNode: totalConstruct 5 totalDestruct 5 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVDataGold b/test/testPVDataGold index 029b329..a05b830 100644 --- a/test/testPVDataGold +++ b/test/testPVDataGold @@ -285,5 +285,3 @@ structure string int nanoSeconds 0 field: totalConstruct 135 totalDestruct 135 pvField: totalConstruct 281 totalDestruct 281 -linkedListNode: totalConstruct 5 totalDestruct 5 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVStructureArray b/test/testPVStructureArray index f50783e..3f8e332 100644 --- a/test/testPVStructureArray +++ b/test/testPVStructureArray @@ -172,5 +172,3 @@ after compressstructure powerSupply int nanoSeconds 0 field: totalConstruct 102 totalDestruct 102 pvField: totalConstruct 88 totalDestruct 88 -linkedListNode: totalConstruct 5 totalDestruct 5 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVStructureArrayGold b/test/testPVStructureArrayGold index f50783e..3f8e332 100644 --- a/test/testPVStructureArrayGold +++ b/test/testPVStructureArrayGold @@ -172,5 +172,3 @@ after compressstructure powerSupply int nanoSeconds 0 field: totalConstruct 102 totalDestruct 102 pvField: totalConstruct 88 totalDestruct 88 -linkedListNode: totalConstruct 5 totalDestruct 5 -linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testQueue b/test/testQueue index 0b0f26d..14669ad 100644 --- a/test/testQueue +++ b/test/testQueue @@ -1,6 +1,6 @@ -queueElement: totalConstruct 5 totalDestruct 5 -queue: totalConstruct 1 totalDestruct 1 +LinkedList: totalConstruct 1 totalDestruct 1 +LinkedListNode: totalConstruct 2 totalDestruct 2 event: totalConstruct 5 totalDestruct 5 thread: totalConstruct 1 totalDestruct 1 -linkedListNode: totalConstruct 7 totalDestruct 7 -linkedList: totalConstruct 2 totalDestruct 2 +queue: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 5 totalDestruct 5 diff --git a/test/testQueueGold b/test/testQueueGold index 0b0f26d..14669ad 100644 --- a/test/testQueueGold +++ b/test/testQueueGold @@ -1,6 +1,6 @@ -queueElement: totalConstruct 5 totalDestruct 5 -queue: totalConstruct 1 totalDestruct 1 +LinkedList: totalConstruct 1 totalDestruct 1 +LinkedListNode: totalConstruct 2 totalDestruct 2 event: totalConstruct 5 totalDestruct 5 thread: totalConstruct 1 totalDestruct 1 -linkedListNode: totalConstruct 7 totalDestruct 7 -linkedList: totalConstruct 2 totalDestruct 2 +queue: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 5 totalDestruct 5 diff --git a/test/testThread b/test/testThread index 8766374..6110dea 100644 --- a/test/testThread +++ b/test/testThread @@ -1,8 +1,8 @@ threads basic middle +LinkedList: totalConstruct 5 totalDestruct 5 +LinkedListNode: totalConstruct 11 totalDestruct 11 event: totalConstruct 8 totalDestruct 8 thread: totalConstruct 2 totalDestruct 2 executor: totalConstruct 2 totalDestruct 2 -linkedListNode: totalConstruct 15 totalDestruct 15 -linkedList: totalConstruct 6 totalDestruct 6 diff --git a/test/testThreadGold b/test/testThreadGold index 8766374..6110dea 100644 --- a/test/testThreadGold +++ b/test/testThreadGold @@ -1,8 +1,8 @@ threads basic middle +LinkedList: totalConstruct 5 totalDestruct 5 +LinkedListNode: totalConstruct 11 totalDestruct 11 event: totalConstruct 8 totalDestruct 8 thread: totalConstruct 2 totalDestruct 2 executor: totalConstruct 2 totalDestruct 2 -linkedListNode: totalConstruct 15 totalDestruct 15 -linkedList: totalConstruct 6 totalDestruct 6 diff --git a/test/testTimer b/test/testTimer index 9e1d103..116398a 100644 --- a/test/testTimer +++ b/test/testTimer @@ -1,6 +1,6 @@ +LinkedList: totalConstruct 4 totalDestruct 4 +LinkedListNode: totalConstruct 13 totalDestruct 13 event: totalConstruct 15 totalDestruct 15 thread: totalConstruct 3 totalDestruct 3 -timerNode: totalConstruct 6 totalDestruct 6 timer: totalConstruct 3 totalDestruct 3 -linkedListNode: totalConstruct 18 totalDestruct 18 -linkedList: totalConstruct 5 totalDestruct 5 +timerNode: totalConstruct 6 totalDestruct 6 diff --git a/test/testTimerGold b/test/testTimerGold index 9e1d103..116398a 100644 --- a/test/testTimerGold +++ b/test/testTimerGold @@ -1,6 +1,6 @@ +LinkedList: totalConstruct 4 totalDestruct 4 +LinkedListNode: totalConstruct 13 totalDestruct 13 event: totalConstruct 15 totalDestruct 15 thread: totalConstruct 3 totalDestruct 3 -timerNode: totalConstruct 6 totalDestruct 6 timer: totalConstruct 3 totalDestruct 3 -linkedListNode: totalConstruct 18 totalDestruct 18 -linkedList: totalConstruct 5 totalDestruct 5 +timerNode: totalConstruct 6 totalDestruct 6 diff --git a/testApp/misc/testBitSet.cpp b/testApp/misc/testBitSet.cpp index a5a2fb3..372689e 100644 --- a/testApp/misc/testBitSet.cpp +++ b/testApp/misc/testBitSet.cpp @@ -12,9 +12,10 @@ #include #include #include -#include +#include #include +#include using namespace epics::pvData; @@ -149,7 +150,8 @@ int main(int argc,char *argv[]) } testGetSetClearFlip(); testOperators(); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return(0); } diff --git a/testApp/misc/testLinkedList.cpp b/testApp/misc/testLinkedList.cpp index 1e39614..5f9e00e 100644 --- a/testApp/misc/testLinkedList.cpp +++ b/testApp/misc/testLinkedList.cpp @@ -18,11 +18,12 @@ #include #include +#include #include "lock.h" #include "timeStamp.h" #include "linkedList.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -448,7 +449,8 @@ int main(int argc, char *argv[]) { testTimeLocked(auxFd); testStdListTime(auxFd); testStdListTimeLocked(auxFd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return (0); } diff --git a/testApp/misc/testMessageQueue.cpp b/testApp/misc/testMessageQueue.cpp index 5e0e3bd..4acb81d 100644 --- a/testApp/misc/testMessageQueue.cpp +++ b/testApp/misc/testMessageQueue.cpp @@ -17,12 +17,13 @@ #include #include +#include #include "lock.h" #include "timeStamp.h" #include "requester.h" #include "messageQueue.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #include "event.h" #include "thread.h" #include "executor.h" @@ -86,7 +87,8 @@ int main(int argc, char *argv[]) { auxfd = fopen(auxFileName,"w+"); } testBasic(fd,auxfd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return (0); } diff --git a/testApp/misc/testQueue.cpp b/testApp/misc/testQueue.cpp index c519877..513d043 100644 --- a/testApp/misc/testQueue.cpp +++ b/testApp/misc/testQueue.cpp @@ -17,11 +17,12 @@ #include #include +#include #include "lock.h" #include "timeStamp.h" #include "queue.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #include "event.h" #include "thread.h" #include "executor.h" @@ -155,7 +156,8 @@ int main(int argc, char *argv[]) { auxfd = fopen(auxFileName,"w+"); } testBasic(fd,auxfd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return (0); } diff --git a/testApp/misc/testSerialization.cpp b/testApp/misc/testSerialization.cpp index 29999b1..c284e48 100644 --- a/testApp/misc/testSerialization.cpp +++ b/testApp/misc/testSerialization.cpp @@ -13,12 +13,13 @@ #include +#include #include "pvIntrospect.h" #include "pvData.h" #include "serialize.h" #include "noDefaultMethods.h" #include "byteBuffer.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #define BYTE_MAX_VALUE 127 #define BYTE_MIN_VALUE -128 @@ -639,7 +640,8 @@ int main(int argc, char *argv[]) { delete control; delete flusher; - getShowConstructDestruct()->showDeleteStaticExit(stdout); + epicsExitCallAtExits(); + CDRMonitor::get().show(stdout); cout<<"\nDone!\n"; return (0); diff --git a/testApp/misc/testThread.cpp b/testApp/misc/testThread.cpp index 5c37290..ce046da 100644 --- a/testApp/misc/testThread.cpp +++ b/testApp/misc/testThread.cpp @@ -18,11 +18,12 @@ #include #include +#include #include "event.h" #include "thread.h" #include "executor.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" #include "timeFunction.h" using namespace epics::pvData; @@ -115,6 +116,7 @@ int main(int argc, char *argv[]) { } testBasic(fd); testThreadContext(fd,auxFd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return (0); } diff --git a/testApp/misc/testTimer.cpp b/testApp/misc/testTimer.cpp index 8e69e02..f9bff9d 100644 --- a/testApp/misc/testTimer.cpp +++ b/testApp/misc/testTimer.cpp @@ -17,11 +17,12 @@ #include #include +#include #include "timeStamp.h" #include "event.h" #include "timer.h" #include "thread.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -112,6 +113,7 @@ int main(int argc, char *argv[]) { oneDelay = .0; twoDelay = .0; testBasic(fd,auxfd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return (0); } diff --git a/testApp/property/testProperty.cpp b/testApp/property/testProperty.cpp index b34032c..f9abcfd 100644 --- a/testApp/property/testProperty.cpp +++ b/testApp/property/testProperty.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "requester.h" #include "pvIntrospect.h" @@ -29,7 +30,7 @@ #include "pvDisplay.h" #include "pvEnumerated.h" #include "pvTimeStamp.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -243,7 +244,8 @@ int main(int argc,char *argv[]) testDisplay(fd,auxfd); testEnumerated(fd,auxfd); deleteRecords(fd,auxfd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return(0); } diff --git a/testApp/pv/temp.cpp b/testApp/pv/temp.cpp index 86541c0..e85f9fe 100644 --- a/testApp/pv/temp.cpp +++ b/testApp/pv/temp.cpp @@ -20,7 +20,7 @@ #include "convert.h" #include "standardField.h" #include "standardPVField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; diff --git a/testApp/pv/testIntrospect.cpp b/testApp/pv/testIntrospect.cpp index f43d884..8eced01 100644 --- a/testApp/pv/testIntrospect.cpp +++ b/testApp/pv/testIntrospect.cpp @@ -13,13 +13,14 @@ #include #include +#include #include "requester.h" #include "executor.h" #include "pvIntrospect.h" #include "pvData.h" #include "standardField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -147,7 +148,8 @@ int main(int argc,char *argv[]) testScalarArray(fd); testSimpleStructure(fd); testStructureArray(fd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return(0); } diff --git a/testApp/pv/testPVAppend.cpp b/testApp/pv/testPVAppend.cpp index 5f70523..50e716e 100644 --- a/testApp/pv/testPVAppend.cpp +++ b/testApp/pv/testPVAppend.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "requester.h" #include "pvIntrospect.h" @@ -20,7 +21,7 @@ #include "convert.h" #include "standardField.h" #include "standardPVField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -142,7 +143,8 @@ int main(int argc,char *argv[]) testAppendSimple(fd); testAppendMore(fd); testAppends(fd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return(0); } diff --git a/testApp/pv/testPVAuxInfo.cpp b/testApp/pv/testPVAuxInfo.cpp index 2456800..f4913cc 100644 --- a/testApp/pv/testPVAuxInfo.cpp +++ b/testApp/pv/testPVAuxInfo.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "requester.h" #include "pvIntrospect.h" @@ -20,7 +21,7 @@ #include "convert.h" #include "standardField.h" #include "standardPVField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -92,7 +93,8 @@ int main(int argc,char *argv[]) standardPVField = getStandardPVField(); convert = getConvert(); testPVAuxInfo(fd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return(0); } diff --git a/testApp/pv/testPVData.cpp b/testApp/pv/testPVData.cpp index 744cae8..d2321a8 100644 --- a/testApp/pv/testPVData.cpp +++ b/testApp/pv/testPVData.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "requester.h" #include "pvIntrospect.h" @@ -20,7 +21,7 @@ #include "convert.h" #include "standardField.h" #include "standardPVField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -282,7 +283,8 @@ int main(int argc,char *argv[]) testAppend(fd); testPVScalar(fd); testScalarArray(fd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return(0); } diff --git a/testApp/pv/testPVStructureArray.cpp b/testApp/pv/testPVStructureArray.cpp index f27120d..94464d6 100644 --- a/testApp/pv/testPVStructureArray.cpp +++ b/testApp/pv/testPVStructureArray.cpp @@ -13,13 +13,14 @@ #include #include +#include #include "requester.h" #include "pvIntrospect.h" #include "pvData.h" #include "standardField.h" #include "standardPVField.h" -#include "showConstructDestruct.h" +#include "CDRMonitor.h" using namespace epics::pvData; @@ -79,7 +80,8 @@ int main(int argc,char *argv[]) standardField = getStandardField(); standardPVField = getStandardPVField(); testPowerSupplyArray(fd); - getShowConstructDestruct()->showDeleteStaticExit(fd); + epicsExitCallAtExits(); + CDRMonitor::get().show(fd); return(0); }