pvAccessCPP 7.1.8
Loading...
Searching...
No Matches
monitor.h
1/* monitor.h */
2/*
3 * Copyright information and license terms for this software can be
4 * found in the file LICENSE that is included with the distribution
5 */
9#ifndef MONITOR_H
10#define MONITOR_H
11
12#include <list>
13#include <ostream>
14
15#ifdef epicsExportSharedSymbols
16# define monitorEpicsExportSharedSymbols
17# undef epicsExportSharedSymbols
18#endif
19
20#include <epicsMutex.h>
21#include <pv/status.h>
22#include <pv/pvData.h>
23#include <pv/sharedPtr.h>
24#include <pv/bitSet.h>
25#include <pv/createRequest.h>
26
27#ifdef monitorEpicsExportSharedSymbols
28# define epicsExportSharedSymbols
29# undef monitorEpicsExportSharedSymbols
30#endif
31
32#include <pv/requester.h>
33#include <pv/destroyable.h>
34
35#include <shareLib.h>
36
37namespace epics { namespace pvAccess {
38
40class MonitorElement;
41typedef std::tr1::shared_ptr<MonitorElement> MonitorElementPtr;
43
44class Monitor;
45typedef std::tr1::shared_ptr<Monitor> MonitorPtr;
46
47
54class epicsShareClass MonitorElement {
55public:
56 POINTER_DEFINITIONS(MonitorElement);
57 MonitorElement(epics::pvData::PVStructurePtr const & pvStructurePtr);
58 const epics::pvData::PVStructurePtr pvStructurePtr;
59 const epics::pvData::BitSet::shared_pointer changedBitSet;
60 const epics::pvData::BitSet::shared_pointer overrunBitSet;
61
62 class Ref;
63};
64
69class epicsShareClass Monitor : public virtual Destroyable{
70 public:
71 POINTER_DEFINITIONS(Monitor);
73
74 virtual ~Monitor(){}
92 virtual MonitorElementPtr poll() = 0;
98 virtual void release(MonitorElementPtr const & monitorElement) = 0;
99
100 struct Stats {
101 size_t nfilled;
102 size_t noutstanding;
103 size_t nempty;
104 };
105
106 virtual void getStats(Stats& s) const {
107 s.nfilled = s.noutstanding = s.nempty = 0;
108 }
109
114 virtual void reportRemoteQueueStatus(epics::pvData::int32 freeElements) {}
115};
116
147{
148 Monitor* mon;
149 MonitorElementPtr elem;
150public:
151 Ref() :mon(0), elem() {}
152 Ref(Monitor& M) :mon(&M), elem(mon->poll()) {}
153 Ref(const Monitor::shared_pointer& M) :mon(M.get()), elem(mon->poll()) {}
154 ~Ref() { reset(); }
155#if __cplusplus>=201103L
156 Ref(Ref&& o) :mon(o.mon), elem(o.elem) {
157 o.mon = 0;
158 o.elem.reset();
159 }
160#endif
161 void swap(Ref& o) {
162 std::swap(mon , o.mon);
163 std::swap(elem, o.elem);
164 }
167 MonitorElementPtr letGo() {
168 MonitorElementPtr ret;
169 elem.swap(ret);
170 return ret;
171 }
172 void attach(Monitor& M) {
173 reset();
174 mon = &M;
175 }
176 void attach(const Monitor::shared_pointer& M) {
177 reset();
178 mon = M.get();
179 }
180 bool next() {
181 if(elem) mon->release(elem);
182 elem = mon->poll();
183 return !!elem;
184 }
185 void reset() {
186 if(elem && mon) mon->release(elem);
187 elem.reset();
188 }
189 Ref& operator++() {// prefix increment. aka "++(*this)"
190 next();
191 return *this;
192 }
193#if __cplusplus>=201103L
194 inline explicit operator bool() const { return elem.get(); }
195#else
196private:
197 typedef const Monitor* const * hidden_bool_type;
198public:
199 operator hidden_bool_type() const { return elem.get() ? &mon : 0; }
200#endif
201 inline MonitorElement* operator->() { return elem.get(); }
202 inline MonitorElement& operator*() { return *elem; }
203 inline MonitorElement* get() { return elem.get(); }
204
205 inline bool operator==(const Ref& o) const { return elem==o.elem; }
206 inline bool operator!=(const Ref& o) const { return !(*this==o); }
207
208 EPICS_NOT_COPYABLE(Ref)
209};
210
211#if __cplusplus>=201103L
212// used by c++11 for-range
213inline MonitorElement::Ref begin(Monitor& mon) { return MonitorElement::Ref(mon); }
214inline MonitorElement::Ref end(Monitor& mon) { return MonitorElement::Ref(); }
215#endif // __cplusplus<201103L
216
258class epicsShareClass MonitorFIFO : public Monitor,
259 public std::tr1::enable_shared_from_this<MonitorFIFO>
260{
261public:
262 POINTER_DEFINITIONS(MonitorFIFO);
266 struct epicsShareClass Source {
267 POINTER_DEFINITIONS(Source);
268 virtual ~Source();
272 virtual void freeHighMark(MonitorFIFO *mon, size_t numEmpty) {}
273 };
274 struct epicsShareClass Config {
275 size_t maxCount,
276 defCount,
277 actualCount;
278 bool dropEmptyUpdates;
280 Config();
281 };
282
289 MonitorFIFO(const std::tr1::shared_ptr<MonitorRequester> &requester,
290 const pvData::PVStructure::const_shared_pointer &pvRequest,
291 const Source::shared_pointer& source = Source::shared_pointer(),
292 Config *conf=0);
293 virtual ~MonitorFIFO();
294
297 inline const std::tr1::shared_ptr<MonitorRequester> getRequester() const { return requester.lock(); }
298
299 void show(std::ostream& strm) const;
300
301 virtual void destroy() OVERRIDE FINAL;
302
303 // configuration
304
308 void setFreeHighMark(double level);
309
310 // up-stream interface (putting data into FIFO)
312 void open(const epics::pvData::StructureConstPtr& type);
314 void close();
316 void finish();
321 bool tryPost(const pvData::PVStructure& value,
322 const epics::pvData::BitSet& changed,
323 const epics::pvData::BitSet& overrun = epics::pvData::BitSet(),
324 bool force =false);
326 void post(const pvData::PVStructure& value,
327 const epics::pvData::BitSet& changed,
328 const epics::pvData::BitSet& overrun = epics::pvData::BitSet());
333 void notify();
334
335 // down-stream interface (taking data from FIFO)
336 virtual epics::pvData::Status start() OVERRIDE FINAL;
337 virtual epics::pvData::Status stop() OVERRIDE FINAL;
338 virtual MonitorElementPtr poll() OVERRIDE FINAL;
339 virtual void release(MonitorElementPtr const & monitorElement) OVERRIDE FINAL; // may call Source::freeHighMark()
340 virtual void getStats(Stats& s) const OVERRIDE FINAL;
341 virtual void reportRemoteQueueStatus(epics::pvData::int32 freeElements) OVERRIDE FINAL;
342
344 size_t freeCount() const;
345private:
346 size_t _freeCount() const;
347
348 friend void providerRegInit(void*);
349 static size_t num_instances;
350
351 // const after ctor
352 Config conf;
353
354 // locking here is complicated...
355 // our entry points which make callbacks are:
356 // notify() -> MonitorRequester::monitorConnect()
357 // -> MonitorRequester::monitorEvent()
358 // -> MonitorRequester::unlisten()
359 // -> ChannelBaseRequester::channelDisconnect()
360 // start() -> MonitorRequester::monitorEvent()
361 // release() -> Source::freeHighMark()
362 // -> notify() -> ...
363 // reportRemoteQueueStatus() -> Source::freeHighMark()
364 // -> notify() -> ...
365 mutable epicsMutex mutex;
366
367 // ownership is archored at the downstream (consumer) end.
368 // strong refs are:
369 // downstream -> MonitorFIFO -> Source
370 // weak refs are:
371 // MonitorRequester <- MonitorFIFO <- upstream
372
373 // so we expect that downstream will hold a strong ref to us,
374 // and we keep a weak ref to downstream's MonitorRequester
375 const std::tr1::weak_ptr<MonitorRequester> requester;
376
377 const epics::pvData::PVStructure::const_shared_pointer pvRequest;
378
379 // then we expect to keep a strong ref to upstream (Source)
380 // and expect that upstream will have only a weak ref to us.
381 const Source::shared_pointer upstream;
382
383 enum state_t {
384 Closed, // not open()'d
385 Opened, // successful open()
386 Error, // unsuccessful open()
387 } state;
388 bool pipeline; // const after ctor
389 bool running; // start() vs. stop()
390 bool finished; // finish() called
391 epics::pvData::BitSet scratch, oscratch; // using during post to avoid re-alloc
392
393 bool needConnected;
394 bool needEvent;
395 bool needUnlisten;
396 bool needClosed;
397
398 epics::pvData::Status error; // Set when entering Error state
399
400 size_t freeHighLevel;
401 epicsInt32 flowCount;
402
404
405 typedef std::list<MonitorElementPtr> buffer_t;
406 // we allocate one extra buffer element to hold data when post()
407 // while all elements poll()'d. So there will always be one
408 // element on either the empty or inuse lists
409 buffer_t inuse, empty, returned;
410 /* our elements are in one of 4 states
411 * Empty - on empty list
412 * In Use - on inuse list
413 * Polled - Returnedd from poll(). Not tracked
414 * Returned - only if pipeline==true, release()'d but not ack'd
415 */
416
417 EPICS_NOT_COPYABLE(MonitorFIFO)
418};
419
420static inline
421std::ostream& operator<<(std::ostream& strm, const MonitorFIFO& fifo) {
422 fifo.show(strm);
423 return strm;
424}
425
426}}
427
428namespace epics { namespace pvData {
429
431using epics::pvAccess::MonitorElementPtr;
434using epics::pvAccess::MonitorPtr;
435}}
436
437#endif /* MONITOR_H */
constexpr _Require< __not_< __is_tuple_like< _Tp > >, is_move_constructible< _Tp >, is_move_assignable< _Tp > > swap(_Tp &, _Tp &) noexcept(__and_< is_nothrow_move_constructible< _Tp >, is_nothrow_move_assignable< _Tp > >::value)
size_t start() const
basic_ostream< _CharT, _Traits > & operator<<(basic_ostream< _CharT, _Traits > &__os, const basic_string< _CharT, _Traits, _Alloc > &__str)
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
constexpr auto begin(_Container &__cont) -> decltype(__cont.begin())
constexpr auto end(_Container &__cont) -> decltype(__cont.end())
Instance declaring destroy method.
Definition destroyable.h:24
A (single ownership) smart pointer to extract a MonitorElement from a Monitor queue.
Definition monitor.h:147
MonitorElementPtr letGo()
analogous to auto_ptr<>::release() but given a different name to avoid being confused with Monitor::r...
Definition monitor.h:167
An element for a monitorQueue.
Definition monitor.h:54
Utility implementation of Monitor.
Definition monitor.h:260
MonitorFIFO(const std::tr1::shared_ptr< MonitorRequester > &requester, const pvData::PVStructure::const_shared_pointer &pvRequest, const Source::shared_pointer &source=Source::shared_pointer(), Config *conf=0)
const std::tr1::shared_ptr< MonitorRequester > getRequester() const
Access to MonitorRequester passed to ctor, or NULL if it has already been destroyed.
Definition monitor.h:297
virtual void destroy()
Destroy this instance.
Access to Monitor subscription and queue.
Definition monitor.h:69
virtual epics::pvData::Status stop()=0
Stop Monitoring.
virtual epics::pvData::Status start()=0
Start monitoring.
virtual void reportRemoteQueueStatus(epics::pvData::int32 freeElements)
Report remote queue status.
Definition monitor.h:114
virtual MonitorElementPtr poll()=0
If monitor has occurred return data.
virtual void release(MonitorElementPtr const &monitorElement)=0
Release a MonitorElement that was returned by poll.
Callback implemented by monitor clients.
Definition pvAccess.h:249
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Copyright - See the COPYRIGHT that is included with this distribution.
Source methods may be called with downstream mutex locked.
Definition monitor.h:266
virtual void freeHighMark(MonitorFIFO *mon, size_t numEmpty)
Called when MonitorFIFO::freeCount() rises above the level computed from MonitorFIFO::setFreeHighMark...
Definition monitor.h:272