This example demonstrates a client which issues a Put operation on startup, waits for acknowledgement that the put has been handled, then exits.
#if !defined(_WIN32)
#include <signal.h>
#define USE_SIGNAL
#endif
#include <epicsEvent.h>
#include <epicsMutex.h>
#include <epicsGuard.h>
#include <epicsGetopt.h>
#include <pv/configuration.h>
#include <pv/caProvider.h>
#include <pva/client.h>
#include <pv/epicsException.h>
namespace pvd = epics::pvData;
namespace pva = epics::pvAccess;
namespace {
typedef epicsGuard<epicsMutex> Guard;
typedef epicsGuardRelease<epicsMutex> UnGuard;
epicsMutex mutex;
epicsEvent done;
size_t waitingFor;
#ifdef USE_SIGNAL
void alldone(int num)
{
(void)num;
done.signal();
}
#endif
{
POINTER_DEFINITIONS(PutTracker);
const pvd::PVStructure::const_shared_pointer& pvReq,
:op(channel.put(this, pvReq))
,value(value)
{}
virtual ~PutTracker()
{
op.cancel();
}
virtual void putBuild(const epics::pvData::StructureConstPtr &build, pvac::ClientChannel::PutCallback::Args& args) OVERRIDE FINAL
{
pvd::PVStructurePtr root(pvd::getPVDataCreate()->createPVStructure(build));
pvd::PVScalarPtr valfld(root->getSubFieldT<pvd::PVScalar>("value"));
valfld->putFrom(value);
args.root = root;
args.tosend.set(valfld->getFieldOffset());
std::cout<<
"Put value "<<valfld<<
" sending="<<args.tosend<<
"\n";
}
{
switch(evt.event) {
std::cerr<<op.name()<<
" Error: "<<evt.message<<
"\n";
break;
break;
}
{
Guard G(mutex);
waitingFor--;
}
done.signal();
}
};
void usage()
{
std::cout<<
"Usage: putme [-h] [-P <provider>] [-w <timeout>] [-r <request>] pvname=value ...\n";
}
{
}
}
int main(int argc, char *argv[]) {
try {
double waitTime = 5.0;
int opt;
while( (opt=getopt(argc, argv, "hP:w:r:"))!=-1)
{
switch(opt) {
case 'P':
providerName = optarg;
break;
case 'w':
waitTime = pvd::castUnsafe<double, std::string>(optarg);
break;
case 'r':
request = optarg;
break;
default:
case 'h':
usage();
return 1;
}
}
args_t args;
for(int i=optind; i<argc; i++)
{
size_t eq =
arg.find(
'=');
usage();
return 1;
}
val(strip(
arg.substr(eq+1)));
}
pvd::PVStructure::const_shared_pointer pvReq(pvd::createRequest(request));
pva::Configuration::shared_pointer conf(pva::ConfigurationBuilder()
.push_env()
.build());
std::cout<<
"Use provider: "<<providerName<<
"\n";
{
Guard G(mutex);
waitingFor = args.size();
}
for(size_t i=0; i<args.size(); i++)
{
args_t::const_reference
arg = args[i];
PutTracker::shared_pointer op(new PutTracker(chan, pvReq, arg.second));
ops.push_back(op);
}
#ifdef USE_SIGNAL
signal(SIGINT, alldone);
signal(SIGTERM, alldone);
signal(SIGQUIT, alldone);
#endif
int ret = 0;
{
Guard G(mutex);
while(waitingFor) {
UnGuard U(G);
if(waitTime<0.0) {
done.wait();
} else if(!done.wait(waitTime)) {
ret = 1;
break;
}
}
}
return ret;
PRINT_EXCEPTION(e);
return 2;
}
}