This is Unofficial EPICS BASE Doxygen Site
clientpvt.h
Go to the documentation of this file.
1 #ifndef CLIENTPVT_H
2 #define CLIENTPVT_H
3 
4 #include <utility>
5 
6 #include <epicsEvent.h>
7 #include <epicsThread.h>
8 
9 #include <pv/sharedPtr.h>
10 
11 #include <pva/client.h>
12 
13 namespace pvd = epics::pvData;
14 namespace pva = epics::pvAccess;
17 
18 namespace pvac{namespace detail{
19 /* Like std::tr1::enable_shared_from_this
20  * with the notion of internal vs. external references.
21  * External references wrap an internal reference.
22  * When the last external reference is dropped,
23  * then Derived::cancel() is called, but the object isn't free'd
24  * until all internal references are dropped as well.
25  */
26 template<typename Derived>
28 private:
29  // const after build()
30  std::tr1::weak_ptr<Derived> myselfptr;
31 
32  struct canceller {
33  std::tr1::shared_ptr<Derived> ptr;
34  canceller(const std::tr1::shared_ptr<Derived>& ptr) :ptr(ptr) {}
35 
36  void operator()(Derived *) {
37  std::tr1::shared_ptr<Derived> P;
38  P.swap(ptr);
39  P->cancel();
40  }
41  };
42 
43 public:
44  std::tr1::shared_ptr<Derived> internal_shared_from_this() {
45  std::tr1::shared_ptr<Derived> ret(myselfptr);
46  if(!ret)
47  throw std::tr1::bad_weak_ptr();
48  return ret;
49  }
50 
51 #if __cplusplus>=201103L
52  template<class ...Args>
53  static
54  std::tr1::shared_ptr<Derived> build(Args... args) {
55  std::tr1::shared_ptr<Derived> inner(new Derived(std::forward<Args>(args)...)),
56  ret(inner.get(), canceller(inner));
57  inner->myselfptr = inner;
58  return ret;
59  }
60 #else
61  static
62  std::tr1::shared_ptr<Derived> build() {
63  std::tr1::shared_ptr<Derived> inner(new Derived),
64  ret(inner.get(), canceller(inner));
65  inner->myselfptr = inner;
66  return ret;
67  }
68 
69  template<typename A>
70  static
71  std::tr1::shared_ptr<Derived> build(A a) {
72  std::tr1::shared_ptr<Derived> inner(new Derived(a)),
73  ret(inner.get(), canceller(inner));
74  inner->myselfptr = inner;
75  return ret;
76  }
77 
78  template<typename A, typename B>
79  static
80  std::tr1::shared_ptr<Derived> build(A a, B b) {
81  std::tr1::shared_ptr<Derived> inner(new Derived(a, b)),
82  ret(inner.get(), canceller(inner));
83  inner->myselfptr = inner;
84  return ret;
85  }
86 #endif
87 };
88 
118  mutable epicsMutex mutex;
120  size_t nwaitcb;
122  CallbackStorage() :nwaitcb(0u), incb(0) {}
123 };
124 
125 // analogous to epicsGuard
129  explicit CallbackGuard(CallbackStorage& store) :store(store), self(0) {
130  store.mutex.lock();
131  }
133  bool notify = store.nwaitcb!=0;
134  store.mutex.unlock();
135  if(notify)
136  store.wakeup.signal();
137  }
138  void ensureself() {
139  if(!self)
140  self = epicsThreadGetIdSelf();
141  }
142  // unlock and block until no in-progress callbacks
143  void wait() {
144  if(!store.incb) return;
145  ensureself();
146  store.nwaitcb++;
147  while(store.incb && store.incb!=self) {
148  store.mutex.unlock();
149  store.wakeup.wait();
150  store.mutex.lock();
151  }
152  store.nwaitcb--;
153  }
154 };
155 
156 // analogous to epicsGuardRelease
157 struct CallbackUse {
159  explicit CallbackUse(CallbackGuard& G) :G(G) {
160  G.wait(); // serialize callbacks
161  G.ensureself();
162  G.store.incb=G.self;
163  G.store.mutex.unlock();
164  }
166  G.store.mutex.lock();
167  G.store.incb=0;
168  }
169 };
170 
171 
172 void registerRefTrack();
173 void registerRefTrackGet();
174 void registerRefTrackPut();
176 void registerRefTrackRPC();
177 void registerRefTrackInfo();
178 
179 }} // namespace pvac::detail
180 
181 #endif // CLIENTPVT_H
void registerRefTrackInfo()
Definition: clientInfo.cpp:117
void registerRefTrack()
Definition: client.cpp:375
void registerRefTrackMonitor()
void registerRefTrackPut()
Definition: clientPut.cpp:233
static std::tr1::shared_ptr< Derived > build(A a)
Definition: clientpvt.h:71
static std::tr1::shared_ptr< Derived > build()
Definition: clientpvt.h:62
Holds all PVA related.
Definition: pvif.h:34
void registerRefTrackGet()
Definition: clientGet.cpp:171
pvData
Definition: monitor.h:428
std::tr1::shared_ptr< Derived > internal_shared_from_this()
Definition: clientpvt.h:44
CallbackStorage & store
Definition: clientpvt.h:127
APIs for the epicsEvent binary semaphore.
epicsGuard< epicsMutex > Guard
Definition: clientpvt.h:15
epicsGuardRelease< epicsMutex > UnGuard
Definition: clientpvt.h:16
CallbackGuard & G
Definition: clientpvt.h:158
void registerRefTrackRPC()
Definition: clientRPC.cpp:179
CallbackUse(CallbackGuard &G)
Definition: clientpvt.h:159
C++ and C descriptions for a thread.
static std::tr1::shared_ptr< Derived > build(A a, B b)
Definition: clientpvt.h:80
CallbackGuard(CallbackStorage &store)
Definition: clientpvt.h:129
See Client API API.
Definition: client.cpp:30
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810