This is Unofficial EPICS BASE Doxygen Site
clientGet.cpp
Go to the documentation of this file.
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 
6 #include <epicsMutex.h>
7 #include <epicsGuard.h>
8 #include <epicsEvent.h>
9 #include <epicsThread.h>
10 
11 #include <pv/current_function.h>
12 #include <pv/pvData.h>
13 #include <pv/bitSet.h>
14 #include <pv/reftrack.h>
15 
16 #define epicsExportSharedSymbols
17 #include "pv/logger.h"
18 #include "clientpvt.h"
19 #include "pv/pvAccess.h"
20 
21 namespace {
24 
25 struct Getter : public pvac::detail::CallbackStorage,
27  public pvac::Operation::Impl,
29 {
30  operation_type::shared_pointer op;
31 
33  pvac::GetEvent event;
34 
35  static size_t num_instances;
36 
37  explicit Getter(pvac::ClientChannel::GetCallback* cb) :cb(cb)
38  {REFTRACE_INCREMENT(num_instances);}
39  virtual ~Getter() {
40  CallbackGuard G(*this);
41  cb = 0;
42  G.wait(); // paranoia
43  REFTRACE_DECREMENT(num_instances);
44  }
45 
47  {
48  if(!cb) return;
49 
50  event.event = evt;
52  cb = 0;
53  CallbackUse U(G);
54  try {
55  C->getDone(event);
56  } catch(std::exception& e) {
57  LOG(pva::logLevelInfo, "Lost exception during getDone(): %s", e.what());
58  }
59  }
60 
61  virtual std::string name() const OVERRIDE FINAL
62  {
63  Guard G(mutex);
64  return op ? op->getChannel()->getChannelName() : "<dead>";
65  }
66 
67  // called automatically via wrapped_shared_from_this
68  virtual void cancel() OVERRIDE FINAL
69  {
70  // keepalive for safety in case callback wants to destroy us
71  std::tr1::shared_ptr<Getter> keepalive(internal_shared_from_this());
72  CallbackGuard G(*this);
73  if(op) op->cancel();
74  callEvent(G, pvac::GetEvent::Cancel);
75  G.wait();
76  }
77 
78  virtual std::string getRequesterName() OVERRIDE FINAL
79  {
80  Guard G(mutex);
81  return op ? op->getChannel()->getRequesterName() : "<dead>";
82  }
83 
84  virtual void channelGetConnect(
86  pva::ChannelGet::shared_pointer const & channelGet,
87  epics::pvData::Structure::const_shared_pointer const & structure) OVERRIDE FINAL
88  {
89  std::tr1::shared_ptr<Getter> keepalive(internal_shared_from_this());
90  CallbackGuard G(*this);
91  if(!cb) return;
92 
93  if(!status.isOK()) {
94  event.message = status.getMessage();
95  } else {
96  event.message.clear();
97  }
98  if(!status.isSuccess()) {
99  callEvent(G);
100 
101  } else {
102  channelGet->get();
103 
104  }
105  }
106 
107  virtual void channelDisconnect(bool destroy) OVERRIDE FINAL
108  {
109  CallbackGuard G(*this);
110  event.message = "Disconnect";
111 
112  callEvent(G);
113  }
114 
115  virtual void getDone(
116  const epics::pvData::Status& status,
117  pva::ChannelGet::shared_pointer const & channelGet,
118  epics::pvData::PVStructure::shared_pointer const & pvStructure,
119  epics::pvData::BitSet::shared_pointer const & bitSet) OVERRIDE FINAL
120  {
121  std::tr1::shared_ptr<Getter> keepalive(internal_shared_from_this());
122  CallbackGuard G(*this);
123  if(!cb) return;
124 
125  if(!status.isOK()) {
126  event.message = status.getMessage();
127  } else {
128  event.message.clear();
129  }
130  event.value = pvStructure;
131  event.valid = bitSet;
132 
133  callEvent(G, status.isSuccess()? pvac::GetEvent::Success : pvac::GetEvent::Fail);
134  }
135 
136  virtual void show(std::ostream &strm) const OVERRIDE FINAL
137  {
138  strm << "Operation(Get"
139  "\"" << name() <<"\""
140  ")";
141  }
142 };
143 
144 size_t Getter::num_instances;
145 
146 } //namespace
147 
148 namespace pvac {
149 
150 Operation
152  epics::pvData::PVStructure::const_shared_pointer pvRequest)
153 {
154  if(!impl) throw std::logic_error("Dead Channel");
155  if(!pvRequest)
156  pvRequest = pvd::createRequest("field()");
157 
158  std::tr1::shared_ptr<Getter> ret(Getter::build(cb));
159 
160  {
161  Guard G(ret->mutex);
162  ret->op = getChannel()->createChannelGet(ret->internal_shared_from_this(),
164  }
165 
166  return Operation(ret);
167 }
168 
169 namespace detail {
170 
172 {
173  epics::registerRefCounter("pvac::Getter", &Getter::num_instances);
174 }
175 
176 }
177 
178 }//namespace pvac
virtual void getDone(const GetEvent &evt)=0
get or rpc operation is complete
pvd::Status status
virtual void channelGetConnect(const epics::pvData::Status &status, ChannelGet::shared_pointer const &channelGet, epics::pvData::Structure::const_shared_pointer const &structure)=0
Information on get/rpc completion.
Definition: client.h:99
virtual void getDone(const epics::pvData::Status &status, ChannelGet::shared_pointer const &channelGet, epics::pvData::PVStructure::shared_pointer const &pvStructure, epics::pvData::BitSet::shared_pointer const &bitSet)=0
virtual std::string name() const =0
callback for get() and rpc()
Definition: client.h:319
#define OVERRIDE
Definition: pvAccess.h:55
const std::string & getMessage() const
Definition: status.h:80
PVStructure::shared_pointer createRequest(std::string const &request)
Handle for in-progress get/put/rpc operation.
Definition: client.h:50
virtual void show(std::ostream &) const =0
#define LOG(level, format,...)
Definition: logger.h:48
void registerRefTrackGet()
Definition: clientGet.cpp:171
virtual void channelDisconnect(bool destroy)
Definition: pvAccess.h:198
std::tr1::shared_ptr< Derived > internal_shared_from_this()
Definition: clientpvt.h:44
epicsMutex mutex
Definition: pvAccess.cpp:71
APIs for the epicsMutex mutual exclusion semaphore.
virtual void cancel()=0
bool isSuccess() const
Definition: status.h:103
Data interface for a structure,.
Definition: pvData.h:712
void registerRefCounter(const char *name, const size_t *counter)
Definition: reftrack.cpp:59
request cancelled before completion
Definition: client.h:92
APIs for the epicsEvent binary semaphore.
request ends in failure. Check message
Definition: client.h:91
Definition: caget.c:48
bool isOK() const
Definition: status.h:95
ChannelPut::shared_pointer op
Definition: pvAccess.cpp:132
shared_ptr< T > const_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:798
C++ and C descriptions for a thread.
It worked!
Definition: client.h:93
#define FINAL
Definition: pvAccess.h:48
See Client API API.
Definition: client.cpp:30