pvAccessCPP  7.1.7
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 
37 namespace epics { namespace pvAccess {
38 
39 class MonitorRequester;
40 class MonitorElement;
41 typedef std::tr1::shared_ptr<MonitorElement> MonitorElementPtr;
43 
44 class Monitor;
45 typedef std::tr1::shared_ptr<Monitor> MonitorPtr;
46 
47 
54 class epicsShareClass MonitorElement {
55 public:
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 
69 class epicsShareClass Monitor : public virtual Destroyable{
70  public:
71  POINTER_DEFINITIONS(Monitor);
73 
74  virtual ~Monitor(){}
79  virtual epics::pvData::Status start() = 0;
84  virtual epics::pvData::Status stop() = 0;
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;
150 public:
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
196 private:
197  typedef const Monitor* const * hidden_bool_type;
198 public:
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
213 inline MonitorElement::Ref begin(Monitor& mon) { return MonitorElement::Ref(mon); }
214 inline MonitorElement::Ref end(Monitor& mon) { return MonitorElement::Ref(); }
215 #endif // __cplusplus<201103L
216 
258 class epicsShareClass MonitorFIFO : public Monitor,
259  public std::tr1::enable_shared_from_this<MonitorFIFO>
260 {
261 public:
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;
279  epics::pvData::PVRequestMapper::mode_t mapperMode;
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;
345 private:
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 
403  epics::pvData::PVRequestMapper mapper;
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 
420 static inline
421 std::ostream& operator<<(std::ostream& strm, const MonitorFIFO& fifo) {
422  fifo.show(strm);
423  return strm;
424 }
425 
426 }}
427 
428 namespace epics { namespace pvData {
429 
431 using epics::pvAccess::MonitorElementPtr;
434 using epics::pvAccess::MonitorPtr;
435 }}
436 
437 #endif /* MONITOR_H */
MonitorElementPtr letGo()
analogous to auto_ptr&lt;&gt;::release() but given a different name to avoid being confused with Monitor::r...
Definition: monitor.h:167
virtual void freeHighMark(MonitorFIFO *mon, size_t numEmpty)
Called when MonitorFIFO::freeCount() rises above the level computed from MonitorFIFO::setFreeHighMark...
Definition: monitor.h:272
basic_ostream< _CharT, _Traits > & operator<<(basic_ostream< _CharT, _Traits > &__os, const basic_string< _CharT, _Traits, _Alloc > &__str)
size_t start() const
Source methods may be called with downstream mutex locked.
Definition: monitor.h:266
Access to Monitor subscription and queue.
Definition: monitor.h:69
Utility implementation of Monitor.
Definition: monitor.h:258
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
enable_if< __and_< __not_< __is_tuple_like< _Tp > >, is_move_constructible< _Tp >, is_move_assignable< _Tp > >::value >::type swap(_Tp &__a, _Tp &__b) noexcept(__and_< is_nothrow_move_constructible< _Tp >, is_nothrow_move_assignable< _Tp >>::value)
_Tp * begin(valarray< _Tp > &__va)
Callback implemented by monitor clients.
Definition: pvAccess.h:249
virtual void release(MonitorElementPtr const &monitorElement)=0
Release a MonitorElement that was returned by poll.
virtual void reportRemoteQueueStatus(epics::pvData::int32 freeElements)
Report remote queue status.
Definition: monitor.h:114
Instance declaring destroy method.
Definition: destroyable.h:24
_Tp * end(valarray< _Tp > &__va)
A (single ownership) smart pointer to extract a MonitorElement from a Monitor queue.
Definition: monitor.h:146
virtual MonitorElementPtr poll()=0
If monitor has occurred return data.
An element for a monitorQueue.
Definition: monitor.h:54