6 #include <epicsGuard.h>
8 #include <pv/pvAccess.h>
10 template<
typename T,
typename A>
11 bool getS(
const epics::pvData::PVStructurePtr& S,
const char *name, A& val)
13 epics::pvData::PVScalarPtr F(S->getSubField<epics::pvData::PVScalar>(name));
22 const std::tr1::weak_ptr<epics::pvAccess::ChannelProvider>& prov,
23 const epics::pvAccess::ChannelRequester::shared_pointer& req,
24 const epics::pvData::StructureConstPtr& dtype
26 :pvname(name), provider(prov), requester(req), fielddesc(dtype)
30 mutable epicsMutex lock;
31 typedef epicsGuard<epicsMutex> guard_t;
33 const std::string pvname;
34 const epics::pvAccess::ChannelProvider::weak_pointer provider;
35 const requester_type::weak_pointer requester;
36 const epics::pvData::StructureConstPtr fielddesc;
39 virtual std::string getRequesterName() OVERRIDE
40 {
return getChannelRequester()->getRequesterName(); }
42 virtual void destroy() OVERRIDE FINAL {}
44 virtual std::tr1::shared_ptr<epics::pvAccess::ChannelProvider> getProvider() OVERRIDE FINAL
45 {
return epics::pvAccess::ChannelProvider::shared_pointer(provider); }
46 virtual std::string getRemoteAddress() OVERRIDE
47 {
return getRequesterName(); }
49 virtual std::string getChannelName() OVERRIDE FINAL {
return pvname; }
50 virtual std::tr1::shared_ptr<epics::pvAccess::ChannelRequester> getChannelRequester() OVERRIDE FINAL
51 {
return requester_type::shared_pointer(requester); }
53 virtual void getField(epics::pvAccess::GetFieldRequester::shared_pointer
const & requester,std::string
const & subField) OVERRIDE
54 { requester->getDone(epics::pvData::Status(), fielddesc); }
56 virtual void printInfo(std::ostream& out) OVERRIDE {
57 out<<
"Channel '"<<pvname<<
"' "<<getRemoteAddress()<<
"\n";
72 weak_pointer weakself;
73 inline shared_pointer shared_from_this() {
return shared_pointer(weakself); }
75 typedef epics::pvAccess::MonitorRequester requester_t;
78 typedef epicsGuard<epicsMutex> guard_t;
79 typedef epicsGuardRelease<epicsMutex> unguard_t;
82 const requester_t::weak_pointer requester;
84 epics::pvData::PVStructurePtr complete;
85 epics::pvData::BitSet changed, overflow;
87 typedef std::deque<epics::pvAccess::MonitorElementPtr> buffer_t;
91 buffer_t inuse, empty;
95 const requester_t::weak_pointer& requester,
96 const epics::pvData::PVStructure::shared_pointer& pvReq)
106 inline const epics::pvData::PVStructurePtr& getValue() {
return complete; }
110 void connect(guard_t& guard,
const epics::pvData::PVStructurePtr& value)
112 guard.assertIdenticalMutex(lock);
113 epics::pvData::StructureConstPtr dtype(value->getStructure());
114 epics::pvData::PVDataCreatePtr create(epics::pvData::getPVDataCreate());
115 BaseMonitor::shared_pointer
self(shared_from_this());
116 requester_t::shared_pointer req(requester.lock());
121 empty.resize(nbuffers);
122 for(
size_t i=0; i<empty.size(); i++) {
123 empty[i].reset(
new epics::pvAccess::MonitorElement(create->createPVStructure(dtype)));
128 epics::pvData::Status sts;
129 req->monitorConnect(sts,
self, dtype);
138 guard.assertIdenticalMutex(lock);
139 requester_t::shared_pointer req;
141 if(!complete || !running)
return false;
145 if(empty.empty())
return false;
148 req = requester.lock();
153 req->monitorEvent(shared_from_this());
161 guard.assertIdenticalMutex(lock);
163 requester_t::shared_pointer req;
165 if(!complete || !running)
return false;
168 oflow = inoverflow =
true;
173 req = requester.lock();
174 oflow = inoverflow =
false;
179 req->monitorEvent(shared_from_this());
186 const epics::pvData::BitSet& updated,
187 const epics::pvData::BitSet& overflowed)
189 guard.assertIdenticalMutex(lock);
191 requester_t::shared_pointer req;
193 if(!complete || !running)
return false;
196 oflow = inoverflow =
true;
197 overflow |= overflowed;
198 overflow.or_and(updated, changed);
205 req = requester.lock();
206 oflow = inoverflow =
false;
211 req->monitorEvent(shared_from_this());
217 bool post(guard_t& guard,
const epics::pvData::BitSet& updated) {
219 requester_t::shared_pointer req;
221 if(!complete || !running)
return false;
224 oflow = inoverflow =
true;
225 overflow.or_and(updated, changed);
232 req = requester.lock();
233 oflow = inoverflow =
false;
238 req->monitorEvent(shared_from_this());
248 assert(!empty.empty());
250 epics::pvAccess::MonitorElementPtr& elem = empty.front();
252 elem->pvStructurePtr->copyUnchecked(*complete);
253 *elem->changedBitSet = changed;
254 *elem->overrunBitSet = overflow;
260 inuse.push_back(elem);
267 virtual void onStart() {}
268 virtual void onStop() {}
273 virtual void destroy()
279 virtual epics::pvData::Status start()
281 epics::pvData::Status ret;
283 BaseMonitor::shared_pointer
self;
286 if(running)
return ret;
288 if(!complete)
return ret;
289 inoverflow = empty.empty();
299 if(notify) onStart();
303 virtual epics::pvData::Status stop()
305 BaseMonitor::shared_pointer
self;
307 epics::pvData::Status ret;
317 virtual epics::pvAccess::MonitorElementPtr poll()
319 epics::pvAccess::MonitorElementPtr ret;
321 if(running && complete && !inuse.empty()) {
328 virtual void release(epics::pvAccess::MonitorElementPtr
const & elem)
330 BaseMonitor::shared_pointer
self;
333 empty.push_back(elem);
335 self = weakself.lock();
338 self->requestUpdate();
341 virtual void getStats(Stats& s)
const
344 s.nempty = empty.size();
345 s.nfilled = inuse.size();
346 s.noutstanding = nbuffers - s.nempty - s.nfilled;
353 typedef CP provider_type;
356 std::tr1::weak_ptr<CP> last_shared;
361 virtual std::string getFactoryName() {
return name; }
363 virtual epics::pvAccess::ChannelProvider::shared_pointer sharedInstance()
365 epicsGuard<epicsMutex> G(lock);
366 std::tr1::shared_ptr<CP> ret(last_shared.lock());
374 virtual epics::pvAccess::ChannelProvider::shared_pointer newInstance(
const std::tr1::shared_ptr<epics::pvAccess::Configuration>&)
376 std::tr1::shared_ptr<CP> ret(
new CP());
381 #endif // PVAHELPER_H
bool post(guard_t &guard, const epics::pvData::BitSet &updated)
post update with changed
bool post(guard_t &guard, const epics::pvData::BitSet &updated, no_overflow)
post update if queue not full, if full return false w/o overflow
bool post(guard_t &guard)
post update of pending changes. eg. call from requestUpdate()
void connect(guard_t &guard, const epics::pvData::PVStructurePtr &value)
virtual void requestUpdate()
bool post(guard_t &guard, const epics::pvData::BitSet &updated, const epics::pvData::BitSet &overflowed)
post update with changed and overflowed masks (eg. when updates were lost in some upstream queue) ...