This is Unofficial EPICS BASE Doxygen Site
ChannelAccessFactory.cpp
Go to the documentation of this file.
1 
7 #include <map>
8 #include <vector>
9 
10 #include <osiSock.h>
11 #include <epicsThread.h>
12 #include <epicsSignal.h>
13 
14 #include <pv/lock.h>
15 #include <pv/noDefaultMethods.h>
16 #include <pv/pvData.h>
17 #include <pv/reftrack.h>
18 #include <pv/timer.h>
19 
20 #define epicsExportSharedSymbols
21 #include <pv/pvAccess.h>
22 #include <pv/clientContextImpl.h>
23 #include <pv/factory.h>
24 #include "pv/codec.h"
25 #include <pv/serverContextImpl.h>
26 #include <pv/serverChannelImpl.h>
27 #include <pv/blockingUDP.h>
28 #include <sharedstateimpl.h>
29 
30 using namespace epics::pvData;
31 using std::string;
32 
33 namespace pvas {
35 }
36 
37 namespace epics {
38 namespace pvAccess {
39 
40 ChannelProviderRegistry::shared_pointer ChannelProviderRegistry::build() {
41  ChannelProviderRegistry::shared_pointer ret(new ChannelProviderRegistry);
42  return ret;
43 }
44 
45 ChannelProvider::shared_pointer ChannelProviderRegistry::getProvider(std::string const & providerName) {
46  ChannelProviderFactory::shared_pointer fact(getFactory(providerName));
47  if(fact)
48  return fact->sharedInstance();
49  else
50  return ChannelProvider::shared_pointer();
51 }
52 
53 ChannelProvider::shared_pointer ChannelProviderRegistry::createProvider(std::string const & providerName,
54  const std::tr1::shared_ptr<Configuration>& conf) {
55  ChannelProviderFactory::shared_pointer fact(getFactory(providerName));
56  if(fact)
57  return fact->newInstance(conf);
58  else
59  return ChannelProvider::shared_pointer();
60 }
61 
62 ChannelProviderFactory::shared_pointer ChannelProviderRegistry::getFactory(std::string const & providerName)
63 {
64  Lock G(mutex);
65  providers_t::const_iterator iter = providers.find(providerName);
66  if (iter == providers.end())
67  return ChannelProviderFactory::shared_pointer();
68  else
69  return iter->second;
70 }
71 
72 void ChannelProviderRegistry::getProviderNames(std::set<std::string>& names)
73 {
74  Lock G(mutex);
75  for (providers_t::const_iterator iter = providers.begin();
76  iter != providers.end(); iter++)
77  names.insert(iter->first);
78 }
79 
80 
81 bool ChannelProviderRegistry::add(const ChannelProviderFactory::shared_pointer& fact, bool replace)
82 {
83  assert(fact);
84  Lock G(mutex);
85  std::string name(fact->getFactoryName());
86  if(!replace && providers.find(name)!=providers.end())
87  return false;
88  providers[name] = fact;
89  return true;
90 }
91 
92 namespace {
93 struct FunctionFactory : public ChannelProviderFactory {
94  const std::string pname;
96  ChannelProvider::weak_pointer shared;
97  const ChannelProviderRegistry::factoryfn_t fn;
98 
99  FunctionFactory(const std::string& name, ChannelProviderRegistry::factoryfn_t fn)
100  :pname(name), fn(fn)
101  {}
102  virtual ~FunctionFactory() {}
103  virtual std::string getFactoryName() { return pname; }
104 
105  virtual ChannelProvider::shared_pointer sharedInstance()
106  {
107  epics::pvData::Lock L(sharedM);
108  ChannelProvider::shared_pointer ret(shared.lock());
109  if(!ret) {
110  ret = fn(std::tr1::shared_ptr<Configuration>());
111  shared = ret;
112  }
113  return ret;
114  }
115 
116  virtual ChannelProvider::shared_pointer newInstance(const std::tr1::shared_ptr<Configuration>& conf)
117  {
118  return fn(conf);
119  }
120 
121 };
122 }//namespace
123 
124 ChannelProviderFactory::shared_pointer ChannelProviderRegistry::add(const std::string& name, factoryfn_t fn, bool replace)
125 {
126  ChannelProviderFactory::shared_pointer F(new FunctionFactory(name, fn));
127  return add(F, replace) ? F : ChannelProviderFactory::shared_pointer();
128 }
129 
130 namespace {
134 struct InstanceChannelProviderFactory : public ChannelProviderFactory
135 {
136  InstanceChannelProviderFactory(const std::tr1::shared_ptr<ChannelProvider>& provider)
137  :name(provider->getProviderName())
138  ,provider(provider)
139  {}
140  virtual ~InstanceChannelProviderFactory() {}
141  virtual std::string getFactoryName() OVERRIDE FINAL
142  {
143  return name;
144  }
145  virtual ChannelProvider::shared_pointer sharedInstance() OVERRIDE FINAL
146  {
147  return provider.lock();
148  }
149  virtual ChannelProvider::shared_pointer newInstance(const std::tr1::shared_ptr<Configuration>& conf) OVERRIDE FINAL
150  {
151  return provider.lock();
152  }
153 private:
154  const std::string name;
155  const ChannelProvider::weak_pointer provider;
156 };
157 }//namespace
158 
159 ChannelProviderFactory::shared_pointer ChannelProviderRegistry::addSingleton(const ChannelProvider::shared_pointer& provider,
160  bool replace)
161 {
162  std::tr1::shared_ptr<InstanceChannelProviderFactory> F(new InstanceChannelProviderFactory(provider));
163  return add(F, replace) ? F : std::tr1::shared_ptr<InstanceChannelProviderFactory>();
164 }
165 
166 ChannelProviderFactory::shared_pointer ChannelProviderRegistry::remove(const std::string& name)
167 {
168  Lock G(mutex);
169  ChannelProviderFactory::shared_pointer fact(getFactory(name));
170  if(fact) {
171  remove(fact);
172  }
173  return fact;
174 }
175 
176 bool ChannelProviderRegistry::remove(const ChannelProviderFactory::shared_pointer& fact)
177 {
178  assert(fact);
179  Lock G(mutex);
180  providers_t::iterator iter(providers.find(fact->getFactoryName()));
181  if(iter!=providers.end() && iter->second==fact) {
182  providers.erase(iter);
183  return true;
184  }
185  return false;
186 }
187 
188 void ChannelProviderRegistry::clear()
189 {
190  Lock G(mutex);
191  providers.clear();
192 }
193 
194 namespace {
195 struct providerRegGbl_t {
196  ChannelProviderRegistry::shared_pointer clients,
197  servers;
198  providerRegGbl_t()
199  :clients(ChannelProviderRegistry::build())
200  ,servers(ChannelProviderRegistry::build())
201  {}
202 } *providerRegGbl;
203 
204 epicsThreadOnceId providerRegOnce = EPICS_THREAD_ONCE_INIT;
205 
206 } // namespace
207 
208 void providerRegInit(void*)
209 {
212 
213  providerRegGbl = new providerRegGbl_t;
214  providerRegGbl->clients->add("pva", createClientProvider);
215 
216  registerRefCounter("ServerContextImpl", &ServerContextImpl::num_instances);
217  registerRefCounter("ServerChannel", &ServerChannel::num_instances);
218  registerRefCounter("Transport (ABC)", &Transport::num_instances);
219  registerRefCounter("BlockingTCPTransportCodec", &detail::BlockingTCPTransportCodec::num_instances);
220  registerRefCounter("BlockingUDPTransport", &BlockingUDPTransport::num_instances);
221  registerRefCounter("ChannelProvider (ABC)", &ChannelProvider::num_instances);
222  registerRefCounter("Channel (ABC)", &Channel::num_instances);
223  registerRefCounter("ChannelRequester (ABC)", &ChannelRequester::num_instances);
224  registerRefCounter("ChannelBaseRequester (ABC)", &ChannelBaseRequester::num_instances);
225  registerRefCounter("ChannelRequest (ABC)", &ChannelRequest::num_instances);
226  registerRefCounter("ResponseHandler (ABC)", &ResponseHandler::num_instances);
227  registerRefCounter("MonitorFIFO", &MonitorFIFO::num_instances);
232  registerRefCounter("pvas::SharedPV", &pvas::SharedPV::num_instances);
233 }
234 
235 ChannelProviderRegistry::shared_pointer ChannelProviderRegistry::clients()
236 {
237  epicsThreadOnce(&providerRegOnce, &providerRegInit, 0);
238 
239  return providerRegGbl->clients;
240 }
241 
242 ChannelProviderRegistry::shared_pointer ChannelProviderRegistry::servers()
243 {
244  epicsThreadOnce(&providerRegOnce, &providerRegInit, 0);
245 
246  return providerRegGbl->servers;
247 }
248 
249 ChannelFind::shared_pointer
250 ChannelProvider::channelList(ChannelListRequester::shared_pointer const & requester)
251 {
252  ChannelFind::shared_pointer ret;
253  requester->channelListResult(Status::error("not implemented"),
254  ret,
256  false);
257  return ret;
258 }
259 
260 Channel::shared_pointer
261 ChannelProvider::createChannel(std::string const & name,
262  ChannelRequester::shared_pointer const & requester,
263  short priority)
264 {
265  return createChannel(name, requester, priority, "");
266 }
267 
268 }
269 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
ChannelProviderRegistry::shared_pointer servers
LIBCOM_API void epicsStdCall epicsSignalInstallSigPipeIgnore(void)
Definition: osdSignal.cpp:17
static Status error(const std::string &m)
Definition: status.h:50
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
A lock for multithreading.
Definition: lock.h:36
static size_t num_instances
void providerRegInit(void *)
#define OVERRIDE
Definition: pvAccess.h:55
#define EPICS_THREAD_ONCE_INIT
Definition: epicsThread.h:109
pvData
Definition: monitor.h:428
ChannelProvider::shared_pointer createClientProvider(const Configuration::shared_pointer &conf)
epicsMutex mutex
Definition: pvAccess.cpp:71
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
ChannelProviderRegistry::shared_pointer clients
const ChannelProcessRequester::weak_pointer requester
Definition: pvAccess.cpp:68
See Server API API.
LIBCOM_API void epicsStdCall epicsSignalInstallSigAlarmIgnore(void)
Definition: osdSignal.cpp:18
void registerRefCounter(const char *name, const size_t *counter)
Definition: reftrack.cpp:59
void registerRefTrackServer()
Definition: server.cpp:281
const ChannelProviderRegistry::factoryfn_t fn
epics::pvData::Mutex sharedM
ChannelProvider::weak_pointer shared
OS-independent routines for ignoring Posix signals.
const std::string pname
epicsMutex Mutex
Definition: lock.h:28
C++ and C descriptions for a thread.
#define FINAL
Definition: pvAccess.h:48