add PVIFBuilder abstraction
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
#ifndef HELPER_H
|
||||
#define HELPER_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if __cplusplus>=201103L
|
||||
# define AUTO_VAL(NAME,VAL) auto NAME = VAL
|
||||
# define AUTO_REF(NAME,VAL) auto& NAME = VAL
|
||||
@ -13,4 +15,15 @@
|
||||
# error Require C++11 or G++
|
||||
#endif
|
||||
|
||||
namespace p2p {
|
||||
#if __cplusplus>=201103L
|
||||
template<typename T>
|
||||
using auto_ptr = std::unique_ptr<T>;
|
||||
#define PTRMOVE(AUTO) std::move(AUTO)
|
||||
#else
|
||||
using std::auto_ptr;
|
||||
#define PTRMOVE(AUTO) (AUTO)
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // HELPER_H
|
||||
|
@ -362,7 +362,9 @@ PDBProvider::PDBProvider(const epics::pvAccess::Configuration::shared_pointer &)
|
||||
|
||||
DBCH chan(mem.pvname);
|
||||
|
||||
builder->add(mem.pvfldname, PVIF::dtype(chan));
|
||||
info.builder.reset(new ScalarBuilder);
|
||||
|
||||
builder->add(mem.pvfldname, info.builder->dtype(chan));
|
||||
|
||||
info.attachment = mem.pvfldname;
|
||||
info.chan.swap(chan);
|
||||
@ -437,7 +439,7 @@ PDBProvider::PDBProvider(const epics::pvAccess::Configuration::shared_pointer &)
|
||||
info.evt_VALUE.index = info.evt_PROPERTY.index = i++;
|
||||
info.evt_VALUE.self = info.evt_PROPERTY.self = pv;
|
||||
|
||||
info.pvif.reset(PVIF::attach(info.chan,
|
||||
info.pvif.reset(info.builder->attach(info.chan,
|
||||
pv->complete->getSubFieldT<pvd::PVStructure>(info.attachment)));
|
||||
|
||||
info.evt_PROPERTY.create(event_context, info.chan, &pdb_group_event, DBE_PROPERTY);
|
||||
|
@ -173,7 +173,7 @@ PDBGroupPut::PDBGroupPut(const PDBGroupChannel::shared_pointer& channel,
|
||||
{
|
||||
PDBGroupPV::Info& info = channel->pv->members[i];
|
||||
|
||||
pvif[i].reset(PVIF::attach(info.chan,
|
||||
pvif[i].reset(info.builder->attach(info.chan,
|
||||
pvf->getSubFieldT<pvd::PVStructure>(info.attachment)
|
||||
));
|
||||
}
|
||||
@ -195,7 +195,7 @@ void PDBGroupPut::put(pvd::PVStructure::shared_pointer const & value,
|
||||
{
|
||||
PDBGroupPV::Info& info = channel->pv->members[i];
|
||||
|
||||
putpvif[i].reset(PVIF::attach(info.chan,
|
||||
putpvif[i].reset(info.builder->attach(info.chan,
|
||||
value->getSubFieldT<pvd::PVStructure>(info.attachment)
|
||||
));
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <pv/pvAccess.h>
|
||||
|
||||
#include "helper.h"
|
||||
#include "pvahelper.h"
|
||||
#include "pvif.h"
|
||||
#include "pdb.h"
|
||||
@ -34,10 +35,11 @@ struct epicsShareClass PDBGroupPV : public PDBPV
|
||||
|
||||
struct Info {
|
||||
DBCH chan;
|
||||
p2p::auto_ptr<PVIFBuilder> builder;
|
||||
std::string attachment;
|
||||
std::vector<size_t> triggers;
|
||||
DBManyLock locker; // lock only those channels being triggered
|
||||
std::auto_ptr<PVIF> pvif;
|
||||
p2p::auto_ptr<PVIF> pvif;
|
||||
DBEvent evt_VALUE, evt_PROPERTY;
|
||||
bool had_initial_VALUE, had_initial_PROPERTY;
|
||||
|
||||
|
@ -69,16 +69,17 @@ void pdb_single_event(void *user_arg, struct dbChannel *chan,
|
||||
PDBSinglePV::PDBSinglePV(DBCH& chan,
|
||||
const PDBProvider::shared_pointer& prov)
|
||||
:provider(prov)
|
||||
,builder(new ScalarBuilder)
|
||||
,evt_VALUE(this)
|
||||
,evt_PROPERTY(this)
|
||||
,hadevent_VALUE(false)
|
||||
,hadevent_PROPERTY(false)
|
||||
{
|
||||
this->chan.swap(chan);
|
||||
fielddesc = PVIF::dtype(this->chan);
|
||||
fielddesc = builder->dtype(this->chan);
|
||||
|
||||
complete = pvd::getPVDataCreate()->createPVStructure(fielddesc);
|
||||
pvif.reset(PVIF::attach(this->chan, complete));
|
||||
pvif.reset(builder->attach(this->chan, complete));
|
||||
|
||||
epics::atomic::increment(num_instances);
|
||||
}
|
||||
@ -206,7 +207,7 @@ PDBSinglePut::PDBSinglePut(const PDBSingleChannel::shared_pointer &channel,
|
||||
,requester(requester)
|
||||
,changed(new pvd::BitSet(channel->fielddesc->getNumberFields()))
|
||||
,pvf(pvd::getPVDataCreate()->createPVStructure(channel->fielddesc))
|
||||
,pvif(PVIF::attach(channel->pv->chan, pvf))
|
||||
,pvif(channel->pv->builder->attach(channel->pv->chan, pvf))
|
||||
,notifyBusy(0)
|
||||
,doProc(true)
|
||||
,doProcForce(false)
|
||||
@ -280,7 +281,7 @@ void PDBSinglePut::put(pvd::PVStructure::shared_pointer const & value,
|
||||
// TODO: dbNotify doesn't allow us for force processing
|
||||
|
||||
// assume value may be a different struct each time
|
||||
std::auto_ptr<PVIF> putpvif(PVIF::attach(channel->pv->chan, value));
|
||||
p2p::auto_ptr<PVIF> putpvif(channel->pv->builder->attach(channel->pv->chan, value));
|
||||
unsigned mask = putpvif->dbe(*changed);
|
||||
|
||||
if(mask&~DBE_VALUE) {
|
||||
@ -294,7 +295,7 @@ void PDBSinglePut::put(pvd::PVStructure::shared_pointer const & value,
|
||||
|
||||
notify.requestType = (mask&DBE_VALUE) ? putProcessRequest : processRequest;
|
||||
|
||||
wait_pvif = putpvif;
|
||||
wait_pvif = PTRMOVE(putpvif);
|
||||
wait_changed = changed;
|
||||
|
||||
dbProcessNotify(¬ify);
|
||||
@ -302,7 +303,7 @@ void PDBSinglePut::put(pvd::PVStructure::shared_pointer const & value,
|
||||
return; // skip notification
|
||||
} else {
|
||||
// assume value may be a different struct each time
|
||||
std::auto_ptr<PVIF> putpvif(PVIF::attach(channel->pv->chan, value));
|
||||
p2p::auto_ptr<PVIF> putpvif(channel->pv->builder->attach(channel->pv->chan, value));
|
||||
try{
|
||||
DBScanLocker L(chan);
|
||||
putpvif->get(*changed);
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <pv/pvAccess.h>
|
||||
|
||||
#include "helper.h"
|
||||
#include "pvahelper.h"
|
||||
#include "pvif.h"
|
||||
#include "pdb.h"
|
||||
@ -35,7 +36,8 @@ struct epicsShareClass PDBSinglePV : public PDBPV
|
||||
epicsMutex lock;
|
||||
|
||||
epics::pvData::BitSet scratch;
|
||||
std::auto_ptr<PVIF> pvif;
|
||||
p2p::auto_ptr<PVIFBuilder> builder;
|
||||
p2p::auto_ptr<PVIF> pvif;
|
||||
|
||||
epics::pvData::PVStructurePtr complete; // complete copy from subscription
|
||||
|
||||
@ -90,7 +92,7 @@ struct PDBSinglePut : public epics::pvAccess::ChannelPut,
|
||||
|
||||
epics::pvData::BitSetPtr changed, wait_changed;
|
||||
epics::pvData::PVStructurePtr pvf;
|
||||
std::auto_ptr<PVIF> pvif, wait_pvif;
|
||||
p2p::auto_ptr<PVIF> pvif, wait_pvif;
|
||||
processNotify notify;
|
||||
int notifyBusy; // atomic: 0 - idle, 1 - active, 2 - being cancelled
|
||||
|
||||
|
@ -285,7 +285,7 @@ void pvaOpenLink(DBLINK *plink)
|
||||
void pvaRemoveLink(struct dbLocker *locker, DBLINK *plink)
|
||||
{
|
||||
try {
|
||||
std::auto_ptr<pvaLink> self((pvaLink*)plink->value.json.jlink);
|
||||
p2p::auto_ptr<pvaLink> self((pvaLink*)plink->value.json.jlink);
|
||||
assert(self->alive);
|
||||
Guard G(self->lchan->lock);
|
||||
|
||||
|
@ -491,10 +491,11 @@ short PVD2DBR(pvd::ScalarType pvt)
|
||||
}
|
||||
}
|
||||
|
||||
pvd::StructureConstPtr PVIF::dtype(dbChannel* chan)
|
||||
epics::pvData::StructureConstPtr
|
||||
ScalarBuilder::dtype(dbChannel *channel)
|
||||
{
|
||||
const short dbr = dbChannelFinalFieldType(chan);
|
||||
const long maxelem = dbChannelFinalElements(chan);
|
||||
const short dbr = dbChannelFinalFieldType(channel);
|
||||
const long maxelem = dbChannelFinalElements(channel);
|
||||
const pvd::ScalarType pvt = DBR2PVD(dbr);
|
||||
|
||||
if(INVALID_DB_REQ(dbr))
|
||||
@ -516,10 +517,11 @@ pvd::StructureConstPtr PVIF::dtype(dbChannel* chan)
|
||||
return pvd::getStandardField()->scalarArray(pvt, options);
|
||||
}
|
||||
|
||||
PVIF* PVIF::attach(dbChannel* chan, const epics::pvData::PVStructurePtr& root)
|
||||
PVIF*
|
||||
ScalarBuilder::attach(dbChannel *channel, const epics::pvData::PVStructurePtr& root)
|
||||
{
|
||||
const short dbr = dbChannelFinalFieldType(chan);
|
||||
const long maxelem = dbChannelFinalElements(chan);
|
||||
const short dbr = dbChannelFinalFieldType(channel);
|
||||
const long maxelem = dbChannelFinalElements(channel);
|
||||
//const pvd::ScalarType pvt = DBR2PVD(dbr);
|
||||
|
||||
if(maxelem==1) {
|
||||
@ -530,14 +532,14 @@ PVIF* PVIF::attach(dbChannel* chan, const epics::pvData::PVStructurePtr& root)
|
||||
case DBR_USHORT:
|
||||
case DBR_LONG:
|
||||
case DBR_ULONG:
|
||||
return new PVIFScalarNumeric<pvScalar, metaLONG>(chan, dbr, root);
|
||||
return new PVIFScalarNumeric<pvScalar, metaLONG>(channel, dbr, root);
|
||||
case DBR_FLOAT:
|
||||
case DBR_DOUBLE:
|
||||
return new PVIFScalarNumeric<pvScalar, metaDOUBLE>(chan, dbr, root);
|
||||
return new PVIFScalarNumeric<pvScalar, metaDOUBLE>(channel, dbr, root);
|
||||
case DBR_ENUM:
|
||||
return new PVIFScalarNumeric<pvScalar, metaENUM>(chan, dbr, root);
|
||||
return new PVIFScalarNumeric<pvScalar, metaENUM>(channel, dbr, root);
|
||||
case DBR_STRING:
|
||||
return new PVIFScalarNumeric<pvScalar, metaSTRING>(chan, dbr, root);
|
||||
return new PVIFScalarNumeric<pvScalar, metaSTRING>(channel, dbr, root);
|
||||
}
|
||||
} else {
|
||||
switch(dbr) {
|
||||
@ -547,12 +549,32 @@ PVIF* PVIF::attach(dbChannel* chan, const epics::pvData::PVStructurePtr& root)
|
||||
case DBR_USHORT:
|
||||
case DBR_LONG:
|
||||
case DBR_ULONG:
|
||||
return new PVIFScalarNumeric<pvArray, metaLONG>(chan, dbr, root);
|
||||
return new PVIFScalarNumeric<pvArray, metaLONG>(channel, dbr, root);
|
||||
case DBR_FLOAT:
|
||||
case DBR_DOUBLE:
|
||||
return new PVIFScalarNumeric<pvArray, metaDOUBLE>(chan, dbr, root);
|
||||
return new PVIFScalarNumeric<pvArray, metaDOUBLE>(channel, dbr, root);
|
||||
}
|
||||
}
|
||||
|
||||
throw std::invalid_argument("Channel has invalid/unsupported DBR type");
|
||||
}
|
||||
|
||||
PVIFBuilder::PVIFBuilder()
|
||||
{}
|
||||
|
||||
PVIFBuilder::~PVIFBuilder() {}
|
||||
|
||||
|
||||
PVIFBuilder* PVIFBuilder::create(const options_t& options)
|
||||
{
|
||||
options_t::const_iterator it;
|
||||
|
||||
if((it = options.find("@type"))==options.end())
|
||||
throw std::runtime_error("Field mapping missing required key \"@type\"");
|
||||
const std::string& type(it->second.ref<std::string>());
|
||||
|
||||
if(type=="scalar")
|
||||
return new ScalarBuilder(options);
|
||||
else
|
||||
throw std::runtime_error("Unknown mapping @type");
|
||||
}
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <pv/bitSet.h>
|
||||
#include <pv/pvData.h>
|
||||
|
||||
#include <anyscalar.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#ifndef VERSION_INT
|
||||
@ -257,7 +259,7 @@ struct epicsShareClass PVIF {
|
||||
PVIF(dbChannel *ch, const epics::pvData::PVStructurePtr& p);
|
||||
virtual ~PVIF() {}
|
||||
|
||||
dbChannel * const chan;
|
||||
dbChannel * const chan; // borrowed reference from PVIFBuilder
|
||||
const epics::pvData::PVStructurePtr pvalue;
|
||||
|
||||
//! Copy from PDB record to pvalue (call dbChannelGet())
|
||||
@ -269,11 +271,45 @@ struct epicsShareClass PVIF {
|
||||
//! Calculate DBE mask from changed bitset
|
||||
virtual unsigned dbe(const epics::pvData::BitSet& mask) =0;
|
||||
|
||||
// fetch the structure description for a DBR type
|
||||
static epics::pvData::StructureConstPtr dtype(dbChannel *chan);
|
||||
|
||||
// Create a PVIF associating the given channel to the given PVStructure node (may not be actual root)
|
||||
static PVIF* attach(dbChannel* ch, const epics::pvData::PVStructurePtr& root);
|
||||
private:
|
||||
PVIF(const PVIF&);
|
||||
PVIF& operator=(const PVIF&);
|
||||
};
|
||||
|
||||
struct epicsShareClass PVIFBuilder {
|
||||
|
||||
virtual ~PVIFBuilder();
|
||||
|
||||
// fetch the structure description
|
||||
virtual epics::pvData::StructureConstPtr dtype(dbChannel *channel) =0;
|
||||
|
||||
// Attach to a structure instance.
|
||||
// must be of the type returned by dtype().
|
||||
// need not be the root structure
|
||||
virtual PVIF* attach(dbChannel *channel, const epics::pvData::PVStructurePtr& root) =0;
|
||||
|
||||
typedef std::map<std::string, AnyScalar> options_t;
|
||||
|
||||
static PVIFBuilder* create(const options_t& options);
|
||||
protected:
|
||||
PVIFBuilder();
|
||||
private:
|
||||
PVIFBuilder(const PVIFBuilder&);
|
||||
PVIFBuilder& operator=(const PVIFBuilder&);
|
||||
};
|
||||
|
||||
struct epicsShareClass ScalarBuilder : public PVIFBuilder
|
||||
{
|
||||
|
||||
ScalarBuilder() {}
|
||||
ScalarBuilder(const options_t& options)
|
||||
{}
|
||||
|
||||
virtual ~ScalarBuilder() {}
|
||||
|
||||
virtual epics::pvData::StructureConstPtr dtype(dbChannel *channel) OVERRIDE FINAL;
|
||||
virtual PVIF* attach(dbChannel *channel, const epics::pvData::PVStructurePtr& root) OVERRIDE FINAL;
|
||||
};
|
||||
|
||||
|
||||
#endif // PVIF_H
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <mbbiRecord.h>
|
||||
#include <stringinRecord.h>
|
||||
|
||||
#include "helper.h"
|
||||
#include "pvif.h"
|
||||
#include "utilities.h"
|
||||
|
||||
@ -53,11 +54,13 @@ void testScalar()
|
||||
testEqual(dbChannelFinalFieldType(chan_ai_rval), DBR_LONG);
|
||||
testEqual(dbChannelFinalFieldType(chan_mbbi), DBR_ENUM);
|
||||
|
||||
pvd::StructureConstPtr dtype_li(PVIF::dtype(chan_li));
|
||||
pvd::StructureConstPtr dtype_si(PVIF::dtype(chan_si));
|
||||
pvd::StructureConstPtr dtype_ai(PVIF::dtype(chan_ai));
|
||||
pvd::StructureConstPtr dtype_ai_rval(PVIF::dtype(chan_ai_rval));
|
||||
pvd::StructureConstPtr dtype_mbbi(PVIF::dtype(chan_mbbi));
|
||||
ScalarBuilder builder;
|
||||
|
||||
pvd::StructureConstPtr dtype_li(builder.dtype(chan_li));
|
||||
pvd::StructureConstPtr dtype_si(builder.dtype(chan_si));
|
||||
pvd::StructureConstPtr dtype_ai(builder.dtype(chan_ai));
|
||||
pvd::StructureConstPtr dtype_ai_rval(builder.dtype(chan_ai_rval));
|
||||
pvd::StructureConstPtr dtype_mbbi(builder.dtype(chan_mbbi));
|
||||
|
||||
pvd::StructureConstPtr dtype_root(pvd::getFieldCreate()->createFieldBuilder()
|
||||
->add("li", dtype_li)
|
||||
@ -69,11 +72,11 @@ void testScalar()
|
||||
|
||||
pvd::PVStructurePtr root(pvd::getPVDataCreate()->createPVStructure(dtype_root));
|
||||
|
||||
std::auto_ptr<PVIF> pvif_li(PVIF::attach(chan_li, root->getSubField<pvd::PVStructure>("li")));
|
||||
std::auto_ptr<PVIF> pvif_si(PVIF::attach(chan_si, root->getSubField<pvd::PVStructure>("si")));
|
||||
std::auto_ptr<PVIF> pvif_ai(PVIF::attach(chan_ai, root->getSubField<pvd::PVStructure>("ai")));
|
||||
std::auto_ptr<PVIF> pvif_ai_rval(PVIF::attach(chan_ai_rval, root->getSubField<pvd::PVStructure>("ai_rval")));
|
||||
std::auto_ptr<PVIF> pvif_mbbi(PVIF::attach(chan_mbbi, root->getSubField<pvd::PVStructure>("mbbi")));
|
||||
p2p::auto_ptr<PVIF> pvif_li(builder.attach(chan_li, root->getSubField<pvd::PVStructure>("li")));
|
||||
p2p::auto_ptr<PVIF> pvif_si(builder.attach(chan_si, root->getSubField<pvd::PVStructure>("si")));
|
||||
p2p::auto_ptr<PVIF> pvif_ai(builder.attach(chan_ai, root->getSubField<pvd::PVStructure>("ai")));
|
||||
p2p::auto_ptr<PVIF> pvif_ai_rval(builder.attach(chan_ai_rval, root->getSubField<pvd::PVStructure>("ai_rval")));
|
||||
p2p::auto_ptr<PVIF> pvif_mbbi(builder.attach(chan_mbbi, root->getSubField<pvd::PVStructure>("mbbi")));
|
||||
|
||||
pvd::BitSet mask;
|
||||
|
||||
|
Reference in New Issue
Block a user