Field de-duplication
add a global cache of Field instances to allow O(0) comparison of types.
This commit is contained in:
@@ -23,7 +23,7 @@ namespace epics { namespace pvData {
|
||||
* 1) same instance
|
||||
* 2) same type (field and scalar/element), same name, same subfields (if any)
|
||||
*/
|
||||
bool operator==(const Field& a, const Field& b)
|
||||
bool compare(const Field& a, const Field& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
@@ -33,53 +33,53 @@ bool operator==(const Field& a, const Field& b)
|
||||
case scalar: {
|
||||
const Scalar &A=static_cast<const Scalar&>(a);
|
||||
const Scalar &B=static_cast<const Scalar&>(b);
|
||||
return A==B;
|
||||
return compare(A, B);
|
||||
}
|
||||
case scalarArray: {
|
||||
const ScalarArray &A=static_cast<const ScalarArray&>(a);
|
||||
const ScalarArray &B=static_cast<const ScalarArray&>(b);
|
||||
return A==B;
|
||||
return compare(A, B);
|
||||
}
|
||||
case structure: {
|
||||
const Structure &A=static_cast<const Structure&>(a);
|
||||
const Structure &B=static_cast<const Structure&>(b);
|
||||
return A==B;
|
||||
return compare(A, B);
|
||||
}
|
||||
case structureArray: {
|
||||
const StructureArray &A=static_cast<const StructureArray&>(a);
|
||||
const StructureArray &B=static_cast<const StructureArray&>(b);
|
||||
return A==B;
|
||||
return compare(A, B);
|
||||
}
|
||||
case union_: {
|
||||
const Union &A=static_cast<const Union&>(a);
|
||||
const Union &B=static_cast<const Union&>(b);
|
||||
return A==B;
|
||||
return compare(A, B);
|
||||
}
|
||||
case unionArray: {
|
||||
const UnionArray &A=static_cast<const UnionArray&>(a);
|
||||
const UnionArray &B=static_cast<const UnionArray&>(b);
|
||||
return A==B;
|
||||
return compare(A, B);
|
||||
}
|
||||
default:
|
||||
throw std::logic_error("Invalid Field type in comparison");
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Scalar& a, const Scalar& b)
|
||||
bool compare(const Scalar& a, const Scalar& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getScalarType()==b.getScalarType();
|
||||
}
|
||||
|
||||
bool operator==(const ScalarArray& a, const ScalarArray& b)
|
||||
bool compare(const ScalarArray& a, const ScalarArray& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getElementType()==b.getElementType();
|
||||
}
|
||||
|
||||
bool operator==(const Structure& a, const Structure& b)
|
||||
bool compare(const Structure& a, const Structure& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
@@ -101,12 +101,12 @@ bool operator==(const Structure& a, const Structure& b)
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
bool compare(const StructureArray& a, const StructureArray& b)
|
||||
{
|
||||
return *(a.getStructure().get())==*(b.getStructure().get());
|
||||
}
|
||||
|
||||
bool operator==(const Union& a, const Union& b)
|
||||
bool compare(const Union& a, const Union& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
@@ -128,12 +128,12 @@ bool operator==(const Union& a, const Union& b)
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const UnionArray& a, const UnionArray& b)
|
||||
bool compare(const UnionArray& a, const UnionArray& b)
|
||||
{
|
||||
return *(a.getUnion().get())==*(b.getUnion().get());
|
||||
}
|
||||
|
||||
bool operator==(const BoundedString& a, const BoundedString& b)
|
||||
bool compare(const BoundedString& a, const BoundedString& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#include <epicsString.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
@@ -35,6 +36,46 @@ static DebugLevel debugLevel = lowDebug;
|
||||
size_t Field::num_instances;
|
||||
|
||||
|
||||
struct Field::Helper {
|
||||
static void hash(Field *fld) {
|
||||
std::ostringstream key;
|
||||
// hash the output of operator<<()
|
||||
// not efficient, but stable within this process.
|
||||
key<<(*fld);
|
||||
fld->m_hash = epicsStrHash(key.str().c_str(), 0xbadc0de1);
|
||||
}
|
||||
};
|
||||
|
||||
struct FieldCreate::Helper {
|
||||
template<typename FLD>
|
||||
static void cache(const FieldCreate *create, std::tr1::shared_ptr<FLD>& ent) {
|
||||
Field::Helper::hash(ent.get());
|
||||
|
||||
Lock G(create->mutex);
|
||||
// we examine raw pointers stored in create->cache, which is safe under create->mutex
|
||||
|
||||
std::pair<cache_t::iterator, cache_t::iterator> itp(create->cache.equal_range(ent->m_hash));
|
||||
for(; itp.first!=itp.second; ++itp.first) {
|
||||
Field* cent(itp.first->second);
|
||||
FLD* centx(dynamic_cast<FLD*>(cent));
|
||||
if(centx && compare(*centx, *ent)) {
|
||||
try{
|
||||
ent = std::tr1::static_pointer_cast<FLD>(cent->shared_from_this());
|
||||
return;
|
||||
}catch(std::tr1::bad_weak_ptr&){
|
||||
// we're racing destruction.
|
||||
// add a new entry.
|
||||
// Field::~Field is in the process of removing this old one.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create->cache.insert(std::make_pair(ent->m_hash, ent.get()));
|
||||
// cache cleaned from Field::~Field
|
||||
}
|
||||
};
|
||||
|
||||
Field::Field(Type type)
|
||||
: m_fieldType(type)
|
||||
{
|
||||
@@ -43,6 +84,18 @@ Field::Field(Type type)
|
||||
|
||||
Field::~Field() {
|
||||
REFTRACE_DECREMENT(num_instances);
|
||||
FieldCreatePtr create(getFieldCreate());
|
||||
|
||||
Lock G(create->mutex);
|
||||
|
||||
std::pair<FieldCreate::cache_t::iterator, FieldCreate::cache_t::iterator> itp(create->cache.equal_range(m_hash));
|
||||
for(; itp.first!=itp.second; ++itp.first) {
|
||||
Field* cent(itp.first->second);
|
||||
if(cent==this) {
|
||||
create->cache.erase(itp.first);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1075,10 +1128,9 @@ ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
|
||||
|
||||
BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) const
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<BoundedString> s(new BoundedString(maxLength), Field::Deleter());
|
||||
BoundedStringConstPtr sa = s;
|
||||
return sa;
|
||||
std::tr1::shared_ptr<BoundedString> s(new BoundedString(maxLength));
|
||||
Helper::cache(this, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
|
||||
@@ -1100,10 +1152,9 @@ ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType,
|
||||
THROW_EXCEPTION2(std::invalid_argument, strm.str());
|
||||
}
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<ScalarArray> s(new FixedScalarArray(elementType, size), Field::Deleter());
|
||||
ScalarArrayConstPtr sa = s;
|
||||
return sa;
|
||||
std::tr1::shared_ptr<ScalarArray> s(new FixedScalarArray(elementType, size));
|
||||
Helper::cache(this, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType, size_t size) const
|
||||
@@ -1114,10 +1165,9 @@ ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType
|
||||
THROW_EXCEPTION2(std::invalid_argument, strm.str());
|
||||
}
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size), Field::Deleter());
|
||||
ScalarArrayConstPtr sa = s;
|
||||
return sa;
|
||||
std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size));
|
||||
Helper::cache(this, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure () const
|
||||
@@ -1174,10 +1224,9 @@ StructureConstPtr FieldCreate::createStructure (
|
||||
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
|
||||
{
|
||||
validateFieldNames(fieldNames);
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields), Field::Deleter());
|
||||
StructureConstPtr structure = sp;
|
||||
return structure;
|
||||
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
@@ -1186,29 +1235,26 @@ StructureConstPtr FieldCreate::createStructure (
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
validateFieldNames(fieldNames);
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields,id), Field::Deleter());
|
||||
StructureConstPtr structure = sp;
|
||||
return structure;
|
||||
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields,id));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
StructureArrayConstPtr FieldCreate::createStructureArray(
|
||||
StructureConstPtr const & structure) const
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<StructureArray> sp(new StructureArray(structure), Field::Deleter());
|
||||
StructureArrayConstPtr structureArray = sp;
|
||||
return structureArray;
|
||||
std::tr1::shared_ptr<StructureArray> sp(new StructureArray(structure));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
UnionConstPtr FieldCreate::createUnion (
|
||||
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
|
||||
{
|
||||
validateFieldNames(fieldNames);
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields), Field::Deleter());
|
||||
UnionConstPtr punion = sp;
|
||||
return punion;
|
||||
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
UnionConstPtr FieldCreate::createUnion (
|
||||
@@ -1217,10 +1263,9 @@ UnionConstPtr FieldCreate::createUnion (
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
validateFieldNames(fieldNames);
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields,id), Field::Deleter());
|
||||
UnionConstPtr punion = sp;
|
||||
return punion;
|
||||
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields,id));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
UnionConstPtr FieldCreate::createVariantUnion () const
|
||||
@@ -1231,10 +1276,9 @@ UnionConstPtr FieldCreate::createVariantUnion () const
|
||||
UnionArrayConstPtr FieldCreate::createUnionArray(
|
||||
UnionConstPtr const & punion) const
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<UnionArray> sp(new UnionArray(punion), Field::Deleter());
|
||||
UnionArrayConstPtr unionArray = sp;
|
||||
return unionArray;
|
||||
std::tr1::shared_ptr<UnionArray> sp(new UnionArray(punion));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
UnionArrayConstPtr FieldCreate::createVariantUnionArray () const
|
||||
@@ -1363,12 +1407,10 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
|
||||
size_t size = SerializeHelper::readSize(buffer, control);
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(
|
||||
new BoundedString(size),
|
||||
Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
new BoundedString(size));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("invalid type encoding");
|
||||
@@ -1393,19 +1435,17 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(
|
||||
new FixedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
|
||||
Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
new FixedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(
|
||||
new BoundedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
|
||||
Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
new BoundedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
}
|
||||
else if (typeCode == 0x80)
|
||||
@@ -1417,9 +1457,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
// Type type = Type.structureArray;
|
||||
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(new StructureArray(elementStructure), Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
std::tr1::shared_ptr<Field> sp(new StructureArray(elementStructure));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
else if (typeCode == 0x81)
|
||||
{
|
||||
@@ -1430,9 +1470,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
// Type type = Type.unionArray;
|
||||
UnionConstPtr elementUnion = std::tr1::static_pointer_cast<const Union>(control->cachedDeserialize(buffer));
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(new UnionArray(elementUnion), Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
std::tr1::shared_ptr<Field> sp(new UnionArray(elementUnion));
|
||||
Helper::cache(this, sp);
|
||||
return sp;
|
||||
}
|
||||
else if (typeCode == 0x82)
|
||||
{
|
||||
@@ -1481,23 +1521,21 @@ FieldCreate::FieldCreate()
|
||||
{
|
||||
for (int i = 0; i <= MAX_SCALAR_TYPE; i++)
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Scalar> sp(new Scalar(static_cast<ScalarType>(i)), Field::Deleter());
|
||||
ScalarConstPtr p = sp;
|
||||
scalars.push_back(p);
|
||||
std::tr1::shared_ptr<Scalar> sp(new Scalar(static_cast<ScalarType>(i)));
|
||||
Helper::cache(this, sp);
|
||||
scalars.push_back(sp);
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<ScalarArray> spa(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter());
|
||||
ScalarArrayConstPtr pa = spa;
|
||||
std::tr1::shared_ptr<ScalarArray> spa(new ScalarArray(static_cast<ScalarType>(i)));
|
||||
Helper::cache(this, spa);
|
||||
scalarArrays.push_back(spa);
|
||||
}
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Union> su(new Union(), Field::Deleter());
|
||||
std::tr1::shared_ptr<Union> su(new Union());
|
||||
Helper::cache(this, su);
|
||||
variantUnion = su;
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<UnionArray> sua(new UnionArray(variantUnion), Field::Deleter());
|
||||
std::tr1::shared_ptr<UnionArray> sua(new UnionArray(variantUnion));
|
||||
Helper::cache(this, sua);
|
||||
variantUnionArray = sua;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <pv/lock.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/byteBuffer.h>
|
||||
@@ -347,6 +349,8 @@ protected:
|
||||
Field(Type type);
|
||||
private:
|
||||
const Type m_fieldType;
|
||||
unsigned int m_hash;
|
||||
struct Helper;
|
||||
|
||||
friend class StructureArray;
|
||||
friend class Structure;
|
||||
@@ -354,7 +358,6 @@ private:
|
||||
friend class StandardField;
|
||||
friend class BasePVStructureArray;
|
||||
friend class FieldCreate;
|
||||
struct Deleter{void operator()(Field *p){delete p;}};
|
||||
EPICS_NOT_COPYABLE(Field)
|
||||
};
|
||||
|
||||
@@ -489,7 +492,6 @@ public:
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const OVERRIDE;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control) OVERRIDE FINAL;
|
||||
|
||||
protected:
|
||||
virtual ~ScalarArray();
|
||||
private:
|
||||
const std::string getIDScalarArrayLUT() const;
|
||||
@@ -525,7 +527,6 @@ public:
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const OVERRIDE FINAL;
|
||||
|
||||
protected:
|
||||
virtual ~BoundedScalarArray();
|
||||
private:
|
||||
std::size_t size;
|
||||
@@ -558,7 +559,6 @@ public:
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const OVERRIDE FINAL;
|
||||
|
||||
protected:
|
||||
virtual ~FixedScalarArray();
|
||||
private:
|
||||
std::size_t size;
|
||||
@@ -599,6 +599,7 @@ protected:
|
||||
* @param structure The introspection interface for the elements.
|
||||
*/
|
||||
StructureArray(StructureConstPtr const & structure);
|
||||
public:
|
||||
virtual ~StructureArray();
|
||||
private:
|
||||
StructureConstPtr pstructure;
|
||||
@@ -639,6 +640,7 @@ protected:
|
||||
* @param _punion The introspection interface for the elements.
|
||||
*/
|
||||
UnionArray(UnionConstPtr const & _punion);
|
||||
public:
|
||||
virtual ~UnionArray();
|
||||
private:
|
||||
UnionConstPtr punion;
|
||||
@@ -1221,11 +1223,19 @@ public:
|
||||
|
||||
private:
|
||||
FieldCreate();
|
||||
|
||||
|
||||
// const after ctor
|
||||
std::vector<ScalarConstPtr> scalars;
|
||||
std::vector<ScalarArrayConstPtr> scalarArrays;
|
||||
UnionConstPtr variantUnion;
|
||||
UnionArrayConstPtr variantUnionArray;
|
||||
|
||||
mutable Mutex mutex;
|
||||
typedef std::multimap<unsigned int, Field*> cache_t;
|
||||
mutable cache_t cache;
|
||||
|
||||
struct Helper;
|
||||
friend class Field;
|
||||
EPICS_NOT_COPYABLE(FieldCreate)
|
||||
};
|
||||
|
||||
@@ -1278,32 +1288,35 @@ OP(pvDouble, double)
|
||||
OP(pvString, std::string)
|
||||
#undef OP
|
||||
|
||||
bool epicsShareExtern operator==(const Field&, const Field&);
|
||||
bool epicsShareExtern operator==(const Scalar&, const Scalar&);
|
||||
bool epicsShareExtern operator==(const ScalarArray&, const ScalarArray&);
|
||||
bool epicsShareExtern operator==(const Structure&, const Structure&);
|
||||
bool epicsShareExtern operator==(const StructureArray&, const StructureArray&);
|
||||
bool epicsShareExtern operator==(const Union&, const Union&);
|
||||
bool epicsShareExtern operator==(const UnionArray&, const UnionArray&);
|
||||
bool epicsShareExtern operator==(const BoundedString&, const BoundedString&);
|
||||
bool epicsShareExtern compare(const Field&, const Field&);
|
||||
bool epicsShareExtern compare(const Scalar&, const Scalar&);
|
||||
bool epicsShareExtern compare(const ScalarArray&, const ScalarArray&);
|
||||
bool epicsShareExtern compare(const Structure&, const Structure&);
|
||||
bool epicsShareExtern compare(const StructureArray&, const StructureArray&);
|
||||
bool epicsShareExtern compare(const Union&, const Union&);
|
||||
bool epicsShareExtern compare(const UnionArray&, const UnionArray&);
|
||||
bool epicsShareExtern compare(const BoundedString&, const BoundedString&);
|
||||
|
||||
static inline bool operator!=(const Field& a, const Field& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Scalar& a, const Scalar& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const ScalarArray& a, const ScalarArray& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Structure& a, const Structure& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const StructureArray& a, const StructureArray& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Union& a, const Union& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const UnionArray& a, const UnionArray& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const BoundedString& a, const BoundedString& b)
|
||||
{return !(a==b);}
|
||||
/** Equality with other Field
|
||||
*
|
||||
* The creation process of class FieldCreate ensures that identical field definitions
|
||||
* will share the same instance. So pointer equality is sufficient to show defintion
|
||||
* equality. If in doubt, compare() will do an full test.
|
||||
*/
|
||||
#define MAKE_COMPARE(CLASS) \
|
||||
static FORCE_INLINE bool operator==(const CLASS& a, const CLASS& b) {return (void*)&a==(void*)&b;} \
|
||||
static FORCE_INLINE bool operator!=(const CLASS& a, const CLASS& b) {return !(a==b);}
|
||||
|
||||
MAKE_COMPARE(Field)
|
||||
MAKE_COMPARE(Scalar)
|
||||
MAKE_COMPARE(ScalarArray)
|
||||
MAKE_COMPARE(Structure)
|
||||
MAKE_COMPARE(StructureArray)
|
||||
MAKE_COMPARE(Union)
|
||||
MAKE_COMPARE(UnionArray)
|
||||
MAKE_COMPARE(BoundedString)
|
||||
|
||||
#undef MAKE_COMPARE
|
||||
}}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/pvUnitTest.h>
|
||||
#include <pv/current_function.h>
|
||||
|
||||
#include <pv/standardField.h>
|
||||
|
||||
@@ -629,6 +631,8 @@ void testStructureId() {
|
||||
|
||||
void serializationFieldTest(FieldConstPtr const & field)
|
||||
{
|
||||
testShow()<<CURRENT_FUNCTION<<"\n"<<field;
|
||||
|
||||
buffer->clear();
|
||||
|
||||
// serialize
|
||||
@@ -639,7 +643,7 @@ void serializationFieldTest(FieldConstPtr const & field)
|
||||
|
||||
FieldConstPtr deserializedField = getFieldCreate()->deserialize(buffer, control);
|
||||
|
||||
// must equal
|
||||
testShow()<<" after "<<(void*)field.get()<<" == "<<(void*)deserializedField.get();
|
||||
testOk1(*field == *deserializedField);
|
||||
}
|
||||
|
||||
|
||||
@@ -324,8 +324,8 @@ void test_extendStructure()
|
||||
<<"amended: "<<amended
|
||||
<<"expected: "<<expected;
|
||||
|
||||
testNotEqual(static_cast<const void*>(amended.get()),
|
||||
static_cast<const void*>(expected.get()));
|
||||
testEqual(static_cast<const void*>(amended.get()),
|
||||
static_cast<const void*>(expected.get()));
|
||||
testEqual(*amended, *expected);
|
||||
|
||||
testThrows(std::runtime_error,
|
||||
|
||||
Reference in New Issue
Block a user