More work on introspection memory management.

Required changes to pvIntrospect.h and pvData.h
This commit is contained in:
Marty Kraimer
2011-01-20 09:16:33 -05:00
parent 85811ffb69
commit f4a1173e7a
17 changed files with 218 additions and 149 deletions

View File

@@ -10,7 +10,7 @@
<body>
<h1 style="text-align: center">EPICS pvDataCPP<br />
Overview<br />
2011.01.12</h1>
2011.01.20</h1>
<p>TODO</p>
<ul>
@@ -627,6 +627,7 @@ public:
Type getType() const;
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
void renameField(String newName);
void incReferenceCount() const;
void decReferenceCount() const;
void dumpReferenceCount(StringBuilder buf,int indentLevel) const;
@@ -676,6 +677,9 @@ public:
FieldConstPtr getField(String fieldName) const;
int getFieldIndex(String fieldName) const;
FieldConstPtrArray getFields() const {return fields;}
void appendField(FieldConstPtr field);
void appendFields(int numberFields,FieldConstPtrArray fields);
void removeField(int index);
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
protected:
@@ -720,6 +724,8 @@ descriptions:</p>
<dd>Get the name of the field.</dd>
<dt style="font-family: courier;">getType</dt>
<dd>Get the field type.</dd>
<dt style="font-family: courier;">renameField</dt>
<dd>Rename the field name.</dd>
<dt style="font-family: courier;">incReferenceCount</dt>
<dd>Increment the reference count. This must be called by any code that
wants to "clone" an instance of the introspection interface and use it as
@@ -775,6 +781,15 @@ methods:</p>
method, of the field.</dd>
<dt style="font-family: courier;">getFields</dt>
<dd>Get the array of introspection interfaces for the field,</dd>
<dt style="font-family: courier;">appendField</dt>
<dd>Append a field to the Structure.</dd>
<dt style="font-family: courier;">appendFields</dt>
<dd>Append the fields to the Structure. The caller is responsible for the
storage for the array for the fields. It is OK if the array is allocate
on the stack.</dd>
<dt style="font-family: courier;">removeField</dt>
<dd>Remove the field at the specified index. An exception is thrown if the
index is out of bounds.</dd>
</dl>
<p><span style="font-family: courier;">FieldCreate</span> has the methods:</p>
@@ -972,8 +987,7 @@ public:
void setImmutable();
FieldConstPtr getField() ;
PVStructure * getParent() ;
void replacePVField(PVField * newPVField);
void renameField(String newName);
bool renameField(String newName);
void postPut() ;
void setPostHandler(PostHandler *postHandler);
virtual void toString(StringBuilder buf) ;
@@ -982,7 +996,6 @@ public:
virtual bool operator!=(PVField &amp;pv) = 0;
protected:
PVField(PVStructure *parent,FieldConstPtr field);
void replaceStructure(PVStructure *pvStructure);
private:
};</pre>
@@ -1032,12 +1045,12 @@ are:</p>
<dt style="font-family: courier;">getParent</dt>
<dd>Get the interface for the parent or null if this is the top level
PVStructure.</dd>
<dt style="font-family: courier;">replacePVField</dt>
<dd>Replace this PVField. This is called by support code that wants to
replace the default implementation of a data field with it's own
implementation.</dd>
<dt style="font-family: courier;">renameField</dt>
<dd>Rename the field name.</dd>
<dd>Rename the field name.
(false,true) is returned if the name (was not,was) changed.
It is not changed if the field is an an element of a structure that
already has a field with the same name.
</dd>
<dt style="font-family: courier;">postPut</dt>
<dd>If a postHandler is registered it is called otherwise no action is
taken.</dd>
@@ -1668,8 +1681,7 @@ introspection interface must be used. The following shows an example:</p>
structure-&gt;incReferenceCount();
structureArray[2] = pvDataCreate-&gt;createPVStructure(0,structure);
powerSupplyArray-&gt;put(0,3,structureArray,0);
}
</pre>
}</pre>
<p>Note that incReferenceCount is called before each element is created.</p>

View File

@@ -153,70 +153,17 @@ FieldConstPtr PVField::getField() {return pImpl->field;}
PVStructure * PVField::getParent() {return pImpl->parent;}
void PVField::replacePVField(PVField * newPVField)
{
PVStructure *parent = getParent();
if(parent==0) {
String message("PVField::replacePVField no parent");
throw std::invalid_argument(message);
}
PVFieldPtrArray pvFields = parent->getPVFields();
int index = -1;
String fieldName = pImpl->field->getFieldName();
int length = parent->getStructure()->getNumberFields();
for(int i=0; i<length; i++) {
PVField *pvField = pvFields[i];
if(pvField->getField()->getFieldName().compare(fieldName) ==0) {
index = i;
break;
}
}
if(index==-1) {
String message("PVField::replacePVField did not find field in parent");
throw std::logic_error(message);
}
pvFields[index] = newPVField;
parent->replaceStructure(parent,length);
}
void PVField::renameField(String newName)
bool PVField::renameField(String newName)
{
FieldCreate *fieldCreate = getFieldCreate();
switch(pImpl->field->getType()) {
case scalar: {
ScalarConstPtr scalar = static_cast<ScalarConstPtr>(pImpl->field);
scalar = fieldCreate->createScalar(newName, scalar->getScalarType());
pImpl->field = scalar;
break;
}
case scalarArray: {
ScalarArrayConstPtr array =
static_cast<ScalarArrayConstPtr>(pImpl->field);
array = fieldCreate->createScalarArray(
newName, array->getElementType());
pImpl->field = array;
break;
}
case structure: {
StructureConstPtr structure =
static_cast<StructureConstPtr>(pImpl->field);
FieldConstPtrArray origFields = structure->getFields();
int numberFields = structure->getNumberFields();
structure = fieldCreate->createStructure(
newName,numberFields,origFields);
pImpl->field = structure;
break;
}
case structureArray: {
StructureArrayConstPtr structureArray =
static_cast<StructureArrayConstPtr>(pImpl->field);
structureArray = fieldCreate->createStructureArray(newName,
structureArray->getStructure());
pImpl->field = structureArray;
}
if(pImpl->parent!=0) {
StructureConstPtr structure = pImpl->parent->getStructure();
int index = structure->getFieldIndex(newName);
if(index>=0) return false;
}
String message("PVField::renameField logic error. should not get here");
throw std::logic_error(message);
Field * field = const_cast<Field *>(pImpl->field);
field->renameField(newName);
return true;
}
void PVField::postPut()
@@ -311,38 +258,5 @@ void PVField::computeOffset(PVField * pvField,int offset) {
pvField->pImpl->nextFieldOffset = nextOffset;
}
void PVField::replaceStructure(PVStructure *pvStructure,int length)
{
PVFieldPtrArray pvFields = pvStructure->getPVFields();
StructureConstPtr old = static_cast<StructureConstPtr>(pImpl->field);
if(old->getNumberFields() == length) {
FieldConstPtrArray fields = old->getFields();
for(int i=0; i<length; i++) {
FieldConstPtr newField = pvFields[i]->getField();
FieldConstPtr oldField = fields[i];
if(newField==oldField) continue;
oldField->decReferenceCount();
fields[i] = newField;
}
return;
}
FieldConstPtrArray newFields = new FieldConstPtr[length];
for(int i=0; i<length; i++) {
FieldConstPtr field = pvFields[i]->getField();
field->incReferenceCount();
newFields[i] = field;
}
StructureConstPtr newStructure = getFieldCreate()->createStructure(
pImpl->field->getFieldName(),length, newFields);
pImpl->field->decReferenceCount();
pImpl->field = newStructure;
PVStructure *parent = pImpl->parent;
if(parent!=0) {
parent->replaceStructure(
parent,parent->getStructure()->getNumberFields());
}
}
}}
#endif /* ABSTRACTPVFIELD_H */

View File

@@ -121,6 +121,8 @@ namespace epics { namespace pvData {
void PVStructure::appendPVField(PVFieldPtr pvField)
{
Structure *structure = const_cast<Structure *>(getStructure());
structure->appendField(pvField->getField());
int origLength = pImpl->numberFields;
PVFieldPtrArray oldPVFields = pImpl->pvFields;
PVFieldPtrArray newPVFields = new PVFieldPtr[origLength + 1];
@@ -132,11 +134,14 @@ namespace epics { namespace pvData {
delete[] pImpl->pvFields;
pImpl->pvFields = newPVFields;
pImpl->numberFields = origLength + 1;
PVField::replaceStructure(this,pImpl->numberFields);
}
void PVStructure::appendPVFields(int numberNewFields,PVFieldPtrArray pvFields)
{
Structure *structure = const_cast<Structure *>(getStructure());
FieldConstPtr fields[numberNewFields];
for(int i=0; i<numberNewFields; i++) fields[i] = pvFields[i]->getField();
structure->appendFields(numberNewFields,fields);
int origLength = pImpl->numberFields;
PVFieldPtrArray oldPVFields = pImpl->pvFields;
int numberFields = origLength + numberNewFields;
@@ -150,7 +155,6 @@ namespace epics { namespace pvData {
delete[] pImpl->pvFields;
pImpl->pvFields = newPVFields;
pImpl->numberFields = numberFields;
PVField::replaceStructure(this,numberFields);
}
void PVStructure::removePVField(String fieldName)
@@ -167,14 +171,19 @@ namespace epics { namespace pvData {
PVFieldPtrArray origPVFields = pImpl->pvFields;
PVFieldPtrArray newPVFields = new PVFieldPtr[newLength];
int newIndex = 0;
int indRemove = -1;
for(int i=0; i<origLength; i++) {
if(origPVFields[i]==pvField) continue;
newPVFields[newIndex++] = origPVFields[i];
if(origPVFields[i]==pvField) {
indRemove = i;
} else {
newPVFields[newIndex++] = origPVFields[i];
}
}
Structure *structure = const_cast<Structure *>(getStructure());
structure->removeField(indRemove);
delete[] pImpl->pvFields;
pImpl->pvFields = newPVFields;
pImpl->numberFields = newLength;
PVField::replaceStructure(this,newLength);
}
PVBoolean *PVStructure::getBooleanField(String fieldName)

View File

@@ -96,6 +96,11 @@ String Field::getFieldName() const {return pImpl->fieldName;}
Type Field::getType() const {return pImpl->type;}
void Field::renameField(String newName)
{
pImpl->fieldName = newName;
}
void Field::incReferenceCount() const {
Lock xx(&globalMutex);
pImpl->referenceCount++;
@@ -321,6 +326,44 @@ int Structure::getFieldIndex(String fieldName) const {
return -1;
}
void Structure::appendField(FieldConstPtr field)
{
FieldConstPtr *newFields = new FieldConstPtr[numberFields+1];
for(int i=0; i<numberFields; i++) newFields[i] = fields[i];
newFields[numberFields] = field;
delete[] fields;
fields = newFields;
numberFields++;
}
void Structure::appendFields(int numberNew,FieldConstPtrArray nfields)
{
FieldConstPtr *newFields = new FieldConstPtr[numberFields+numberNew];
for(int i=0; i<numberFields; i++) newFields[i] = fields[i];
for(int i=0; i<numberNew; i++) newFields[numberFields+i] = nfields[i];
delete[] fields;
fields = newFields;
numberFields += numberNew;
}
void Structure::removeField(int index)
{
if(index<0 || index>=numberFields) {
throw std::invalid_argument(
String("Structure::removeField index out of bounds"));
}
FieldConstPtr *newFields = new FieldConstPtr[numberFields-1];
fields[index]->decReferenceCount();
int ind=0;
for(int i=0; i<numberFields; i++) {
if(i==index) continue;
newFields[ind++] = fields[i];
}
delete[] fields;
fields = newFields;
--numberFields;
}
void Structure::toString(StringBuilder buffer,int indentLevel) const{
*buffer += "structure";
Field::toString(buffer,indentLevel);

View File

@@ -96,8 +96,7 @@ public:
void setImmutable();
FieldConstPtr getField() ;
PVStructure * getParent() ;
void replacePVField(PVField * newPVField);
void renameField(String newName);
bool renameField(String newName);
void postPut() ;
void setPostHandler(PostHandler *postHandler);
virtual void toString(StringBuilder buf) ;
@@ -106,7 +105,6 @@ public:
virtual bool operator!=(PVField &pv) = 0;
protected:
PVField(PVStructure *parent,FieldConstPtr field);
void replaceStructure(PVStructure *pvStructure,int numberFields);
private:
class PVFieldPvt *pImpl;
static void computeOffset(PVField *pvField);

View File

@@ -64,6 +64,7 @@ public:
Type getType() const;
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
void renameField(String newName);
void incReferenceCount() const;
void decReferenceCount() const;
void dumpReferenceCount(StringBuilder buf,int indentLevel) const;
@@ -128,6 +129,9 @@ public:
FieldConstPtr getField(String fieldName) const;
int getFieldIndex(String fieldName) const;
FieldConstPtrArray getFields() const {return fields;}
void appendField(FieldConstPtr field);
void appendFields(int numberFields,FieldConstPtrArray fields);
void removeField(int index);
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
protected:

View File

@@ -7,6 +7,7 @@ system ("./testLinkedList.pl");
system ("./testIntrospect.pl");
system ("./testPVData.pl");
system ("./testPVStructureArray.pl");
system ("./testPVAppend.pl");
system ("./testPVAuxInfo.pl");
system ("./testTimeStamp.pl");
system ("./testTimer.pl");

View File

@@ -1,20 +1,20 @@
Time test
diff 23.955010 milliSeconds
time per iteration 23.955010 microseconds
time per addTail/removeHead 0.011978 microseconds
diff 23.579571 milliSeconds
time per iteration 23.579571 microseconds
time per addTail/removeHead 0.011790 microseconds
Time test locked
diff 176.706476 milliSeconds
time per iteration 176.706476 microseconds
time per addTail/removeHead 0.088353 microseconds
diff 179.506759 milliSeconds
time per iteration 179.506759 microseconds
time per addTail/removeHead 0.089753 microseconds
Time std::list test
diff 631.501215 milliSeconds
time per iteration 631.501215 microseconds
time per addTail/removeHead 0.315751 microseconds
diff 632.658369 milliSeconds
time per iteration 632.658369 microseconds
time per addTail/removeHead 0.316329 microseconds
Time std::list test locked
diff 787.995967 milliSeconds
time per iteration 787.995967 microseconds
time per addTail/removeHead 0.393998 microseconds
diff 789.969392 milliSeconds
time per iteration 789.969392 microseconds
time per addTail/removeHead 0.394985 microseconds

View File

@@ -8,7 +8,27 @@ structure parent
string value bla
structure child2
string value bla
field: totalConstruct 107 totalDestruct 101 ACTIVE 6
pvField: totalConstruct 8 totalDestruct 8
structure parent
structure child1
string Joe Good Guy
string Mary Good Girl
structure child2
string Bill Bad Guy
string Jane Bad Girl
structure parent
structure child1
string Joe Good Guy
string Mary Good Girl
structure child2
string Joe Bad Guy
string Jane Bad Girl
structure parent
structure child1
string Joe Good Guy
string Mary Good Girl
structure child2
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

View File

@@ -8,7 +8,27 @@ structure parent
string value bla
structure child2
string value bla
field: totalConstruct 107 totalDestruct 101 ACTIVE 6
pvField: totalConstruct 8 totalDestruct 8
structure parent
structure child1
string Joe Good Guy
string Mary Good Girl
structure child2
string Bill Bad Guy
string Jane Bad Girl
structure parent
structure child1
string Joe Good Guy
string Mary Good Girl
structure child2
string Joe Bad Guy
string Jane Bad Girl
structure parent
structure child1
string Joe Good Guy
string Mary Good Girl
structure child2
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

View File

@@ -283,7 +283,7 @@ structure string
timeStamp timeStamp
long secondsPastEpoch 0
int nanoSeconds 0
field: totalConstruct 136 totalDestruct 135 ACTIVE 1
field: totalConstruct 135 totalDestruct 135
pvField: totalConstruct 281 totalDestruct 281
linkedListNode: totalConstruct 5 totalDestruct 5
linkedList: totalConstruct 1 totalDestruct 1

View File

@@ -1,4 +0,0 @@
286c286
< field: totalConstruct 136 totalDestruct 135 ACTIVE 1
---
> field: totalConstruct 136 totalDestruct 136

View File

@@ -283,7 +283,7 @@ structure string
timeStamp timeStamp
long secondsPastEpoch 0
int nanoSeconds 0
field: totalConstruct 136 totalDestruct 136
field: totalConstruct 135 totalDestruct 135
pvField: totalConstruct 281 totalDestruct 281
linkedListNode: totalConstruct 5 totalDestruct 5
linkedList: totalConstruct 1 totalDestruct 1

View File

@@ -1 +1 @@
time per call 40.790343 microseconds
time per call 32.876347 microseconds

View File

@@ -1,5 +1,5 @@
current 1295465466 621311375 milliSec 1295465466621
2011.01.19 14:31:06 621311375 nanoSeconds isDst false
current 1295532583 699024477 milliSec 1295532583699
2011.01.20 09:09:43 699024477 nanoSeconds isDst false
fromTime_t
current 1295465466 0 milliSec 1295465466000
2011.01.19 14:31:06 0 nanoSeconds isDst false
current 1295532583 0 milliSec 1295532583000
2011.01.20 09:09:43 0 nanoSeconds isDst false

View File

@@ -1,6 +1,6 @@
one requested 0.400000 diff 0.400195 seconds
two requested 0.200000 diff 0.200170 seconds
one requested 0.200000 diff 0.200124 seconds
two requested 0.400000 diff 0.400223 seconds
one requested 0.000000 diff 0.000039 seconds
two requested 0.000000 diff 0.000060 seconds
one requested 0.400000 diff 0.400259 seconds
two requested 0.200000 diff 0.200178 seconds
one requested 0.200000 diff 0.200145 seconds
two requested 0.400000 diff 0.400165 seconds
one requested 0.000000 diff 0.000136 seconds
two requested 0.000000 diff 0.000173 seconds

View File

@@ -34,7 +34,7 @@ static String alarmTimeStamp("alarm,timeStamp");
static String alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm");
static String allProperties("alarm,timeStamp,display,control,valueAlarm");
static void testAppend(FILE * fd)
static void testAppendSimple(FILE * fd)
{
FieldConstPtrArray fields = new FieldConstPtr[0];
PVStructure *pvParent = pvDataCreate->createPVStructure(
@@ -54,11 +54,15 @@ static void testAppend(FILE * fd)
pvParent->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
delete pvParent;
}
static void testAppendMore(FILE * fd)
{
PVStructure* pvStructure = pvDataCreate->createPVStructure(
0,"parent", 0);
PVStructure* pvChild1 = pvDataCreate->createPVStructure(
pvStructure, "child1", 0);
pvStringField = static_cast<PVString*>(
PVString *pvStringField = static_cast<PVString*>(
pvDataCreate->createPVScalar(pvChild1,"value", pvString));
pvStringField->put("bla");
pvChild1->appendPVField(pvStringField);
@@ -76,6 +80,52 @@ static void testAppend(FILE * fd)
delete pvStructure;
}
static void append2(PVStructure* pvStructure,
const char *oneName,const char *twoName,
const char *oneValue,const char *twoValue)
{
PVField* array[2];
PVString *pvStringField = static_cast<PVString*>(
pvDataCreate->createPVScalar(pvStructure,oneName, pvString));
pvStringField->put(oneValue);
array[0] = pvStringField;
pvStringField = static_cast<PVString*>(
pvDataCreate->createPVScalar(pvStructure,twoName, pvString));
pvStringField->put(twoValue);
array[1] = pvStringField;
pvStructure->appendPVFields(2,array);
}
static void testAppends(FILE * fd)
{
PVField* array[2];
PVStructure* pvStructure = pvDataCreate->createPVStructure(
0,"parent", 0);
PVStructure* pvChild = pvDataCreate->createPVStructure(
pvStructure, "child1", 0);
append2(pvChild,"Joe","Mary","Good Guy","Good Girl");
array[0] = pvChild;
pvChild = pvDataCreate->createPVStructure(
pvStructure, "child2", 0);
append2(pvChild,"Bill","Jane","Bad Guy","Bad Girl");
array[1] = pvChild;
pvStructure->appendPVFields(2,array);
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
PVField *pvField = pvStructure->getSubField("child2.Bill");
assert(pvField!=0);
bool ok = pvField->renameField("Joe");
assert(ok);
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
pvField->getParent()->removePVField("Joe");
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
delete pvStructure;
}
int main(int argc,char *argv[])
{
char *fileName = 0;
@@ -89,7 +139,9 @@ int main(int argc,char *argv[])
standardField = getStandardField();
standardPVField = getStandardPVField();
convert = getConvert();
testAppend(fd);
testAppendSimple(fd);
testAppendMore(fd);
testAppends(fd);
getShowConstructDestruct()->showDeleteStaticExit(fd);
return(0);
}