1) implemented noDefaultMethods. See effective C++ Item 6. There it is called Uncopyable

2) implemented Lock. See effective C++ item 14.
     This is as easy to use as Java synchronize.
3) wrapper on top of std::string. All usage of string in pvData is one of:
      String - Just a std::string
     StringBuilder - Used where StringBuilder is used in Java
     StringConst - Just a "std::string const". This is used wherever String is used in Java
     StringConstArray - Just like a String[] in Java.
4) The reference counting (incReferenceCount and decReferenceCount) are now private. It is completely handled by the implenentaion.
    NO code that uses pvData needs even know about reference counting.
This commit is contained in:
Marty Kraimer
2010-09-27 08:33:10 -04:00
parent dd6ecf9bec
commit f6c9b0eea3
26 changed files with 377 additions and 522 deletions

View File

@@ -3,13 +3,14 @@
#include <cstdlib>
#include <string>
#include <cstdio>
#include <epicsMutex.h>
#include <lock.h>
#include "pvIntrospect.h"
#include "factory.h"
namespace epics { namespace pvData {
static void newLine(StringPtr buffer, int indentLevel)
static DebugLevel debugLevel = highDebug;
static void newLine(StringBuilder buffer, int indentLevel)
{
*buffer += "\n";
for(int i=0; i<indentLevel; i++) *buffer += " ";
@@ -19,25 +20,23 @@ namespace epics { namespace pvData {
class BaseField : public Field {
public:
BaseField(StringConstPtr fieldName,Type type);
BaseField(StringConst fieldName,Type type);
virtual ~BaseField();
virtual void decReferenceCount() const;
virtual void incReferenceCount() const {referenceCount++;}
virtual int getReferenceCount() const {return referenceCount;}
virtual StringConstPtr getFieldName() const {return &fieldName;}
virtual StringConst getFieldName() const {return fieldName;}
virtual Type getType() const {return type;}
virtual void toString(StringPtr buf) const {return toString(buf,0);}
virtual void toString(StringPtr buf,int indentLevel) const;
virtual void toString(StringBuilder buf) const {return toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
private:
BaseField(BaseField const & ); // not implemented
BaseField & operator=(BaseField const &); //not implemented
std::string const fieldName;
StringConst fieldName;
Type type;
mutable volatile int referenceCount;
};
BaseField::BaseField(StringConstPtr fieldName,Type type)
:fieldName(*fieldName),type(type), referenceCount(0){}
BaseField::BaseField(StringConst fieldName,Type type)
:fieldName(fieldName),type(type), referenceCount(0){}
BaseField::~BaseField() {
// note that c++ automatically calls destructor for fieldName
@@ -46,7 +45,7 @@ namespace epics { namespace pvData {
void BaseField::decReferenceCount() const {
if(referenceCount<=0) {
std::string message("logicError field ");
String message("logicError field ");
message += fieldName;
throw std::logic_error(message);
}
@@ -54,7 +53,7 @@ namespace epics { namespace pvData {
if(referenceCount==0) delete this;
}
void BaseField::toString(StringPtr buffer,int indentLevel) const{
void BaseField::toString(StringBuilder buffer,int indentLevel) const{
newLine(buffer,indentLevel);
*buffer += "field ";
*buffer += fieldName.c_str();
@@ -66,26 +65,26 @@ namespace epics { namespace pvData {
class BaseScalar: private BaseField,public Scalar {
public:
BaseScalar(StringConstPtr fieldName,ScalarType scalarType);
BaseScalar(StringConst fieldName,ScalarType scalarType);
virtual ~BaseScalar();
virtual void incReferenceCount() const {BaseField::incReferenceCount();}
virtual void decReferenceCount() const {BaseField::decReferenceCount();}
virtual int getReferenceCount() const {return BaseField::getReferenceCount();}
virtual StringConstPtr getFieldName() const{ return BaseField::getFieldName(); }
virtual StringConst getFieldName() const{ return BaseField::getFieldName(); }
virtual Type getType() const{return BaseField::getType();}
virtual ScalarType getScalarType() const { return scalarType;}
virtual void toString(StringPtr buf) const {toString(buf,0);}
virtual void toString(StringPtr buf,int indentLevel) const;
virtual void toString(StringBuilder buf) const {toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
private:
ScalarType scalarType;
};
BaseScalar::BaseScalar(StringConstPtr fieldName,ScalarType scalarType)
BaseScalar::BaseScalar(StringConst fieldName,ScalarType scalarType)
: BaseField(fieldName,scalar),scalarType(scalarType){}
BaseScalar::~BaseScalar() {}
void BaseScalar::toString(StringPtr buffer,int indentLevel) const{
void BaseScalar::toString(StringBuilder buffer,int indentLevel) const{
BaseField::toString(buffer,indentLevel);
*buffer += " scalarType ";
ScalarTypeFunc::toString(buffer,scalarType);
@@ -95,27 +94,27 @@ namespace epics { namespace pvData {
class BaseScalarArray: private BaseField,public ScalarArray {
public:
BaseScalarArray(StringConstPtr fieldName,ScalarType elementType);
BaseScalarArray(StringConst fieldName,ScalarType elementType);
virtual ~BaseScalarArray();
virtual void incReferenceCount() const {BaseField::incReferenceCount();}
virtual void decReferenceCount() const {BaseField::decReferenceCount();}
virtual int getReferenceCount() const {return BaseField::getReferenceCount();}
virtual StringConstPtr getFieldName() const{ return BaseField::getFieldName(); }
virtual StringConst getFieldName() const{ return BaseField::getFieldName(); }
virtual Type getType() const{return BaseField::getType();}
virtual ScalarType getElementType() const { return elementType;}
virtual void toString(StringPtr buf) const {toString(buf,0);}
virtual void toString(StringPtr buf,int indentLevel) const;
virtual void toString(StringBuilder buf) const {toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
private:
ScalarType elementType;
};
BaseScalarArray::BaseScalarArray
(StringConstPtr fieldName,ScalarType elementType)
(StringConst fieldName,ScalarType elementType)
: BaseField(fieldName,scalar),elementType(elementType){}
BaseScalarArray::~BaseScalarArray() {}
void BaseScalarArray::toString(StringPtr buffer,int indentLevel) const{
void BaseScalarArray::toString(StringBuilder buffer,int indentLevel) const{
BaseField::toString(buffer,indentLevel);
*buffer += " elementType ";
ScalarTypeFunc::toString(buffer,elementType);
@@ -125,39 +124,39 @@ namespace epics { namespace pvData {
class BaseStructure: private BaseField,public Structure {
public:
BaseStructure(StringConstPtr fieldName, int numberFields,FieldConstPtrArray fields);
BaseStructure(StringConst fieldName, int numberFields,FieldConstPtrArray fields);
virtual ~BaseStructure();
virtual void incReferenceCount() const {BaseField::incReferenceCount();}
virtual void decReferenceCount() const {BaseField::decReferenceCount();}
virtual int getReferenceCount() const {return BaseField::getReferenceCount();}
virtual StringConstPtr getFieldName() const{ return BaseField::getFieldName(); }
virtual StringConst getFieldName() const{ return BaseField::getFieldName(); }
virtual Type getType() const{return BaseField::getType();}
virtual int const getNumberFields() const {return numberFields;}
virtual FieldConstPtr getField(StringConstPtr fieldName) const;
virtual int getFieldIndex(StringConstPtr fieldName) const;
virtual FieldConstPtr getField(StringConst fieldName) const;
virtual int getFieldIndex(StringConst fieldName) const;
virtual FieldConstPtrArray getFields() const { return fields;}
virtual void toString(StringPtr buf) const {toString(buf,0);}
virtual void toString(StringPtr buf,int indentLevel) const;
virtual void toString(StringBuilder buf) const {toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
private:
int numberFields;
FieldConstPtrArray fields;
};
BaseStructure::BaseStructure (StringConstPtr fieldName,
BaseStructure::BaseStructure (StringConst fieldName,
int numberFields, FieldConstPtrArray fields)
: BaseField(fieldName,structure),
numberFields(numberFields),
fields(fields)
{
for(int i=0; i<numberFields; i++) {
StringConstPtr name = fields[i]->getFieldName();
StringConst name = fields[i]->getFieldName();
// look for duplicates
for(int j=i+1; j<numberFields; j++) {
StringConstPtr otherName = fields[j]->getFieldName();
int result = name->compare(*otherName);
StringConst otherName = fields[j]->getFieldName();
int result = name.compare(otherName);
if(result==0) {
std::string message("duplicate fieldName ");
message += *name;
String message("duplicate fieldName ");
message += name;
throw std::invalid_argument(message);
}
}
@@ -166,32 +165,32 @@ namespace epics { namespace pvData {
}
}
BaseStructure::~BaseStructure() {
if(debugLevel==highDebug) printf("~BaseStructure %s\n",BaseField::getFieldName()->c_str());
if(debugLevel==highDebug) printf("~BaseStructure %s\n",BaseField::getFieldName().c_str());
for(int i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
pfield->decReferenceCount();
}
}
FieldConstPtr BaseStructure::getField(StringConstPtr fieldName) const {
FieldConstPtr BaseStructure::getField(StringConst fieldName) const {
for(int i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
int result = fieldName->compare(*pfield->getFieldName());
int result = fieldName.compare(pfield->getFieldName());
if(result==0) return pfield;
}
return 0;
}
int BaseStructure::getFieldIndex(StringConstPtr fieldName) const {
int BaseStructure::getFieldIndex(StringConst fieldName) const {
for(int i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
int result = fieldName->compare(*pfield->getFieldName());
int result = fieldName.compare(pfield->getFieldName());
if(result==0) return i;
}
return -1;
}
void BaseStructure::toString(StringPtr buffer,int indentLevel) const{
void BaseStructure::toString(StringBuilder buffer,int indentLevel) const{
BaseField::toString(buffer,indentLevel);
*buffer += " {";
for(int i=0; i<numberFields; i++) {
@@ -206,23 +205,23 @@ namespace epics { namespace pvData {
class BaseStructureArray: private BaseField,public StructureArray {
public:
BaseStructureArray(StringConstPtr fieldName,StructureConstPtr structure);
BaseStructureArray(StringConst fieldName,StructureConstPtr structure);
virtual ~BaseStructureArray();
virtual void incReferenceCount() const {BaseField::incReferenceCount();}
virtual void decReferenceCount() const {BaseField::decReferenceCount();}
virtual int getReferenceCount() const {return BaseField::getReferenceCount();}
virtual StringConstPtr getFieldName() const{
virtual StringConst getFieldName() const{
return BaseField::getFieldName();
}
virtual Type getType() const{return BaseField::getType();}
virtual StructureConstPtr getStructure() const { return pstructure; }
virtual void toString(StringPtr buf) const {toString(buf,0);}
virtual void toString(StringPtr buf,int indentLevel) const;
virtual void toString(StringBuilder buf) const {toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
private:
StructureConstPtr pstructure;
};
BaseStructureArray::BaseStructureArray(StringConstPtr fieldName,StructureConstPtr structure)
BaseStructureArray::BaseStructureArray(StringConst fieldName,StructureConstPtr structure)
: BaseField(fieldName,structureArray),pstructure(structure)
{
pstructure->incReferenceCount();
@@ -234,7 +233,7 @@ namespace epics { namespace pvData {
}
void BaseStructureArray::toString(StringPtr buffer,int indentLevel) const {
void BaseStructureArray::toString(StringBuilder buffer,int indentLevel) const {
BaseField::toString(buffer,indentLevel);
*buffer += " structure ";
pstructure->toString(buffer,indentLevel + 1);
@@ -242,7 +241,7 @@ namespace epics { namespace pvData {
FieldCreate::FieldCreate(){};
ScalarConstPtr FieldCreate::createScalar(StringConstPtr fieldName,
ScalarConstPtr FieldCreate::createScalar(StringConst fieldName,
ScalarType scalarType) const
{
BaseScalar *baseScalar = new BaseScalar(fieldName,scalarType);
@@ -250,13 +249,13 @@ namespace epics { namespace pvData {
}
ScalarArrayConstPtr FieldCreate::createScalarArray(
StringConstPtr fieldName,ScalarType elementType) const
StringConst fieldName,ScalarType elementType) const
{
BaseScalarArray *baseScalarArray = new BaseScalarArray(fieldName,elementType);
return baseScalarArray;
}
StructureConstPtr FieldCreate::createStructure (
StringConstPtr fieldName,int numberFields,
StringConst fieldName,int numberFields,
FieldConstPtr fields[]) const
{
BaseStructure *baseStructure = new BaseStructure(
@@ -264,13 +263,13 @@ namespace epics { namespace pvData {
return baseStructure;
}
StructureArrayConstPtr FieldCreate::createStructureArray(
StringConstPtr fieldName,StructureConstPtr structure) const
StringConst fieldName,StructureConstPtr structure) const
{
BaseStructureArray *baseStructureArray = new BaseStructureArray(fieldName,structure);
return baseStructureArray;
}
FieldConstPtr FieldCreate::create(StringConstPtr fieldName,
FieldConstPtr FieldCreate::create(StringConst fieldName,
FieldConstPtr pfield) const
{
Type type = pfield->getType();
@@ -292,8 +291,8 @@ namespace epics { namespace pvData {
return createStructureArray(fieldName,pstructureArray->getStructure());
}
}
std::string message("field ");
message += *fieldName;
String message("field ");
message += fieldName;
throw std::logic_error(message);
}
@@ -306,10 +305,10 @@ namespace epics { namespace pvData {
};
FieldCreate * getFieldCreate() {
static epicsMutex *lock = new epicsMutex();
lock->lock();
static Mutex *mutex = new Mutex();
Lock xx(mutex);
if(instance==0) instance = new FieldCreateExt();
lock->unlock();
return instance;
}