Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
usServiceRegistrationBase.cpp
Go to the documentation of this file.
1 /*=============================================================================
2 
3  Library: CppMicroServices
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics
7 
8  Licensed under the Apache License, Version 2.0 (the "License");
9  you may not use this file except in compliance with the License.
10  You may obtain a copy of the License at
11 
12  http://www.apache.org/licenses/LICENSE-2.0
13 
14  Unless required by applicable law or agreed to in writing, software
15  distributed under the License is distributed on an "AS IS" BASIS,
16  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  See the License for the specific language governing permissions and
18  limitations under the License.
19 
20 =============================================================================*/
21 
23 #include "usServiceRegistrationBasePrivate.h"
24 #include "usServiceListenerEntry_p.h"
25 #include "usServiceRegistry_p.h"
26 #include "usServiceFactory.h"
27 
28 #include "usModulePrivate.h"
29 #include "usCoreModuleContext_p.h"
30 
31 #include <stdexcept>
32 
33 US_BEGIN_NAMESPACE
34 
35 ServiceRegistrationBase::ServiceRegistrationBase()
36  : d(0)
37 {
38 
39 }
40 
41 ServiceRegistrationBase::ServiceRegistrationBase(const ServiceRegistrationBase& reg)
42  : d(reg.d)
43 {
44  if (d) d->ref.Ref();
45 }
46 
47 ServiceRegistrationBase::ServiceRegistrationBase(ServiceRegistrationBasePrivate* registrationPrivate)
48  : d(registrationPrivate)
49 {
50  if (d) d->ref.Ref();
51 }
52 
53 ServiceRegistrationBase::ServiceRegistrationBase(ModulePrivate* module, const InterfaceMap& service,
54  const ServicePropertiesImpl& props)
55  : d(new ServiceRegistrationBasePrivate(module, service, props))
56 {
57 
58 }
59 
60 ServiceRegistrationBase::operator bool_type() const
61 {
62  return d != NULL ? &ServiceRegistrationBase::d : NULL;
63 }
64 
66 {
67  if (null == 0)
68  {
69  if (d && !d->ref.Deref())
70  {
71  delete d;
72  }
73  d = 0;
74  }
75  return *this;
76 }
77 
79 {
80  if (d && !d->ref.Deref())
81  delete d;
82 }
83 
84 ServiceReferenceBase ServiceRegistrationBase::GetReference(const std::string& interfaceId) const
85 {
86  if (!d) throw std::logic_error("ServiceRegistrationBase object invalid");
87  if (!d->available) throw std::logic_error("Service is unregistered");
88 
89  ServiceReferenceBase ref = d->reference;
90  ref.SetInterfaceId(interfaceId);
91  return ref;
92 }
93 
95 {
96  if (!d) throw std::logic_error("ServiceRegistrationBase object invalid");
97 
98  MutexLock lock(d->eventLock);
99 
100  ServiceEvent modifiedEndMatchEvent(ServiceEvent::MODIFIED_ENDMATCH, d->reference);
101  ServiceListeners::ServiceListenerEntries before;
102  // TBD, optimize the locking of services
103  {
104  //MutexLock lock2(d->module->coreCtx->globalFwLock);
105 
106  if (d->available)
107  {
108  // NYI! Optimize the MODIFIED_ENDMATCH code
109  int old_rank = 0;
110  int new_rank = 0;
111 
112  std::vector<std::string> classes;
113  {
114  MutexLock lock3(d->propsLock);
115 
116  {
117  const Any& any = d->properties.Value(ServiceConstants::SERVICE_RANKING());
118  if (any.Type() == typeid(int)) old_rank = any_cast<int>(any);
119  }
120 
121  d->module->coreCtx->listeners.GetMatchingServiceListeners(modifiedEndMatchEvent, before, false);
122  classes = ref_any_cast<std::vector<std::string> >(d->properties.Value(ServiceConstants::OBJECTCLASS()));
123  long int sid = any_cast<long int>(d->properties.Value(ServiceConstants::SERVICE_ID()));
124  d->properties = ServiceRegistry::CreateServiceProperties(props, classes, false, false, sid);
125 
126  {
127  const Any& any = d->properties.Value(ServiceConstants::SERVICE_RANKING());
128  if (any.Type() == typeid(int)) new_rank = any_cast<int>(any);
129  }
130  }
131 
132  if (old_rank != new_rank)
133  {
134  d->module->coreCtx->services.UpdateServiceRegistrationOrder(*this, classes);
135  }
136  }
137  else
138  {
139  throw std::logic_error("Service is unregistered");
140  }
141  }
142  ServiceEvent modifiedEvent(ServiceEvent::MODIFIED, d->reference);
143  ServiceListeners::ServiceListenerEntries matchingListeners;
144  d->module->coreCtx->listeners.GetMatchingServiceListeners(modifiedEvent, matchingListeners);
145  d->module->coreCtx->listeners.ServiceChanged(matchingListeners,
146  modifiedEvent,
147  before);
148 
149  d->module->coreCtx->listeners.ServiceChanged(before,
150  modifiedEndMatchEvent);
151 }
152 
154 {
155  if (!d) throw std::logic_error("ServiceRegistrationBase object invalid");
156 
157  if (d->unregistering) return; // Silently ignore redundant unregistration.
158  {
159  MutexLock lock(d->eventLock);
160  if (d->unregistering) return;
161  d->unregistering = true;
162 
163  if (d->available)
164  {
165  if (d->module)
166  {
167  d->module->coreCtx->services.RemoveServiceRegistration(*this);
168  }
169  }
170  else
171  {
172  throw std::logic_error("Service is unregistered");
173  }
174  }
175 
176  if (d->module)
177  {
178  ServiceListeners::ServiceListenerEntries listeners;
179  ServiceEvent unregisteringEvent(ServiceEvent::UNREGISTERING, d->reference);
180  d->module->coreCtx->listeners.GetMatchingServiceListeners(unregisteringEvent, listeners);
181  d->module->coreCtx->listeners.ServiceChanged(
182  listeners,
183  unregisteringEvent);
184  }
185 
186  {
187  MutexLock lock(d->eventLock);
188  {
189  MutexLock lock2(d->propsLock);
190  d->available = false;
191  InterfaceMap::const_iterator factoryIter = d->service.find("org.cppmicroservices.factory");
192  if (d->module && factoryIter != d->service.end())
193  {
194  ServiceFactory* serviceFactory = reinterpret_cast<ServiceFactory*>(factoryIter->second);
195  ServiceRegistrationBasePrivate::ModuleToServicesMap::const_iterator end = d->prototypeServiceInstances.end();
196 
197  // unget all prototype services
198  for (ServiceRegistrationBasePrivate::ModuleToServicesMap::const_iterator i = d->prototypeServiceInstances.begin();
199  i != end; ++i)
200  {
201  for (std::list<InterfaceMap>::const_iterator listIter = i->second.begin();
202  listIter != i->second.end(); ++listIter)
203  {
204  const InterfaceMap& service = *listIter;
205  try
206  {
207  // NYI, don't call inside lock
208  serviceFactory->UngetService(i->first, *this, service);
209  }
210  catch (const std::exception& /*ue*/)
211  {
212  US_WARN << "ServiceFactory UngetService implementation threw an exception";
213  }
214  }
215  }
216 
217  // unget module scope services
218  ServiceRegistrationBasePrivate::ModuleToServiceMap::const_iterator moduleEnd = d->moduleServiceInstance.end();
219  for (ServiceRegistrationBasePrivate::ModuleToServiceMap::const_iterator i = d->moduleServiceInstance.begin();
220  i != moduleEnd; ++i)
221  {
222  try
223  {
224  // NYI, don't call inside lock
225  serviceFactory->UngetService(i->first, *this, i->second);
226  }
227  catch (const std::exception& /*ue*/)
228  {
229  US_WARN << "ServiceFactory UngetService implementation threw an exception";
230  }
231  }
232  }
233  d->module = 0;
234  d->dependents.clear();
235  d->service.clear();
236  d->prototypeServiceInstances.clear();
237  d->moduleServiceInstance.clear();
238  // increment the reference count, since "d->reference" was used originally
239  // to keep d alive.
240  d->ref.Ref();
241  d->reference = 0;
242  d->unregistering = false;
243  }
244  }
245 }
246 
248 {
249  if ((!d && !o.d) || !o.d) return false;
250  if (!d) return true;
251  return d->reference <(o.d->reference);
252 }
253 
255 {
256  return d == registration.d;
257 }
258 
260 {
261  ServiceRegistrationBasePrivate* curr_d = d;
262  d = registration.d;
263  if (d) d->ref.Ref();
264 
265  if (curr_d && !curr_d->ref.Deref())
266  delete curr_d;
267 
268  return *this;
269 }
270 
271 US_END_NAMESPACE
ServiceRegistrationBase & operator=(int null)
const std::type_info & Type() const
Definition: usAny.h:278
US_Core_EXPORT const std::string & SERVICE_RANKING()
std::map< std::string, void * > InterfaceMap
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
ServiceReferenceBase GetReference(const std::string &interfaceId=std::string()) const
Definition: usAny.h:163
bool operator<(const ServiceRegistrationBase &o) const
US_Core_EXPORT const std::string & OBJECTCLASS()
US_UNORDERED_MAP_TYPE< std::string, Any > ServiceProperties
const ValueType & ref_any_cast(const Any &operand)
Definition: usAny.h:449
bool operator==(const ServiceRegistrationBase &registration) const
virtual void UngetService(Module *module, const ServiceRegistrationBase &registration, const InterfaceMap &service)=0
void SetProperties(const ServiceProperties &properties)
US_Core_EXPORT const std::string & SERVICE_ID()