pvaTestClient: simple blocking get/rpc
This commit is contained in:
@ -9,6 +9,8 @@ TESTPROD_HOST += putme
|
||||
TESTPROD_HOST += monitorme
|
||||
TESTPROD_HOST += spamme
|
||||
|
||||
TESTPROD_HOST += miniget
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
32
examples/miniget.cpp
Normal file
32
examples/miniget.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
// The simplest possible PVA get
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "pv/clientFactory.h"
|
||||
#include "pv/pvaTestClient.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
try {
|
||||
if(argc<=1) {
|
||||
std::cerr<<"Usage: "<<argv[0]<<" <pvname>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
epics::pvAccess::ClientFactory::start();
|
||||
|
||||
TestClientProvider provider("pva");
|
||||
|
||||
TestClientChannel channel(provider.connect(argv[1]));
|
||||
|
||||
std::cout<<channel.name()<<" : "<<channel.get()<<"\n";
|
||||
|
||||
}catch(std::exception& e){
|
||||
std::cerr<<"Error: "<<e.what()<<"\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ include $(TOP)/configure/CONFIG
|
||||
LIBRARY += pvAccessIOC
|
||||
|
||||
pvAccessIOC_LIBS += pvAccess
|
||||
pvAccessIOC_LIBS += $(LIB_LIBS)
|
||||
|
||||
INC += pv/syncChannelFind.h
|
||||
|
||||
|
@ -5,6 +5,7 @@ SRC_DIRS += $(PVACCESS_SRC)/testing
|
||||
INC += pv/pvaTestClient.h
|
||||
|
||||
LIBSRCS += pvaTestClient.cpp
|
||||
LIBSRCS += pvaTestClientSync.cpp
|
||||
LIBSRCS += pvaTestClientGet.cpp
|
||||
LIBSRCS += pvaTestClientRPC.cpp
|
||||
LIBSRCS += pvaTestClientMonitor.cpp
|
||||
|
@ -5,6 +5,8 @@
|
||||
#ifndef PVATESTCLIENT_H
|
||||
#define PVATESTCLIENT_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <epicsMutex.h>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
@ -106,6 +108,11 @@ struct epicsShareClass TestConnectEvent
|
||||
bool connected;
|
||||
};
|
||||
|
||||
struct epicsShareClass TestTimeout : public std::runtime_error
|
||||
{
|
||||
TestTimeout();
|
||||
};
|
||||
|
||||
//! Represents a single channel
|
||||
class epicsShareClass TestClientChannel
|
||||
{
|
||||
@ -128,6 +135,8 @@ public:
|
||||
const Options& opt = Options());
|
||||
~TestClientChannel();
|
||||
|
||||
std::string name() const;
|
||||
|
||||
//! callback for get() and rpc()
|
||||
struct epicsShareClass GetCallback {
|
||||
virtual ~GetCallback() {}
|
||||
@ -139,12 +148,24 @@ public:
|
||||
TestOperation get(GetCallback* cb,
|
||||
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
|
||||
|
||||
//! Block and retrieve current PV value
|
||||
//! @throws TestTimeout or std::runtime_error
|
||||
epics::pvData::PVStructure::const_shared_pointer
|
||||
get(double timeout = 3.0,
|
||||
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
|
||||
|
||||
|
||||
//! Start an RPC call
|
||||
//! @param cb Completion notification callback. Must outlive TestOperation (call TestOperation::cancel() to force release)
|
||||
TestOperation rpc(GetCallback* cb,
|
||||
const epics::pvData::PVStructure::const_shared_pointer& arguments,
|
||||
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
|
||||
|
||||
epics::pvData::PVStructure::const_shared_pointer
|
||||
rpc(double timeout,
|
||||
const epics::pvData::PVStructure::const_shared_pointer& arguments,
|
||||
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
|
||||
|
||||
//! callbacks for put()
|
||||
struct epicsShareClass PutCallback {
|
||||
virtual ~PutCallback() {}
|
||||
|
@ -20,6 +20,10 @@ namespace pva = epics::pvAccess;
|
||||
|
||||
typedef epicsGuard<epicsMutex> Guard;
|
||||
|
||||
TestTimeout::TestTimeout()
|
||||
:std::runtime_error("Timeout")
|
||||
{}
|
||||
|
||||
struct TestClientChannel::Impl : public pva::ChannelRequester
|
||||
{
|
||||
epicsMutex mutex;
|
||||
@ -78,7 +82,6 @@ TestOperation::TestOperation(const std::tr1::shared_ptr<Impl>& i)
|
||||
|
||||
TestOperation::~TestOperation() {}
|
||||
|
||||
|
||||
std::string TestOperation::name() const
|
||||
{
|
||||
return impl ? impl->name() : "<NULL>";
|
||||
@ -103,6 +106,11 @@ TestClientChannel::TestClientChannel(const std::tr1::shared_ptr<pva::ChannelProv
|
||||
|
||||
TestClientChannel::~TestClientChannel() {}
|
||||
|
||||
std::string TestClientChannel::name() const
|
||||
{
|
||||
return impl ? impl->channel->getChannelName() : "<NONE>";
|
||||
}
|
||||
|
||||
void TestClientChannel::addConnectListener(ConnectCallback* cb)
|
||||
{
|
||||
if(!impl) throw std::logic_error("Dead Channel");
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsGuard.h>
|
||||
#include <epicsEvent.h>
|
||||
|
||||
#include <pv/current_function.h>
|
||||
#include <pv/pvData.h>
|
||||
@ -188,7 +189,6 @@ TestClientChannel::get(TestClientChannel::GetCallback* cb,
|
||||
return TestOperation(ret);
|
||||
}
|
||||
|
||||
|
||||
TestOperation
|
||||
TestClientChannel::put(PutCallback* cb,
|
||||
epics::pvData::PVStructure::const_shared_pointer pvRequest)
|
||||
|
93
src/testing/pvaTestClientSync.cpp
Normal file
93
src/testing/pvaTestClientSync.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsGuard.h>
|
||||
#include <epicsEvent.h>
|
||||
|
||||
#include <pv/current_function.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/logger.h"
|
||||
#include "pv/pvaTestClient.h"
|
||||
#include "pv/pvAccess.h"
|
||||
|
||||
namespace pvd = epics::pvData;
|
||||
namespace pva = epics::pvAccess;
|
||||
typedef epicsGuard<epicsMutex> Guard;
|
||||
typedef epicsGuardRelease<epicsMutex> UnGuard;
|
||||
|
||||
namespace {
|
||||
struct GetWait : TestClientChannel::GetCallback
|
||||
{
|
||||
epicsMutex mutex;
|
||||
epicsEvent event;
|
||||
bool done;
|
||||
TestGetEvent result;
|
||||
|
||||
GetWait() :done(false) {}
|
||||
virtual ~GetWait() {}
|
||||
virtual void getDone(const TestGetEvent& evt)
|
||||
{
|
||||
{
|
||||
Guard G(mutex);
|
||||
if(done) {
|
||||
LOG(pva::logLevelWarn, "oops, double event to GetCallback");
|
||||
} else {
|
||||
result = evt;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
event.signal();
|
||||
}
|
||||
};
|
||||
} //namespace
|
||||
|
||||
pvd::PVStructure::const_shared_pointer
|
||||
TestClientChannel::get(double timeout,
|
||||
pvd::PVStructure::const_shared_pointer pvRequest)
|
||||
{
|
||||
GetWait waiter;
|
||||
TestOperation op(get(&waiter, pvRequest));
|
||||
{
|
||||
Guard G(waiter.mutex);
|
||||
while(!waiter.done) {
|
||||
UnGuard U(G);
|
||||
if(!waiter.event.wait(timeout)) {
|
||||
op.cancel();
|
||||
throw TestTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(waiter.result.event==TestGetEvent::Success)
|
||||
return waiter.result.value;
|
||||
else
|
||||
throw std::runtime_error(waiter.result.message);
|
||||
}
|
||||
|
||||
pvd::PVStructure::const_shared_pointer
|
||||
TestClientChannel::rpc(double timeout,
|
||||
const epics::pvData::PVStructure::const_shared_pointer& arguments,
|
||||
epics::pvData::PVStructure::const_shared_pointer pvRequest)
|
||||
{
|
||||
GetWait waiter;
|
||||
TestOperation op(rpc(&waiter, arguments, pvRequest));
|
||||
{
|
||||
Guard G(waiter.mutex);
|
||||
while(!waiter.done) {
|
||||
UnGuard U(G);
|
||||
if(!waiter.event.wait(timeout)) {
|
||||
op.cancel();
|
||||
throw TestTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(waiter.result.event==TestGetEvent::Success)
|
||||
return waiter.result.value;
|
||||
else
|
||||
throw std::runtime_error(waiter.result.message);
|
||||
}
|
Reference in New Issue
Block a user