pvac: add synchronous put to 'value' field
This commit is contained in:
@@ -22,14 +22,31 @@ typedef epicsGuard<epicsMutex> Guard;
|
||||
typedef epicsGuardRelease<epicsMutex> UnGuard;
|
||||
|
||||
namespace {
|
||||
struct GetWait : pvac::ClientChannel::GetCallback
|
||||
struct WaitCommon
|
||||
{
|
||||
epicsMutex mutex;
|
||||
epicsEvent event;
|
||||
bool done;
|
||||
|
||||
WaitCommon() :done(false) {}
|
||||
void wait(double timeout)
|
||||
{
|
||||
Guard G(mutex);
|
||||
while(!done) {
|
||||
UnGuard U(G);
|
||||
if(!event.wait(timeout)) {
|
||||
throw pvac::Timeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct GetWait : public pvac::ClientChannel::GetCallback,
|
||||
public WaitCommon
|
||||
{
|
||||
pvac::GetEvent result;
|
||||
|
||||
GetWait() :done(false) {}
|
||||
GetWait() {}
|
||||
virtual ~GetWait() {}
|
||||
virtual void getDone(const pvac::GetEvent& evt)
|
||||
{
|
||||
@@ -55,16 +72,7 @@ pvac::ClientChannel::get(double timeout,
|
||||
{
|
||||
GetWait waiter;
|
||||
Operation op(get(&waiter, pvRequest));
|
||||
{
|
||||
Guard G(waiter.mutex);
|
||||
while(!waiter.done) {
|
||||
UnGuard U(G);
|
||||
if(!waiter.event.wait(timeout)) {
|
||||
op.cancel();
|
||||
throw Timeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
waiter.wait(timeout);
|
||||
if(waiter.result.event==pvac::GetEvent::Success)
|
||||
return waiter.result.value;
|
||||
else
|
||||
@@ -94,4 +102,105 @@ pvac::ClientChannel::rpc(double timeout,
|
||||
throw std::runtime_error(waiter.result.message);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct PutValCommon : public pvac::ClientChannel::PutCallback,
|
||||
public WaitCommon
|
||||
{
|
||||
pvac::PutEvent result;
|
||||
|
||||
PutValCommon() {}
|
||||
virtual ~PutValCommon() {}
|
||||
|
||||
virtual void putDone(const PutEvent& evt)
|
||||
{
|
||||
{
|
||||
Guard G(mutex);
|
||||
if(done) {
|
||||
LOG(pva::logLevelWarn, "oops, double event to PutCallback");
|
||||
} else {
|
||||
result = evt;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
event.signal();
|
||||
}
|
||||
};
|
||||
|
||||
struct PutValScalar : public PutValCommon
|
||||
{
|
||||
const void* value;
|
||||
pvd::ScalarType vtype;
|
||||
|
||||
PutValScalar(const void* value, pvd::ScalarType vtype) :value(value), vtype(vtype) {}
|
||||
virtual ~PutValScalar() {}
|
||||
|
||||
virtual void putBuild(const epics::pvData::StructureConstPtr& build, Args& args)
|
||||
{
|
||||
pvd::PVStructurePtr root(pvd::getPVDataCreate()->createPVStructure(build));
|
||||
pvd::PVScalarPtr value(root->getSubField<pvd::PVScalar>("value"));
|
||||
if(value) {
|
||||
value->putFrom(this->value, vtype);
|
||||
args.tosend.set(value->getFieldOffset());
|
||||
} else {
|
||||
// TODO: handle enum
|
||||
throw std::runtime_error("PV has no scalar 'value' sub-field");
|
||||
}
|
||||
args.root = root;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct PutValArray : public PutValCommon
|
||||
{
|
||||
pvd::shared_vector<const void> arr;
|
||||
|
||||
PutValArray(const pvd::shared_vector<const void>& arr) :arr(arr) {}
|
||||
virtual ~PutValArray() {}
|
||||
|
||||
virtual void putBuild(const epics::pvData::StructureConstPtr& build, Args& args)
|
||||
{
|
||||
pvd::PVStructurePtr root(pvd::getPVDataCreate()->createPVStructure(build));
|
||||
pvd::PVScalarArrayPtr value(root->getSubField<pvd::PVScalarArray>("value"));
|
||||
if(value) {
|
||||
value->putFrom(arr);
|
||||
args.tosend.set(value->getFieldOffset());
|
||||
} else {
|
||||
throw std::runtime_error("PV has no scalar array 'value' sub-field");
|
||||
}
|
||||
args.root = root;
|
||||
}
|
||||
|
||||
};
|
||||
} //namespace
|
||||
|
||||
void
|
||||
ClientChannel::putValue(const void* value,
|
||||
pvd::ScalarType vtype,
|
||||
double timeout,
|
||||
pvd::PVStructure::const_shared_pointer pvRequest)
|
||||
{
|
||||
PutValScalar waiter(value, vtype);
|
||||
Operation op(put(&waiter, pvRequest));
|
||||
waiter.wait(timeout);
|
||||
if(waiter.result.event==PutEvent::Success)
|
||||
return;
|
||||
else
|
||||
throw std::runtime_error(waiter.result.message);
|
||||
}
|
||||
|
||||
void
|
||||
ClientChannel::putValue(const epics::pvData::shared_vector<const void>& value,
|
||||
double timeout,
|
||||
epics::pvData::PVStructure::const_shared_pointer pvRequest)
|
||||
{
|
||||
PutValArray waiter(value);
|
||||
Operation op(put(&waiter, pvRequest));
|
||||
waiter.wait(timeout);
|
||||
if(waiter.result.event==PutEvent::Success)
|
||||
return;
|
||||
else
|
||||
throw std::runtime_error(waiter.result.message);
|
||||
}
|
||||
|
||||
|
||||
}//namespace pvac
|
||||
|
||||
Reference in New Issue
Block a user