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