diff --git a/pvDataApp/factory/AbstractPVField.h b/pvDataApp/factory/AbstractPVField.h index fd07360..ee9373d 100644 --- a/pvDataApp/factory/AbstractPVField.h +++ b/pvDataApp/factory/AbstractPVField.h @@ -32,12 +32,12 @@ PVFieldPvt::PVFieldPvt(PVStructure *parent,FieldConstPtr field) pvAuxInfo(0), immutable(false),requester(0),postHandler(0) { - delete pvAuxInfo; field->incReferenceCount(); } PVFieldPvt::~PVFieldPvt() { + if(pvAuxInfo!=0) delete pvAuxInfo; field->decReferenceCount(); } diff --git a/pvDataApp/factory/PVAuxInfoImpl.cpp b/pvDataApp/factory/PVAuxInfoImpl.cpp index 9fbd9d9..0bb6809 100644 --- a/pvDataApp/factory/PVAuxInfoImpl.cpp +++ b/pvDataApp/factory/PVAuxInfoImpl.cpp @@ -5,7 +5,9 @@ #include #include "noDefaultMethods.h" #include "pvData.h" +#include "convert.h" #include "factory.h" +#include "lock.h" namespace epics { namespace pvData { @@ -19,27 +21,64 @@ 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)) -{ } +{ + Lock xx(globalMutex); + totalConstruct++; +} -PVAuxInfo::~PVAuxInfo() { delete pImpl;} +PVAuxInfo::~PVAuxInfo() { + Lock xx(globalMutex); + totalDestruct++; + map_iterator i = pImpl->theMap.begin(); + while(i!=pImpl->theMap.end()) { + PVScalar *value = i->second; + delete value; + i++; + } + delete pImpl; +} PVField * PVAuxInfo::getPVField() { return pImpl->pvField; } -typedef std::map::const_iterator map_iterator; PVScalar * PVAuxInfo::createInfo(String key,ScalarType scalarType) { map_iterator i = pImpl->theMap.find(key); - if(i!=pImpl->theMap.end()) { + while(i!=pImpl->theMap.end()) { String message("AuxoInfo:create key "); message += key.c_str(); message += " already exists with scalarType "; ScalarTypeFunc::toString(&message,scalarType); pImpl->pvField->message(message,errorMessage); + i++; } PVScalar *pvScalar = getPVDataCreate()->createPVScalar(0,key,scalarType); pImpl->theMap.insert(std::pair(key, pvScalar)); @@ -61,19 +100,23 @@ PVScalar * PVAuxInfo::getInfo(String key) void PVAuxInfo::toString(StringBuilder buf) { - return PVAuxInfo::toString(buf,0); + PVAuxInfo::toString(buf,0); } void PVAuxInfo::toString(StringBuilder buf,int indentLevel) { + Convert *convert = getConvert(); + convert->newLine(buf,indentLevel); + *buf += "auxInfo"; map_iterator i = pImpl->theMap.begin(); while(i!=pImpl->theMap.end()) { + convert->newLine(buf,indentLevel+1); String key = i->first; PVScalar *value = i->second; - *buf += " "; + *buf += "key("; *buf += key.c_str(); - *buf += " "; - value->toString(buf); + *buf += ") "; + value->toString(buf,indentLevel + 1); i++; } } diff --git a/pvDataApp/factory/PVDataCreateFactory.cpp b/pvDataApp/factory/PVDataCreateFactory.cpp index 7073a2b..4529d84 100644 --- a/pvDataApp/factory/PVDataCreateFactory.cpp +++ b/pvDataApp/factory/PVDataCreateFactory.cpp @@ -40,6 +40,7 @@ static PVDataCreate* pvDataCreate = 0; PVDataCreate::PVDataCreate(){ PVField::init(); + PVAuxInfo::init(); } PVField *PVDataCreate::createPVField(PVStructure *parent, diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index 981ab6e..4b78385 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -46,6 +46,8 @@ namespace epics { namespace pvData { public: PVAuxInfo(PVField *pvField); ~PVAuxInfo(); + static int64 getTotalConstruct(); + static int64 getTotalDestruct(); PVField * getPVField(); PVScalar * createInfo(String key,ScalarType scalarType); PVScalarMap getInfos(); @@ -55,6 +57,7 @@ namespace epics { namespace pvData { private: static void init(); class PVAuxInfoPvt *pImpl; + friend class PVDataCreate; }; class PostHandler { diff --git a/pvDataApp/pvTest/Makefile b/pvDataApp/pvTest/Makefile index 8c2065b..93d5c12 100644 --- a/pvDataApp/pvTest/Makefile +++ b/pvDataApp/pvTest/Makefile @@ -6,6 +6,10 @@ PROD_HOST += testPVType testPVType_SRCS += testPVType.cpp testPVType_LIBS += pvFactory Com +PROD_HOST += testPVAuxInfo +testPVAuxInfo_SRCS += testPVAuxInfo.cpp +testPVAuxInfo_LIBS += pvFactory Com + PROD_HOST += testIntrospect testIntrospect_SRCS += testIntrospect.cpp testIntrospect_LIBS += pvFactory Com diff --git a/pvDataApp/pvTest/testPVAuxInfo.cpp b/pvDataApp/pvTest/testPVAuxInfo.cpp new file mode 100644 index 0000000..74ef86a --- /dev/null +++ b/pvDataApp/pvTest/testPVAuxInfo.cpp @@ -0,0 +1,113 @@ +/* testPVAuxInfo.cpp */ +/* Author: Marty Kraimer Date: 2010.11 */ + +#include +#include +#include +#include +#include + +#include + +#include "requester.h" +#include "pvIntrospect.h" +#include "pvData.h" +#include "convert.h" +#include "standardField.h" +#include "standardPVField.h" + +using namespace epics::pvData; + +static FieldCreate * fieldCreate = 0; +static PVDataCreate * pvDataCreate = 0; +static StandardField *standardField = 0; +static StandardPVField *standardPVField = 0; +static Convert *convert = 0; +static String buffer(""); + +static void printOffsets(PVStructure *pvStructure,FILE *fd) +{ + fprintf(fd,"%s offset %d next %d number %d\n", + pvStructure->getField()->getFieldName().c_str(), + pvStructure->getFieldOffset(), + pvStructure->getNextFieldOffset(), + pvStructure->getNumberFields()); + PVFieldPtrArray fields = pvStructure->getPVFields(); + int number = pvStructure->getStructure()->getNumberFields(); + for(int i=0; igetField()->getType()==structure) { + printOffsets((PVStructure *)pvField,fd); + continue; + } + fprintf(fd,"%s offset %d next %d number %d\n", + pvField->getField()->getFieldName().c_str(), + pvField->getFieldOffset(), + pvField->getNextFieldOffset(), + pvField->getNumberFields()); + } +} + +static void testPVAuxInfo(FILE * fd) { + fprintf(fd,"\ntestPVAuxInfo\n"); + PVStructure * pvStructure = standardPVField->scalar( + 0,String("value"),pvDouble,String("alarm,timeStamp,display,conytrol")); + PVStructure *displayLimit = pvStructure->getStructureField( + String("display.limit")); + assert(displayLimit!=0); + PVAuxInfo *auxInfo = displayLimit->getPVAuxInfo(); + auxInfo->createInfo(String("factory"),pvString); + auxInfo->createInfo(String("junk"),pvDouble); + PVScalar *pscalar = auxInfo->getInfo(String("factory")); + assert(pscalar!=0); + convert->fromString(pscalar,String("factoryName")); + pscalar = auxInfo->getInfo(String("junk")); + assert(pscalar!=0); + convert->fromString(pscalar,String("3.0")); + buffer.clear(); + pvStructure->toString(&buffer); + fprintf(fd,"%s\n",buffer.c_str()); + // now show field offsets + printOffsets(pvStructure,fd); + delete pvStructure; +} + +int main(int argc,char *argv[]) +{ + int initialTotalReferences,finalTotalReferences; + char *fileName = 0; + if(argc>1) fileName = argv[1]; + FILE * fd = stdout; + if(fileName!=0 && fileName[0]!=0) { + fd = fopen(fileName,"w+"); + } + fieldCreate = getFieldCreate(); + pvDataCreate = getPVDataCreate(); + 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); + return(0); +} + diff --git a/pvDataApp/test/Makefile b/pvDataApp/test/Makefile index 0efb4f3..7d795bd 100644 --- a/pvDataApp/test/Makefile +++ b/pvDataApp/test/Makefile @@ -2,10 +2,6 @@ TOP=../.. include $(TOP)/configure/CONFIG -PROD_HOST += testPVAuxInfo -testPVAuxInfo_SRCS += testPVAuxInfo.cpp -testPVAuxInfo_LIBS += pvFactory - PROD_HOST += testBitSet testBitSet_SRCS += testBitSet.cpp testBitSet_LIBS += pvMisc Com diff --git a/pvDataApp/test/testPVAuxInfo.cpp b/pvDataApp/test/testPVAuxInfo.cpp deleted file mode 100644 index caebae4..0000000 --- a/pvDataApp/test/testPVAuxInfo.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* testPVAuxInfo.cpp */ -/* Author: Marty Kraimer Date: 2010.09.21 */ - -#include -#include -#include -#include -#include - -#include "pvData.h" - -using namespace epics::pvData; - -static FieldCreate * fieldCreate = 0; -static PVDataCreate *pvDataCreate = 0; -static String buffer(""); - -void testDouble() { - printf("\ntestDouble\n"); - String valueName("value"); - ScalarConstPtr pscalar = fieldCreate->createScalar(valueName,pvDouble); - PVScalar *pvScalar = pvDataCreate->createPVScalar(0,pscalar); - PVDouble *pvValue = dynamic_cast(pvScalar); - double value = 2; - pvValue->put(value); - double getValue = pvValue->get(); - if(value!=getValue) { - fprintf(stderr,"ERROR getValue put %f get %f\n",value,getValue); - } - PVAuxInfo *auxInfo = pvValue->getPVAuxInfo(); - String stringName("string"); - PVScalar *pvAux = auxInfo->createInfo(stringName,pvDouble); - PVDouble *doubleInfo = dynamic_cast(pvAux); - doubleInfo->put(100.0); - pvAux = auxInfo->getInfo(stringName); - buffer.clear(); - buffer += "auxInfo "; - printf("\ncalling toString\n"); - printf("%s\n",buffer.c_str()); - buffer.clear(); - buffer += "pvScalar "; - pvScalar->toString(&buffer); - printf("%s\n",buffer.c_str()); - delete pvValue; -} - -int main(int argc,char *argv[]) -{ - fieldCreate = getFieldCreate(); - pvDataCreate = getPVDataCreate(); - testDouble(); - return(0); -} - diff --git a/test/testAll.pl b/test/testAll.pl index 2978579..a281dcb 100755 --- a/test/testAll.pl +++ b/test/testAll.pl @@ -5,3 +5,4 @@ system ("./testPVType.pl"); system ("./testIntrospect.pl"); system ("./testPVData.pl"); system ("./testPVStructureArray.pl"); +system ("./testPVAuxInfo.pl"); diff --git a/test/testPVAuxInfo b/test/testPVAuxInfo new file mode 100644 index 0000000..f76fe81 --- /dev/null +++ b/test/testPVAuxInfo @@ -0,0 +1,39 @@ + +testPVAuxInfo +structure value + double value 0 + structure alarm + int severity 0 + string message + structure timeStamp + long secondsPastEpoch 0 + int nanoSeconds 0 + structure display + string description + string format + string units + structure limit + double low 0 + double high 0 + auxInfo + key(factory) string factory factoryName + key(junk) double junk 3 +value offset 0 next 15 number 15 +value offset 1 next 2 number 1 +alarm offset 2 next 5 number 3 +severity offset 3 next 4 number 1 +message offset 4 next 5 number 1 +timeStamp offset 5 next 8 number 3 +secondsPastEpoch offset 6 next 7 number 1 +nanoSeconds offset 7 next 8 number 1 +display offset 8 next 15 number 7 +description offset 9 next 10 number 1 +format offset 10 next 11 number 1 +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 diff --git a/test/testPVAuxInfo.pl b/test/testPVAuxInfo.pl new file mode 100755 index 0000000..7d48cc6 --- /dev/null +++ b/test/testPVAuxInfo.pl @@ -0,0 +1,12 @@ +eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*- + if $running_under_some_shell; # testPVAuxInfo.pl +$EPICS_HOST_ARCH = "linux-x86"; +system ("rm testPVAuxInfo"); +system ("rm testPVAuxInfoDiff"); +system ("../bin/${EPICS_HOST_ARCH}/testPVAuxInfo testPVAuxInfo"); +system ("diff testPVAuxInfo testPVAuxInfoGold >> testPVAuxInfoDiff"); +if(-z "testPVAuxInfoDiff") { + print "testPVAuxInfo OK\n"; +} else { + print "testPVAuxInfo Failed\n"; +} diff --git a/test/testPVAuxInfoDiff b/test/testPVAuxInfoDiff new file mode 100644 index 0000000..e69de29 diff --git a/test/testPVAuxInfoGold b/test/testPVAuxInfoGold new file mode 100644 index 0000000..f76fe81 --- /dev/null +++ b/test/testPVAuxInfoGold @@ -0,0 +1,39 @@ + +testPVAuxInfo +structure value + double value 0 + structure alarm + int severity 0 + string message + structure timeStamp + long secondsPastEpoch 0 + int nanoSeconds 0 + structure display + string description + string format + string units + structure limit + double low 0 + double high 0 + auxInfo + key(factory) string factory factoryName + key(junk) double junk 3 +value offset 0 next 15 number 15 +value offset 1 next 2 number 1 +alarm offset 2 next 5 number 3 +severity offset 3 next 4 number 1 +message offset 4 next 5 number 1 +timeStamp offset 5 next 8 number 3 +secondsPastEpoch offset 6 next 7 number 1 +nanoSeconds offset 7 next 8 number 1 +display offset 8 next 15 number 7 +description offset 9 next 10 number 1 +format offset 10 next 11 number 1 +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 diff --git a/test/testtestPVAuxInfoDiff b/test/testtestPVAuxInfoDiff new file mode 100644 index 0000000..e69de29