diff --git a/Core/Code/Service/mitkLDAPFilter.h b/Core/Code/Service/mitkLDAPFilter.h index 8f859b6a32..6f886f851a 100644 --- a/Core/Code/Service/mitkLDAPFilter.h +++ b/Core/Code/Service/mitkLDAPFilter.h @@ -1,163 +1,161 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKLDAPFILTER_H #define MITKLDAPFILTER_H -#include "mitkCommon.h" - #include "mitkServiceReference.h" #include "mitkServiceProperties.h" #include "mitkSharedData.h" namespace mitk { class LDAPFilterData; /** * \ingroup MicroServices * * An RFC 1960-based Filter. * *

* A LDAPFilter can be used numerous times to determine if the match * argument matches the filter string that was used to create the LDAPFilter. *

* Some examples of LDAP filters are: * * - "(cn=Babs Jensen)" * - "(!(cn=Tim Howes))" * - "(&(" + ServiceConstants::OBJECTCLASS() + "=Person)(|(sn=Jensen)(cn=Babs J*)))" * - "(o=univ*of*mich*)" * * \remarks This class is thread safe. */ class MITK_CORE_EXPORT LDAPFilter { public: /** * Creates in invalid LDAPFilter object. * Test the validity by using the boolean conversion operator. * *

* Calling methods on an invalid LDAPFilter * will result in undefined behavior. */ LDAPFilter(); /** * Creates a LDAPFilter object. This LDAPFilter * object may be used to match a ServiceReference object or a * ServiceProperties object. * *

* If the filter cannot be parsed, an std::invalid_argument will be * thrown with a human readable message where the filter became unparsable. * * @param filter The filter string. * @return A LDAPFilter object encapsulating the filter string. * @throws std::invalid_argument If filter contains an invalid * filter string that cannot be parsed. * @see "Framework specification for a description of the filter string syntax." TODO! */ LDAPFilter(const std::string& filter); LDAPFilter(const LDAPFilter& other); ~LDAPFilter(); operator bool() const; /** * Filter using a service's properties. *

* This LDAPFilter is executed using the keys and values of the * referenced service's properties. The keys are looked up in a case * insensitive manner. * * @param reference The reference to the service whose properties are used * in the match. * @return true if the service's properties match this * LDAPFilter false otherwise. */ bool Match(const ServiceReference& reference) const; /** * Filter using a ServiceProperties object with case insensitive key lookup. This * LDAPFilter is executed using the specified ServiceProperties's keys * and values. The keys are looked up in a case insensitive manner. * * @param dictionary The ServiceProperties whose key/value pairs are used * in the match. * @return true if the ServiceProperties's values match this * filter; false otherwise. */ bool Match(const ServiceProperties& dictionary) const; /** * Filter using a ServiceProperties. This LDAPFilter is executed using * the specified ServiceProperties's keys and values. The keys are looked * up in a normal manner respecting case. * * @param dictionary The ServiceProperties whose key/value pairs are used * in the match. * @return true if the ServiceProperties's values match this * filter; false otherwise. */ bool MatchCase(const ServiceProperties& dictionary) const; /** * Returns this LDAPFilter's filter string. *

* The filter string is normalized by removing whitespace which does not * affect the meaning of the filter. * * @return This LDAPFilter's filter string. */ std::string ToString() const; /** * Compares this LDAPFilter to another LDAPFilter. * *

* This implementation returns the result of calling * this->ToString() == other.ToString(). * * @param other The object to compare against this LDAPFilter. * @return Returns the result of calling * this->ToString() == other.ToString(). */ bool operator==(const LDAPFilter& other) const; LDAPFilter& operator=(const LDAPFilter& filter); protected: SharedDataPointer d; }; } /** * \ingroup MicroServices */ MITK_CORE_EXPORT std::ostream& operator<<(std::ostream& os, const mitk::LDAPFilter& filter); #endif // MITKLDAPFILTER_H diff --git a/Core/Code/Service/mitkModule.cpp b/Core/Code/Service/mitkModule.cpp index d7321ee6f4..b209b240a1 100644 --- a/Core/Code/Service/mitkModule.cpp +++ b/Core/Code/Service/mitkModule.cpp @@ -1,223 +1,225 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkModule.h" #include "mitkModuleContext.h" #include "mitkModuleActivator.h" #include "mitkModulePrivate.h" #include "mitkCoreModuleContext_p.h" +#include + namespace mitk { const std::string& Module::PROP_ID() { static const std::string s("module.id"); return s; } const std::string& Module::PROP_NAME() { static const std::string s("module.name"); return s; } const std::string& Module::PROP_LOCATION() { static const std::string s("module.location"); return s; } const std::string& Module::PROP_MODULE_DEPENDS() { static const std::string s("module.module_depends"); return s; } const std::string& Module::PROP_LIB_DEPENDS() { static const std::string s("module.lib_depends"); return s; } const std::string& Module::PROP_PACKAGE_DEPENDS() { static const std::string s("module.package_depends"); return s; } const std::string& Module::PROP_VERSION() { static const std::string s("module.version"); return s; } const std::string& Module::PROP_QT() { static const std::string s("module.qt"); return s; } Module::Module() : d(0) { } Module::~Module() { delete d; } void Module::Init(CoreModuleContext* coreCtx, ModuleInfo* info) { ModulePrivate* mp = new ModulePrivate(this, coreCtx, info); std::swap(mp, d); delete mp; } bool Module::IsLoaded() const { return d->moduleContext != 0; } void Module::Start() { if (d->moduleContext) { MITK_WARN << "Module " << d->info.name << " already started."; return; } d->moduleContext = new ModuleContext(this->d); // try // { d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::LOADING, this)); // try to get a ModuleActivator instance if (d->info.activatorHook) { try { d->moduleActivator = d->info.activatorHook(); } catch (...) { MITK_ERROR << "Creating the module activator of " << d->info.name << " failed"; throw; } d->moduleActivator->Load(d->moduleContext); } d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::LOADED, this)); // } // catch (...) // { // d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADING, this)); // d->RemoveModuleResources(); // delete d->moduleContext; // d->moduleContext = 0; // d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADED, this)); // MITK_ERROR << "Calling the module activator Load() method of " << d->info.name << " failed!"; // throw; // } } void Module::Stop() { if (d->moduleContext == 0) { MITK_WARN << "Module " << d->info.name << " already stopped."; return; } try { d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADING, this)); if (d->moduleActivator) { d->moduleActivator->Unload(d->moduleContext); } } catch (...) { MITK_ERROR << "Calling the module activator Unload() method of " << d->info.name << " failed!"; try { d->RemoveModuleResources(); } catch (...) {} delete d->moduleContext; d->moduleContext = 0; d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADED, this)); throw; } d->RemoveModuleResources(); delete d->moduleContext; d->moduleContext = 0; d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADED, this)); } ModuleContext* Module::GetModuleContext() const { return d->moduleContext; } long Module::GetModuleId() const { return d->info.id; } std::string Module::GetLocation() const { return d->info.location; } std::string Module::GetName() const { return d->info.name; } ModuleVersion Module::GetVersion() const { return d->version; } std::string Module::GetProperty(const std::string& key) const { if (d->properties.count(key) == 0) return ""; return d->properties[key]; } } // end namespace mitk std::ostream& operator<<(std::ostream& os, const mitk::Module& module) { os << "Module[" << "id=" << module.GetModuleId() << ", loc=" << module.GetLocation() << ", name=" << module.GetName() << "]"; return os; } std::ostream& operator<<(std::ostream& os, mitk::Module const * module) { return operator<<(os, *module); } diff --git a/Core/Code/Service/mitkModule.h b/Core/Code/Service/mitkModule.h index 59d580050d..a793299260 100644 --- a/Core/Code/Service/mitkModule.h +++ b/Core/Code/Service/mitkModule.h @@ -1,243 +1,241 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKMODULE_H #define MITKMODULE_H -#include - #include "mitkModuleVersion.h" namespace mitk { class CoreModuleContext; class ModuleInfo; class ModuleContext; class ModulePrivate; /** * \ingroup MicroServices * * Represents a MITK module. * *

* A %Module object is the access point to a MITK module. * Each MITK module has an associated %Module object. * *

* A module has unique identity, a long, chosen by the * framework. This identity does not change during the lifecycle of a module. * *

* A module can be in one of two states: *

*

* You can determine the current state by using IsLoaded(). * *

* A module can only execute code when its state is LOADED. * An UNLOADED module is a * zombie and can only be reached because it was loaded before. However, * unloaded modules can be loaded again. * *

* The framework is the only entity that is allowed to create * %Module objects. * * @remarks This class is thread safe. */ class MITK_CORE_EXPORT Module { public: static const std::string& PROP_ID(); static const std::string& PROP_NAME(); static const std::string& PROP_LOCATION(); static const std::string& PROP_MODULE_DEPENDS(); static const std::string& PROP_PACKAGE_DEPENDS(); static const std::string& PROP_LIB_DEPENDS(); static const std::string& PROP_VERSION(); static const std::string& PROP_QT(); ~Module(); /** * Returns this module's current state. * *

* A module can be in only one state at any time. * * @return true if the module is LOADED * false if it is UNLOADED */ bool IsLoaded() const; /** * Returns this module's {@link ModuleContext}. The returned * ModuleContext can be used by the caller to act on behalf * of this module. * *

* If this module is not in the LOADED state, then this * module has no valid ModuleContext. This method will * return 0 if this module has no valid * ModuleContext. * * @return A ModuleContext for this module or * 0 if this module has no valid * ModuleContext. */ ModuleContext* GetModuleContext() const; /** * Returns this module's unique identifier. This module is assigned a unique * identifier by the framework when it was loaded. * *

* A module's unique identifier has the following attributes: *

* *

* This method continues to return this module's unique identifier while * this module is in the UNLOADED state. * * @return The unique identifier of this module. */ long GetModuleId() const; /** * Returns this module's location. * *

* The location is the full path to the module's shared library. * This method continues to return this module's location * while this module is in the UNLOADED state. * * @return The string representation of this module's location. */ std::string GetLocation() const; /** * Returns the name of this module as specified by the * MITK_CREATE_MODULE CMake macro. The module * name together with a version must identify a unique module. * *

* This method continues to return this module's name while * this module is in the UNLOADED state. * * @return The name of this module. */ std::string GetName() const; /** * Returns the version of this module as specified by the * MITK_CREATE_MODULE CMake macro. If this module does not have a * specified version then {@link ModuleVersion#EmptyVersion} is returned. * *

* This method continues to return this module's version while * this module is in the UNLOADED state. * * @return The version of this module. */ ModuleVersion GetVersion() const; /** * Returns the value of the specified property for this module. The * method returns an empty string if the property is not found. * * @param key The name of the requested property. * @return The value of the requested property, or an empty string * if the property is undefined. */ std::string GetProperty(const std::string& key) const; private: friend class ModuleRegistry; friend class ServiceReferencePrivate; ModulePrivate* d; Module(); Module(const Module&); void Init(CoreModuleContext* coreCtx, ModuleInfo* info); void Start(); void Stop(); }; } #ifdef MITK_HAS_UNORDERED_MAP_H namespace std { #elif defined(__GNUC__) namespace __gnu_cxx { #else namespace itk { #endif template class hash; template<> class hash { public: std::size_t operator()(const mitk::Module* module) const { #ifdef MITK_HAS_HASH_SIZE_T return hash()(reinterpret_cast(module)); #else std::size_t key = reinterpret_cast(module); return std::size_t(key & (~0U)); #endif } }; /** * \ingroup MicroServices */ namespace ModuleConstants { } } /** * \ingroup MicroServices */ MITK_CORE_EXPORT std::ostream& operator<<(std::ostream& os, const mitk::Module& module); /** * \ingroup MicroServices */ MITK_CORE_EXPORT std::ostream& operator<<(std::ostream& os, mitk::Module const * module); #endif // MITKMODULE_H diff --git a/Core/Code/Service/mitkModuleContext.h b/Core/Code/Service/mitkModuleContext.h index d1388ee58e..7057eac7d7 100644 --- a/Core/Code/Service/mitkModuleContext.h +++ b/Core/Code/Service/mitkModuleContext.h @@ -1,659 +1,657 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKMODULECONTEXT_H_ #define MITKMODULECONTEXT_H_ -#include - #include "mitkServiceInterface.h" #include "mitkMessage.h" #include "mitkServiceEvent.h" #include "mitkServiceRegistration.h" #include "mitkServiceException.h" #include "mitkModuleEvent.h" namespace mitk { typedef MessageAbstractDelegate1 ServiceListenerDelegate; typedef MessageAbstractDelegate1 ModuleListenerDelegate; class ModuleContextPrivate; /** * \ingroup MicroServices * * A module's execution context within the framework. The context is used to * grant access to other methods so that this module can interact with the * Micro Services Framework. * *

* ModuleContext methods allow a module to: *

* *

* A ModuleContext object will be created and provided to the * module associated with this context when it is loaded using the * {@link ModuleActivator::Load} method. The same ModuleContext * object will be passed to the module associated with this context when it is * unloaded using the {@link ModuleActivator::Unload} method. A * ModuleContext object is generally for the private use of its * associated module and is not meant to be shared with other modules in the * module environment. * *

* The Module object associated with a ModuleContext * object is called the context module. * *

* The ModuleContext object is only valid during the execution of * its context module; that is, during the period when the context module * is loaded. If the ModuleContext * object is used subsequently, a std::logic_error is * thrown. The ModuleContext object is never reused after * its context module is unloaded. * *

* The framework is the only entity that can create ModuleContext * objects. * * @remarks This class is thread safe. */ class MITK_CORE_EXPORT ModuleContext { public: ~ModuleContext(); /** * Returns the Module object associated with this * ModuleContext. This module is called the context module. * * @return The Module object associated with this * ModuleContext. * @throws std::logic_error If this ModuleContext is no * longer valid. */ Module* GetModule() const; /** * Returns the module with the specified identifier. * * @param id The identifier of the module to retrieve. * @return A Module object or 0 if the * identifier does not match any previously loaded module. */ Module* GetModule(long id) const; /** * Returns a list of all known modules. *

* This method returns a list of all modules loaded in the module * environment at the time of the call to this method. This list will * also contain modules which might already have been unloaded. * * @param modules A std::vector of Module objects which * will hold one object per known module. */ void GetModules(std::vector& modules) const; /** * Registers the specified service object with the specified properties * under the specified class names into the framework. A * ServiceRegistration object is returned. The * ServiceRegistration object is for the private use of the * module registering the service and should not be shared with other * modules. The registering module is defined to be the context module. * Other modules can locate the service by using either the * {@link #GetServiceReferences} or {@link #GetServiceReference} method. * *

* A module can register a service object that implements the * {@link ServiceFactory} interface to have more flexibility in providing * service objects to other modules. * *

* The following steps are taken when registering a service: *

    *
  1. The framework adds the following service properties to the service * properties from the specified ServiceProperties (which may be * omitted):
    * A property named {@link ServiceConstants#SERVICE_ID} identifying the * registration number of the service
    * A property named {@link ServiceConstants#OBJECTCLASS} containing all the * specified classes.
    * Properties with these names in the specified ServiceProperties will * be ignored. *
  2. The service is added to the framework service registry and may now be * used by other modules. *
  3. A service event of type {@link ServiceEvent#REGISTERED} is fired. *
  4. A ServiceRegistration object for this registration is * returned. *
* * @param clazzes The class names under which the service can be located. * The class names will be stored in the service's * properties under the key {@link ServiceConstants#OBJECTCLASS}. * @param service The service object or a ServiceFactory * object. * @param properties The properties for this service. The keys in the * properties object must all be std::string objects. See * {@link ServiceConstants} for a list of standard service property keys. * Changes should not be made to this object after calling this * method. To update the service's properties the * {@link ServiceRegistration::SetProperties} method must be called. * The set of properties may be omitted if the service has * no properties. * @return A ServiceRegistration object for use by the module * registering the service to update the service's properties or to * unregister the service. * @throws std::invalid_argument If one of the following is true: * * @throws std::logic_error If this ModuleContext is no longer valid. * @see ServiceRegistration * @see ServiceFactory */ ServiceRegistration RegisterService(const std::list& clazzes, itk::LightObject* service, const ServiceProperties& properties = ServiceProperties()); /** * Registers the specified service object with the specified properties * under the specified class name with the framework. * *

* This method is otherwise identical to * RegisterService(const std:vector&, itk::LighObject*, const ServiceProperties&) * and is provided as a convenience when service will only be registered under a single * class name. Note that even in this case the value of the service's * ServiceConstants::OBJECTCLASS property will be a std::list, rather * than just a single string. * * @param clazz The class name under which the service can be located. * @param service The service object or a ServiceFactory object. * @param properties The properties for this service. * @return A ServiceRegistration object for use by the module * registering the service to update the service's properties or to * unregister the service. * @throws std::logic_error If this ModuleContext is no longer valid. * @see RegisterService(const std:list&, itk::LighObject*, const ServiceProperties&) */ ServiceRegistration RegisterService(const char* clazz, itk::LightObject* service, const ServiceProperties& properties = ServiceProperties()); /** * Registers the specified service object with the specified properties * using the specified template argument with the framework. * *

* This method is provided as a convenience when service will only be registered under * a single class name whose type is available to the caller. It is otherwise identical to * RegisterService(const char*, itk::LightObject*, const ServiceProperties&) but should be preferred * since it avoids errors in the string literal identifying the class name or interface identifier. * * @tparam S The type under which the service can be located. * @param service The service object or a ServiceFactory object. * @param properties The properties for this service. * @return A ServiceRegistration object for use by the module * registering the service to update the service's properties or to * unregister the service. * @throws std::logic_error If this ModuleContext is no longer valid. * @see RegisterService(const char*, itk::LighObject*, const ServiceProperties&) */ template ServiceRegistration RegisterService(itk::LightObject* service, const ServiceProperties& properties = ServiceProperties()) { const char* clazz = mitk_service_interface_iid(); if (clazz == 0) { throw ServiceException(std::string("The interface class you are registering your service ") + service->GetNameOfClass() + " against has no MITK_DECLARE_SERVICE_INTERFACE macro"); } return RegisterService(clazz, service, properties); } /** * Returns a list of ServiceReference objects. The returned * list contains services that * were registered under the specified class and match the specified filter * expression. * *

* The list is valid at the time of the call to this method. However since * the Micro Services framework is a very dynamic environment, services can be modified or * unregistered at any time. * *

* The specified filter expression is used to select the * registered services whose service properties contain keys and values * which satisfy the filter expression. See {@link LDAPFilter} for a description * of the filter syntax. If the specified filter is * empty, all registered services are considered to match the * filter. If the specified filter expression cannot be parsed, * an std::invalid_argument will be thrown with a human readable * message where the filter became unparsable. * *

* The result is a list of ServiceReference objects for all * services that meet all of the following conditions: *

* * @param clazz The class name with which the service was registered or * an empty string for all services. * @param filter The filter expression or empty for all * services. * @return A list of ServiceReference objects or * an empty list if no services are registered which satisfy the * search. * @throws std::invalid_argument If the specified filter * contains an invalid filter expression that cannot be parsed. * @throws std::logic_error If this ModuleContext is no longer valid. */ std::list GetServiceReferences(const std::string& clazz, const std::string& filter = std::string()); /** * Returns a list of ServiceReference objects. The returned * list contains services that * were registered under the interface id of the template argument S * and match the specified filter expression. * *

* This method is identical to GetServiceReferences(const std::tring&, const std::string&) except that * the class name for the service object is automatically deduced from the template argument. * * @tparam S The type under which the requested service objects must have been registered. * @param filter The filter expression or empty for all * services. * @return A list of ServiceReference objects or * an empty list if no services are registered which satisfy the * search. * @throws std::invalid_argument If the specified filter * contains an invalid filter expression that cannot be parsed. * @throws std::logic_error If this ModuleContext is no longer valid. * @see GetServiceReferences(const std::string&, const std::string&) */ template std::list GetServiceReferences(const std::string& filter = std::string()) { const char* clazz = mitk_service_interface_iid(); if (clazz == 0) throw ServiceException("The service interface class has no MITK_DECLARE_SERVICE_INTERFACE macro"); return GetServiceReferences(std::string(clazz), filter); } /** * Returns a ServiceReference object for a service that * implements and was registered under the specified class. * *

* The returned ServiceReference object is valid at the time of * the call to this method. However as the Micro Services framework is a very dynamic * environment, services can be modified or unregistered at any time. * *

* This method is the same as calling * {@link ModuleContext::GetServiceReferences(const std::string&, const std::string&)} with an * empty filter expression. It is provided as a convenience for * when the caller is interested in any service that implements the * specified class. *

* If multiple such services exist, the service with the highest ranking (as * specified in its {@link ServiceConstants::SERVICE_RANKING} property) is returned. *

* If there is a tie in ranking, the service with the lowest service ID (as * specified in its {@link ServiceConstants::SERVICE_ID} property); that is, the * service that was registered first is returned. * * @param clazz The class name with which the service was registered. * @return A ServiceReference object, or an invalid ServiceReference if * no services are registered which implement the named class. * @throws std::logic_error If this ModuleContext is no longer valid. * @throws ServiceException If no service was registered under the given class name. * @see #GetServiceReferences(const std::string&, const std::string&) */ ServiceReference GetServiceReference(const std::string& clazz); /** * Returns a ServiceReference object for a service that * implements and was registered under the specified template class argument. * *

* This method is identical to GetServiceReference(const std::string&) except that * the class name for the service object is automatically deduced from the template argument. * * @tparam S The type under which the requested service must have been registered. * @return A ServiceReference object, or an invalid ServiceReference if * no services are registered which implement the type S. * @throws std::logic_error If this ModuleContext is no longer valid. * @throws ServiceException It no service was registered under the given class name. * @see #GetServiceReference(const std::string&) * @see #GetServiceReferences(const std::string&) */ template ServiceReference GetServiceReference() { const char* clazz = mitk_service_interface_iid(); if (clazz == 0) throw ServiceException("The service interface class has no MITK_DECLARE_SERVICE_INTERFACE macro"); return GetServiceReference(std::string(clazz)); } /** * Returns the service object referenced by the specified * ServiceReference object. *

* A module's use of a service is tracked by the module's use count of that * service. Each time a service's service object is returned by * {@link #GetService(const ServiceReference&)} the context module's use count for * that service is incremented by one. Each time the service is released by * {@link #UngetService(const ServiceReference&)} the context module's use count * for that service is decremented by one. *

* When a module's use count for a service drops to zero, the module should * no longer use that service. * *

* This method will always return 0 when the service * associated with this reference has been unregistered. * *

* The following steps are taken to get the service object: *

    *
  1. If the service has been unregistered, 0 is returned. *
  2. The context module's use count for this service is incremented by * one. *
  3. If the context module's use count for the service is currently one * and the service was registered with an object implementing the * ServiceFactory interface, the * {@link ServiceFactory::GetService} method is * called to create a service object for the context module. This service * object is cached by the framework. While the context module's use count * for the service is greater than zero, subsequent calls to get the * services's service object for the context module will return the cached * service object.
    * If the ServiceFactory object throws an * exception, 0 is returned and a warning is logged. *
  4. The service object for the service is returned. *
* * @param reference A reference to the service. * @return A service object for the service associated with * reference or 0 if the service is not * registered or the ServiceFactory threw * an exception. * @throws std::logic_error If this ModuleContext is no * longer valid. * @throws std::invalid_argument If the specified * ServiceReference is invalid (default constructed). * @see #UngetService(const ServiceReference&) * @see ServiceFactory */ itk::LightObject* GetService(const ServiceReference& reference); /** * Returns the service object referenced by the specified * ServiceReference object. *

* This is a convenience method which is identical to itk::LightObject* GetService(const ServiceReference&) * except that it casts the service object to the supplied template argument type * * @tparam S The type the service object will be cast to. * @return A service object for the service associated with * reference or 0 if the service is not * registered, the ServiceFactory threw * an exception or the service could not be casted to the desired type. * @throws std::logic_error If this ModuleContext is no * longer valid. * @throws std::invalid_argument If the specified * ServiceReference is invalid (default constructed). * @see #GetService(const ServiceReference&) * @see #UngetService(const ServiceReference&) * @see ServiceFactory */ template S* GetService(const ServiceReference& reference) { return dynamic_cast(GetService(reference)); } /** * Releases the service object referenced by the specified * ServiceReference object. If the context module's use count * for the service is zero, this method returns false. * Otherwise, the context modules's use count for the service is decremented * by one. * *

* The service's service object should no longer be used and all references * to it should be destroyed when a module's use count for the service drops * to zero. * *

* The following steps are taken to unget the service object: *

    *
  1. If the context module's use count for the service is zero or the * service has been unregistered, false is returned. *
  2. The context module's use count for this service is decremented by * one. *
  3. If the context module's use count for the service is currently zero * and the service was registered with a ServiceFactory object, * the ServiceFactory#UngetService * method is called to release the service object for the context module. *
  4. true is returned. *
* * @param reference A reference to the service to be released. * @return false if the context module's use count for the * service is zero or if the service has been unregistered; * true otherwise. * @throws std::logic_error If this ModuleContext is no * longer valid. * @see #GetService * @see ServiceFactory */ bool UngetService(const ServiceReference& reference); /** * Adds the specified callback with the * specified filter to the context modules's list of listeners. * See LDAPFilter for a description of the filter syntax. Listeners * are notified when a service has a lifecycle state change. * *

* You must take care to remove registered listeners befor the receiver * object is destroyed. However, the Micro Services framework takes care * of removing all listeners registered by this context module's classes * after the module is unloaded. * *

* If the context module's list of listeners already contains a pair (r,c) * of receiver and callback such that * (r == receiver && c == callback), then this * method replaces that callback's filter (which may be empty) * with the specified one (which may be empty). * *

* The callback is called if the filter criteria is met. To filter based * upon the class of the service, the filter should reference the * {@link ServiceConstants#OBJECTCLASS} property. If filter is * empty, all services are considered to match the filter. * *

* When using a filter, it is possible that the * ServiceEvents for the complete lifecycle of a service * will not be delivered to the callback. For example, if the * filter only matches when the property x has * the value 1, the callback will not be called if the * service is registered with the property x not set to the * value 1. Subsequently, when the service is modified * setting property x to the value 1, the * filter will match and the callback will be called with a * ServiceEvent of type MODIFIED. Thus, the * callback will not be called with a ServiceEvent of type * REGISTERED. * * @tparam The type of the receiver (containing the member function to be called) * @param receiver The object to connect to. * @param callback The member function pointer to call. * @param filter The filter criteria. * @throws std::invalid_argument If filter contains an * invalid filter string that cannot be parsed. * @throws std::logic_error If this ModuleContext is no * longer valid. * @see ServiceEvent * @see RemoveServiceListener() */ template void AddServiceListener(R* receiver, void(R::*callback)(const ServiceEvent&), const std::string& filter = std::string()) { MessageDelegate1 delegate(receiver, callback); AddServiceListener(delegate, filter); } /** * Removes the specified callback from the context module's * list of listeners. * *

* If the (receiver,callback) pair is not contained in this * context module's list of listeners, this method does nothing. * * @tparam The type of the receiver (containing the member function to be removed) * @param receiver The object from which to disconnect. * @param callback The member function pointer to remove. * @throws std::logic_error If this ModuleContext is no * longer valid. * @see AddServiceListener() */ template void RemoveServiceListener(R* receiver, void(R::*callback)(const ServiceEvent&)) { MessageDelegate1 delegate(receiver, callback); RemoveServiceListener(delegate); } /** * Adds the specified callback to the context modules's list * of listeners. Listeners are notified when a module has a lifecycle * state change. * *

* If the context module's list of listeners already contains a pair (r,c) * of receiver and callback such that * (r == receiver && c == callback), then this method does nothing. * * @tparam The type of the receiver (containing the member function to be called) * @param receiver The object to connect to. * @param callback The member function pointer to call. * @throws std::logic_error If this ModuleContext is no * longer valid. * @see ModuleEvent */ template void AddModuleListener(R* receiver, void(R::*callback)(const ModuleEvent&)) { MessageDelegate1 delegate(receiver, callback); AddModuleListener(delegate); } /** * Removes the specified callback from the context module's * list of listeners. * *

* If the (receiver,callback) pair is not contained in this * context module's list of listeners, this method does nothing. * * @tparam The type of the receiver (containing the member function to be removed) * @param receiver The object from which to disconnect. * @param callback The member function pointer to remove. * @throws std::logic_error If this ModuleContext is no * longer valid. * @see AddModuleListener() */ template void RemoveModuleListener(R* receiver, void(R::*callback)(const ModuleEvent&)) { MessageDelegate1 delegate(receiver, callback); RemoveModuleListener(delegate); } private: friend class Module; friend class ModulePrivate; ModuleContext(ModulePrivate* module); void AddServiceListener(const ServiceListenerDelegate& delegate, const std::string& filter); void RemoveServiceListener(const ServiceListenerDelegate& delegate); void AddModuleListener(const ModuleListenerDelegate& delegate); void RemoveModuleListener(const ModuleListenerDelegate& delegate); ModuleContextPrivate * const d; }; } #ifdef MITK_HAS_UNORDERED_MAP_H namespace std { #elif defined(__GNUC__) namespace __gnu_cxx { #else namespace itk { #endif template<> struct hash { std::size_t operator()(const mitk::ModuleContext* context) const { #ifdef MITK_HAS_HASH_SIZE_T return hash()(reinterpret_cast(context)); #else std::size_t key = reinterpret_cast(context); return std::size_t(key & (~0U)); #endif } }; } #endif /* MITKMODULECONTEXT_H_ */ diff --git a/Core/Code/Service/mitkServiceListeners.cpp b/Core/Code/Service/mitkServiceListeners.cpp index 0aa6c24523..39ea0974a9 100644 --- a/Core/Code/Service/mitkServiceListeners.cpp +++ b/Core/Code/Service/mitkServiceListeners.cpp @@ -1,268 +1,270 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkServiceListeners_p.h" #include "mitkServiceReferencePrivate.h" #include "mitkModule.h" +#include + namespace mitk { const int ServiceListeners::OBJECTCLASS_IX = 0; const int ServiceListeners::SERVICE_ID_IX = 1; ServiceListeners::ServiceListeners() { hashedServiceKeys.push_back(ServiceConstants::OBJECTCLASS()); hashedServiceKeys.push_back(ServiceConstants::SERVICE_ID()); } void ServiceListeners::AddServiceListener(ModuleContext* mc, const ServiceListenerDelegate& listener, const std::string& filter) { MutexLocker lock(mutex); ServiceListenerEntry sle(mc->GetModule(), listener, filter); if (serviceSet.find(sle) != serviceSet.end()) { RemoveServiceListener_unlocked(sle); } serviceSet.insert(sle); CheckSimple(sle); } void ServiceListeners::RemoveServiceListener(ModuleContext* mc, const ServiceListenerDelegate& listener) { ServiceListenerEntry entryToRemove(mc->GetModule(), listener); MutexLocker lock(mutex); RemoveServiceListener_unlocked(entryToRemove); } void ServiceListeners::RemoveServiceListener_unlocked(const ServiceListenerEntry& entryToRemove) { for (ServiceListenerEntries::iterator it = serviceSet.begin(); it != serviceSet.end(); ++it) { if (it->operator ==(entryToRemove)) { it->SetRemoved(true); RemoveFromCache(*it); serviceSet.erase(it); break; } } } void ServiceListeners::AddModuleListener(ModuleContext* mc, const ModuleListenerDelegate& listener) { MutexLocker lock(moduleListenerMapMutex); moduleListenerMap[mc] += listener; } void ServiceListeners::RemoveModuleListener(ModuleContext* mc, const ModuleListenerDelegate& listener) { MutexLocker lock(moduleListenerMapMutex); moduleListenerMap[mc] -= listener; } void ServiceListeners::RemoveAllListeners(ModuleContext* mc) { { MutexLocker lock(mutex); for (ServiceListenerEntries::iterator it = serviceSet.begin(); it != serviceSet.end(); ) { if (it->GetModule() == mc->GetModule()) { RemoveFromCache(*it); serviceSet.erase(it++); } else { ++it; } } } { MutexLocker lock(moduleListenerMapMutex); moduleListenerMap.erase(mc); } } void ServiceListeners::ServiceChanged(const ServiceListenerEntries& receivers, const ServiceEvent& evt) { ServiceListenerEntries matchBefore; ServiceChanged(receivers, evt, matchBefore); } void ServiceListeners::ServiceChanged(const ServiceListenerEntries& receivers, const ServiceEvent& evt, ServiceListenerEntries& matchBefore) { ServiceReference sr = evt.GetServiceReference(); int n = 0; for (ServiceListenerEntries::const_iterator l = receivers.begin(); l != receivers.end(); ++l) { if (!matchBefore.empty()) { matchBefore.erase(*l); } if (!l->IsRemoved()) { try { ++n; l->CallDelegate(evt); } catch (...) { MITK_ERROR << "Service listener in " << l->GetModule()->GetName() << " threw an exception!"; } } } MITK_INFO << "Notified " << n << " listeners"; } void ServiceListeners::GetMatchingServiceListeners(const ServiceReference& sr, ServiceListenerEntries& set) { MutexLocker lock(mutex); // Check complicated or empty listener filters int n = 0; for (std::list::const_iterator sse = complicatedListeners.begin(); sse != complicatedListeners.end(); ++sse) { ++n; if (sse->GetLDAPExpr().IsNull() || sse->GetLDAPExpr().Evaluate(sr.d->GetProperties(), false)) { set.insert(*sse); } } MITK_INFO << "Added " << set.size() << " out of " << n << " listeners with complicated filters"; // Check the cache const std::list c(any_cast > (sr.GetProperty(ServiceConstants::OBJECTCLASS()))); for (std::list::const_iterator objClass = c.begin(); objClass != c.end(); ++objClass) { AddToSet(set, OBJECTCLASS_IX, *objClass); } long service_id = any_cast(sr.GetProperty(ServiceConstants::SERVICE_ID())); std::stringstream ss; ss << service_id; AddToSet(set, SERVICE_ID_IX, ss.str()); } void ServiceListeners::ModuleChanged(const ModuleEvent& evt) { MutexLocker lock(moduleListenerMapMutex); for(ModuleListenerMap::iterator i = moduleListenerMap.begin(); i != moduleListenerMap.end(); ++i) { i->second.Send(evt); } } void ServiceListeners::RemoveFromCache(const ServiceListenerEntry& sle) { if (!sle.GetLocalCache().empty()) { for (std::size_t i = 0; i < hashedServiceKeys.size(); ++i) { CacheType& keymap = cache[i]; std::vector& l = sle.GetLocalCache()[i]; for (std::vector::const_iterator it = l.begin(); it != l.end(); ++it) { std::list& sles = keymap[*it]; sles.remove(sle); if (sles.empty()) { keymap.erase(*it); } } } } else { complicatedListeners.remove(sle); } } void ServiceListeners::CheckSimple(const ServiceListenerEntry& sle) { if (sle.GetLDAPExpr().IsNull()) { complicatedListeners.push_back(sle); } else { LDAPExpr::LocalCache local_cache; if (sle.GetLDAPExpr().IsSimple(hashedServiceKeys, local_cache, false)) { sle.GetLocalCache() = local_cache; for (std::size_t i = 0; i < hashedServiceKeys.size(); ++i) { for (std::vector::const_iterator it = local_cache[i].begin(); it != local_cache[i].end(); ++it) { std::list& sles = cache[i][*it]; sles.push_back(sle); } } } else { MITK_INFO << "Too complicated filter: " << sle.GetFilter(); complicatedListeners.push_back(sle); } } } void ServiceListeners::AddToSet(ServiceListenerEntries& set, int cache_ix, const std::string& val) { std::list& l = cache[cache_ix][val]; if (!l.empty()) { MITK_INFO << hashedServiceKeys[cache_ix] << " matches " << l.size(); for (std::list::const_iterator entry = l.begin(); entry != l.end(); ++entry) { set.insert(*entry); } } else { MITK_INFO << hashedServiceKeys[cache_ix] << " matches none"; } } } diff --git a/Core/Code/Service/mitkServiceProperties.h b/Core/Code/Service/mitkServiceProperties.h index f68ff790eb..fed7311c51 100644 --- a/Core/Code/Service/mitkServiceProperties.h +++ b/Core/Code/Service/mitkServiceProperties.h @@ -1,191 +1,191 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITK_SERVICE_PROPERTIES_H #define MITK_SERVICE_PROPERTIES_H #include #include #ifdef MITK_HAS_UNORDERED_MAP_H #include #else #include "mitkItkHashMap.h" #endif -#include +#include #include "mitkAny.h" namespace mitk { struct ci_char_traits : public std::char_traits // just inherit all the other functions // that we don't need to override { static bool eq(char c1, char c2) { return std::toupper(c1) == std::toupper(c2); } static bool ne(char c1, char c2) { return std::toupper(c1) != std::toupper(c2); } static bool lt(char c1, char c2) { return std::toupper(c1) < std::toupper(c2); } static bool gt(char c1, char c2) { return std::toupper(c1) > std::toupper(c2); } static int compare(const char* s1, const char* s2, std::size_t n) { while (n-- > 0) { if (lt(*s1, *s2)) return -1; if (gt(*s1, *s2)) return 1; ++s1; ++s2; } return 0; } static const char* find(const char* s, int n, char a) { while (n-- > 0 && std::toupper(*s) != std::toupper(a)) { ++s; } return s; } }; class ci_string : public std::basic_string { private: typedef std::basic_string Super; public: inline ci_string() : Super() {} inline ci_string(const ci_string& cistr) : Super(cistr) {} inline ci_string(const ci_string& cistr, size_t pos, size_t n) : Super(cistr, pos, n) {} inline ci_string(const char* s, size_t n) : Super(s, n) {} inline ci_string(const char* s) : Super(s) {} inline ci_string(size_t n, char c) : Super(n, c) {} inline ci_string(const std::string& str) : Super(str.begin(), str.end()) {} template ci_string(InputIterator begin, InputIterator end) : Super(begin, end) {} inline operator std::string () const { return std::string(begin(), end()); } }; struct MITK_CORE_EXPORT hash_ci_string { std::size_t operator()(const ci_string& s) const; }; /** * \ingroup MicroServices * * A hash table based map class with case-insensitive keys. This class * uses ci_string as key type and Any as values. Due * to the conversion capabilities of ci_string, std::string objects * can be used transparantly to insert or retrieve key-value pairs. * *

* Note that the case of the keys will be preserved. */ #ifdef MITK_HAS_UNORDERED_MAP_H typedef std::unordered_map ServiceProperties; #else typedef itk::hash_map ServiceProperties; #endif /** * \ingroup MicroServices */ namespace ServiceConstants { /** * Service property identifying all of the class names under which a service * was registered in the framework. The value of this property must be of * type std::list<std::string>. * *

* This property is set by the framework when a service is registered. */ MITK_CORE_EXPORT const std::string& OBJECTCLASS(); // = "objectclass" /** * Service property identifying a service's registration number. The value * of this property must be of type long int. * *

* The value of this property is assigned by the framework when a service is * registered. The framework assigns a unique value that is larger than all * previously assigned values since the framework was started. These values * are NOT persistent across restarts of the framework. */ MITK_CORE_EXPORT const std::string& SERVICE_ID(); // = "service.id" /** * Service property identifying a service's ranking number. * *

* This property may be supplied in the * ServiceProperties object passed to the * ModuleContext::RegisterService method. The value of this * property must be of type int. * *

* The service ranking is used by the framework to determine the natural * order of services, see ServiceReference::operator<(const ServiceReference&), * and the default service to be returned from a call to the * {@link ModuleContext::GetServiceReference} method. * *

* The default ranking is zero (0). A service with a ranking of * std::numeric_limits::max() is very likely to be returned as the * default service, whereas a service with a ranking of * std::numeric_limits::min() is very unlikely to be returned. * *

* If the supplied property value is not of type int, it is * deemed to have a ranking value of zero. */ MITK_CORE_EXPORT const std::string& SERVICE_RANKING(); // = "service.ranking" } } #endif // MITK_SERVICE_PROPERTIES_H diff --git a/Core/Code/Service/mitkServiceReference.h b/Core/Code/Service/mitkServiceReference.h index 2bb504c8db..2229bb33d3 100644 --- a/Core/Code/Service/mitkServiceReference.h +++ b/Core/Code/Service/mitkServiceReference.h @@ -1,239 +1,239 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKSERVICEREFERENCE_H #define MITKSERVICEREFERENCE_H -#include +#include #include #ifdef MITK_HAS_UNORDERED_MAP_H namespace std { #elif defined(__GNUC__) namespace __gnu_cxx { #else namespace itk { #endif template class hash; } namespace mitk { class Module; class ServiceRegistrationPrivate; class ServiceReferencePrivate; /** * \ingroup MicroServices * * A reference to a service. * *

* The framework returns ServiceReference objects from the * ModuleContext::GetServiceReference and * ModuleContext::GetServiceReferences methods. *

* A ServiceReference object may be shared between modules and * can be used to examine the properties of the service and to get the service * object. *

* Every service registered in the framework has a unique * ServiceRegistration object and may have multiple, distinct * ServiceReference objects referring to it. * ServiceReference objects associated with a * ServiceRegistration are considered equal * (more specifically, their operator==() * method will return true when compared). *

* If the same service object is registered multiple times, * ServiceReference objects associated with different * ServiceRegistration objects are not equal. * * @see ModuleContext::GetServiceReference * @see ModuleContext::GetServiceReferences * @see ModuleContext::GetService * @remarks This class is thread safe. */ class MITK_CORE_EXPORT ServiceReference { public: /** * Creates an invalid ServiceReference object. You can use * this object in boolean expressions and it will evaluate to * false. */ ServiceReference(); ServiceReference(const ServiceReference& ref); /** * Converts this ServiceReference instance into a boolean * expression. If this instance was default constructed or * the service it references has been unregistered, the conversion * returns false, otherwise it returns true. */ operator bool() const; /** * Releases any resources held or locked by this * ServiceReference and renders it invalid. */ ServiceReference& operator=(int null); ~ServiceReference(); /** * Returns the property value to which the specified property key is mapped * in the properties ServiceProperties object of the service * referenced by this ServiceReference object. * *

* Property keys are case-insensitive. * *

* This method continues to return property values after the service has * been unregistered. This is so references to unregistered services can * still be interrogated. * * @param key The property key. * @return The property value to which the key is mapped; an invalid Any * if there is no property named after the key. */ Any GetProperty(const std::string& key) const; /** * Returns a list of the keys in the ServiceProperties * object of the service referenced by this ServiceReference * object. * *

* This method will continue to return the keys after the service has been * unregistered. This is so references to unregistered services can * still be interrogated. * * @param keys A vector being filled with the property keys. */ void GetPropertyKeys(std::vector& keys) const; /** * Returns the module that registered the service referenced by this * ServiceReference object. * *

* This method must return 0 when the service has been * unregistered. This can be used to determine if the service has been * unregistered. * * @return The module that registered the service referenced by this * ServiceReference object; 0 if that * service has already been unregistered. * @see ModuleContext::RegisterService(const std::vector&, itk::LightObject*, const ServiceProperties&) */ Module* GetModule() const; /** * Returns the modules that are using the service referenced by this * ServiceReference object. Specifically, this method returns * the modules whose usage count for that service is greater than zero. * * @param modules A list of modules whose usage count for the service referenced * by this ServiceReference object is greater than * zero. */ void GetUsingModules(std::vector& modules) const; /** * Compares this ServiceReference with the specified * ServiceReference for order. * *

* If this ServiceReference and the specified * ServiceReference have the same {@link ServiceProperties::SERVICE_ID * service id} they are equal. This ServiceReference is less * than the specified ServiceReference if it has a lower * {@link ServiceProperties::SERVICE_RANKING service ranking} and greater if it has a * higher service ranking. Otherwise, if this ServiceReference * and the specified ServiceReference have the same * {@link ServiceProperties::SERVICE_RANKING service ranking}, this * ServiceReference is less than the specified * ServiceReference if it has a higher * {@link ServiceProperties::SERVICE_ID service id} and greater if it has a lower * service id. * * @param reference The ServiceReference to be compared. * @return Returns a false or true if this * ServiceReference is less than or greater * than the specified ServiceReference. */ bool operator<(const ServiceReference& reference) const; bool operator==(const ServiceReference& reference) const; ServiceReference& operator=(const ServiceReference& reference); protected: friend class ModulePrivate; friend class ModuleContext; friend class ServiceFilter; friend class ServiceRegistrationPrivate; friend class ServiceListeners; friend class LDAPFilter; template friend class ServiceTracker; template friend class ServiceTrackerPrivate; template friend class ModuleAbstractTracked; #ifdef MITK_HAS_UNORDERED_MAP_H friend class std::hash; #elif defined(__GNUC__) friend class __gnu_cxx::hash; #else friend struct itk::hash; #endif ServiceReference(ServiceRegistrationPrivate* reg); ServiceReferencePrivate* d; }; } MITK_CORE_EXPORT std::ostream& operator<<(std::ostream& os, const mitk::ServiceReference& serviceRef); #ifdef MITK_HAS_UNORDERED_MAP_H namespace std { #elif defined(__GNUC__) namespace __gnu_cxx { #else namespace itk { #endif template<> struct MITK_CORE_EXPORT hash { std::size_t operator()(const mitk::ServiceReference& sr) const; }; } #endif // MITKSERVICEREFERENCE_H diff --git a/Core/Code/Service/mitkServiceReferencePrivate.cpp b/Core/Code/Service/mitkServiceReferencePrivate.cpp index c778e50734..fc964ab2cc 100644 --- a/Core/Code/Service/mitkServiceReferencePrivate.cpp +++ b/Core/Code/Service/mitkServiceReferencePrivate.cpp @@ -1,157 +1,159 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkServiceReferencePrivate.h" #include "mitkServiceFactory.h" #include "mitkServiceException.h" #include "mitkServiceRegistry_p.h" #include "mitkServiceRegistrationPrivate.h" #include "mitkModule.h" #include "mitkModulePrivate.h" #include "mitkCoreModuleContext_p.h" +#include + #include namespace mitk { typedef ServiceRegistrationPrivate::MutexLocker MutexLocker; ServiceReferencePrivate::ServiceReferencePrivate(ServiceRegistrationPrivate* reg) : ref(1), registration(reg) { } itk::LightObject* ServiceReferencePrivate::GetService(Module* module) { itk::LightObject* s = 0; { MutexLocker lock(registration->propsLock); if (registration->available) { int count = registration->dependents[module]; if (count == 0) { const std::list& classes = ref_any_cast >(registration->properties[ServiceConstants::OBJECTCLASS()]); registration->dependents[module] = 1; if (ServiceFactory* serviceFactory = dynamic_cast(registration->GetService())) { try { s = serviceFactory->GetService(module, ServiceRegistration(registration)); } catch (...) { MITK_WARN << "mitk::ServiceFactory threw an exception"; return 0; } if (s == 0) { MITK_WARN << "mitk::ServiceFactory produced null"; return 0; } for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { if (!registration->module->coreCtx->services.CheckServiceClass(s, *i)) { MITK_WARN << "mitk::ServiceFactory produced an object " "that did not implement: " << (*i); return 0; } } registration->serviceInstances.insert(std::make_pair(module, s)); } else { s = registration->GetService(); } } else { registration->dependents.insert(std::make_pair(module, count + 1)); if (dynamic_cast(registration->GetService())) { s = registration->serviceInstances[module]; } else { s = registration->GetService(); } } } } return s; } bool ServiceReferencePrivate::UngetService(Module* module, bool checkRefCounter) { MutexLocker lock(registration->propsLock); bool hadReferences = false; bool removeService = false; int count= registration->dependents[module]; if (count > 0) { hadReferences = true; } if(checkRefCounter) { if (count > 1) { registration->dependents[module] = count - 1; } else if(count == 1) { removeService = true; } } else { removeService = true; } if (removeService) { itk::LightObject* sfi = registration->serviceInstances[module]; registration->serviceInstances.erase(module); if (sfi != 0) { try { dynamic_cast( registration->GetService())->UngetService(module, ServiceRegistration(registration), sfi); } catch (const std::exception& /*e*/) { MITK_WARN << "mitk::ServiceFactory threw an exception"; } } registration->dependents.erase(module); } return hadReferences; } ServiceProperties ServiceReferencePrivate::GetProperties() const { return registration->properties; } } diff --git a/Core/Code/Service/mitkServiceRegistration.cpp b/Core/Code/Service/mitkServiceRegistration.cpp index 7974483638..60633cbf3b 100644 --- a/Core/Code/Service/mitkServiceRegistration.cpp +++ b/Core/Code/Service/mitkServiceRegistration.cpp @@ -1,220 +1,222 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkServiceRegistration.h" #include "mitkServiceRegistrationPrivate.h" #include "mitkServiceListenerEntry_p.h" #include "mitkServiceRegistry_p.h" #include "mitkServiceFactory.h" #include "mitkModulePrivate.h" #include "mitkCoreModuleContext_p.h" +#include + #include namespace mitk { typedef ServiceRegistrationPrivate::MutexLocker MutexLocker; ServiceRegistration::ServiceRegistration() : d(0) { } ServiceRegistration::ServiceRegistration(const ServiceRegistration& reg) : d(reg.d) { d->ref.Ref(); } ServiceRegistration::ServiceRegistration(ServiceRegistrationPrivate* registrationPrivate) : d(registrationPrivate) { d->ref.Ref(); } ServiceRegistration::ServiceRegistration(ModulePrivate* module, itk::LightObject* service, const ServiceProperties& props) : d(new ServiceRegistrationPrivate(module, service, props)) { } ServiceRegistration::operator bool() const { return d != 0; } ServiceRegistration& ServiceRegistration::operator=(int null) { if (null == 0) { if (d && !d->ref.Deref()) { delete d; } d = 0; } return *this; } ServiceRegistration::~ServiceRegistration() { if (d && !d->ref.Deref()) delete d; } ServiceReference ServiceRegistration::GetReference() const { if (!d) throw std::logic_error("ServiceRegistration object invalid"); if (!d->available) throw std::logic_error("Service is unregistered"); return d->reference; } void ServiceRegistration::SetProperties(const ServiceProperties& props) { if (!d) throw std::logic_error("ServiceRegistration object invalid"); MutexLocker lock(d->eventLock); ServiceListeners::ServiceListenerEntries before; // TBD, optimize the locking of services { //MutexLocker lock2(d->module->coreCtx->globalFwLock); MutexLocker lock3(d->propsLock); if (d->available) { // NYI! Optimize the MODIFIED_ENDMATCH code int old_rank = any_cast(d->properties[ServiceConstants::SERVICE_RANKING()]); d->module->coreCtx->listeners.GetMatchingServiceListeners(d->reference, before); const std::list& classes = ref_any_cast >(d->properties[ServiceConstants::OBJECTCLASS()]); long int sid = any_cast(d->properties[ServiceConstants::SERVICE_ID()]); d->properties = ServiceRegistry::CreateServiceProperties(props, classes, sid); int new_rank = any_cast(d->properties[ServiceConstants::SERVICE_RANKING()]); if (old_rank != new_rank) { d->module->coreCtx->services.UpdateServiceRegistrationOrder(*this, classes); } } else { throw std::logic_error("Service is unregistered"); } } ServiceListeners::ServiceListenerEntries matchingListeners; d->module->coreCtx->listeners.GetMatchingServiceListeners(d->reference, matchingListeners); d->module->coreCtx->listeners.ServiceChanged(matchingListeners, ServiceEvent(ServiceEvent::MODIFIED, d->reference), before); d->module->coreCtx->listeners.ServiceChanged(before, ServiceEvent(ServiceEvent::MODIFIED_ENDMATCH, d->reference)); } void ServiceRegistration::Unregister() { if (!d) throw std::logic_error("ServiceRegistration object invalid"); if (d->unregistering) return; // Silently ignore redundant unregistration. { MutexLocker lock(d->eventLock); if (d->unregistering) return; d->unregistering = true; if (d->available) { if (d->module) { d->module->coreCtx->services.RemoveServiceRegistration(*this); } } else { throw std::logic_error("Service is unregistered"); } } if (d->module) { ServiceListeners::ServiceListenerEntries listeners; d->module->coreCtx->listeners.GetMatchingServiceListeners(d->reference, listeners); d->module->coreCtx->listeners.ServiceChanged( listeners, ServiceEvent(ServiceEvent::UNREGISTERING, d->reference)); } { MutexLocker lock(d->eventLock); { MutexLocker lock2(d->propsLock); d->available = false; if (d->module) { ServiceRegistrationPrivate::ModuleToServicesMap::const_iterator end = d->serviceInstances.end(); for (ServiceRegistrationPrivate::ModuleToServicesMap::const_iterator i = d->serviceInstances.begin(); i != end; ++i) { itk::LightObject* obj = i->second; try { // NYI, don't call inside lock dynamic_cast(d->service)->UngetService(i->first, *this, obj); } catch (const std::exception& /*ue*/) { MITK_WARN << "mitk::ServiceFactory UngetService implementation threw an exception"; } } } d->module = 0; d->dependents.clear(); d->service = 0; d->serviceInstances.clear();; d->unregistering = false; } } } bool ServiceRegistration::operator<(const ServiceRegistration& o) const { if (!d) return true; return d->reference <(o.d->reference); } bool ServiceRegistration::operator==(const ServiceRegistration& registration) const { return d == registration.d; } ServiceRegistration& ServiceRegistration::operator=(const ServiceRegistration& registration) { ServiceRegistrationPrivate* curr_d = d; d = registration.d; d->ref.Ref(); if (curr_d && !curr_d->ref.Deref()) delete curr_d; return *this; } } diff --git a/Core/Code/Service/mitkServiceRegistration.h b/Core/Code/Service/mitkServiceRegistration.h index e41630bbb2..f29d9d5055 100644 --- a/Core/Code/Service/mitkServiceRegistration.h +++ b/Core/Code/Service/mitkServiceRegistration.h @@ -1,171 +1,173 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKSERVICEREGISTRATION_H #define MITKSERVICEREGISTRATION_H #include "mitkServiceProperties.h" #include "mitkServiceReference.h" +namespace itk { class LightObject; } + namespace mitk { class ModulePrivate; /** * \ingroup MicroServices * * A registered service. * *

* The framework returns a ServiceRegistration object when a * ModuleContext#RegisterService() method invocation is successful. * The ServiceRegistration object is for the private use of the * registering module and should not be shared with other modules. *

* The ServiceRegistration object may be used to update the * properties of the service or to unregister the service. * * @see ModuleContext#RegisterService() * @remarks This class is thread safe. */ class MITK_CORE_EXPORT ServiceRegistration { public: /** * Creates an invalid ServiceRegistration object. You can use * this object in boolean expressions and it will evaluate to * false. */ ServiceRegistration(); ServiceRegistration(const ServiceRegistration& reg); operator bool() const; /** * Releases any resources held or locked by this * ServiceRegistration and renders it invalid. */ ServiceRegistration& operator=(int null); ~ServiceRegistration(); /** * Returns a ServiceReference object for a service being * registered. *

* The ServiceReference object may be shared with other * modules. * * @throws std::logic_error If this * ServiceRegistration object has already been * unregistered or if it is invalid. * @return ServiceReference object. */ ServiceReference GetReference() const; /** * Updates the properties associated with a service. * *

* The {@link ServiceProperties#OBJECTCLASS} and {@link ServiceProperties#SERVICE_ID} keys * cannot be modified by this method. These values are set by the framework * when the service is registered in the environment. * *

* The following steps are taken to modify service properties: *

    *
  1. The service's properties are replaced with the provided properties. *
  2. A service event of type {@link ServiceEvent#MODIFIED} is fired. *
* * @param properties The properties for this service. See {@link ServiceProperties} * for a list of standard service property keys. Changes should not * be made to this object after calling this method. To update the * service's properties this method should be called again. * * @throws std::logic_error If this ServiceRegistration * object has already been unregistered or if it is invalid. * @throws std::invalid_argument If properties contains * case variants of the same key name. */ void SetProperties(const ServiceProperties& properties); /** * Unregisters a service. Remove a ServiceRegistration object * from the framework service registry. All ServiceRegistration * objects associated with this ServiceRegistration object * can no longer be used to interact with the service once unregistration is * complete. * *

* The following steps are taken to unregister a service: *

    *
  1. The service is removed from the framework service registry so that * it can no longer be obtained. *
  2. A service event of type {@link ServiceEvent#UNREGISTERING} is fired * so that modules using this service can release their use of the service. * Once delivery of the service event is complete, the * ServiceRegistration objects for the service may no longer be * used to get a service object for the service. *
  3. For each module whose use count for this service is greater than * zero:
    * The module's use count for this service is set to zero.
    * If the service was registered with a {@link ServiceFactory} object, the * ServiceFactory#UngetService method is called to release * the service object for the module. *
* * @throws std::logic_error If this * ServiceRegistration object has already been * unregistered or if it is invalid. * @see ModuleContext#UngetService * @see ServiceFactory#UngetService */ virtual void Unregister(); bool operator<(const ServiceRegistration& o) const; bool operator==(const ServiceRegistration& registration) const; ServiceRegistration& operator=(const ServiceRegistration& registration); protected: friend class ServiceRegistry; friend class ServiceReferencePrivate; friend struct HashServiceRegistration; ServiceRegistration(ServiceRegistrationPrivate* registrationPrivate); ServiceRegistration(ModulePrivate* module, itk::LightObject* service, const ServiceProperties& props); ServiceRegistrationPrivate* d; }; } inline std::ostream& operator<<(std::ostream& os, const mitk::ServiceRegistration& /*reg*/) { return os << "mitk::ServiceRegistration object"; } #endif // MITKSERVICEREGISTRATION_H diff --git a/Core/Code/Service/mitkServiceRegistry.cpp b/Core/Code/Service/mitkServiceRegistry.cpp index 3f6644f91f..b295497328 100644 --- a/Core/Code/Service/mitkServiceRegistry.cpp +++ b/Core/Code/Service/mitkServiceRegistry.cpp @@ -1,329 +1,331 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include "mitkServiceRegistry_p.h" #include "mitkServiceFactory.h" #include "mitkServiceRegistry_p.h" #include "mitkServiceRegistrationPrivate.h" #include "mitkModulePrivate.h" #include "mitkCoreModuleContext_p.h" +#include + #include "itkMutexLockHolder.h" namespace mitk { typedef itk::MutexLockHolder MutexLocker; std::size_t HashServiceRegistration::operator()(const ServiceRegistration& s) const { return reinterpret_cast(s.d); } struct ServiceRegistrationComparator { bool operator()(const ServiceRegistration& a, const ServiceRegistration& b) const { return a < b; } }; ServiceProperties ServiceRegistry::CreateServiceProperties(const ServiceProperties& in, const std::list& classes, long sid) { static long nextServiceID = 1; ServiceProperties props(in); if (!classes.empty()) { props.insert(std::make_pair(ServiceConstants::OBJECTCLASS(), classes)); } props.insert(std::make_pair(ServiceConstants::SERVICE_ID(), sid != -1 ? sid : nextServiceID++)); return props; } ServiceRegistry::ServiceRegistry(CoreModuleContext* coreCtx) : core(coreCtx) { } ServiceRegistry::~ServiceRegistry() { Clear(); } void ServiceRegistry::Clear() { services.clear(); serviceRegistrations.clear(); classServices.clear(); core = 0; } ServiceRegistration ServiceRegistry::RegisterService(ModulePrivate* module, const std::list& classes, itk::LightObject* service, const ServiceProperties& properties) { if (service == 0) { throw std::invalid_argument("Can't register 0 as a service"); } // Check if service implements claimed classes and that they exist. for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { if (i->empty()) { throw std::invalid_argument("Can't register as null class"); } if (!(dynamic_cast(service))) { if (!CheckServiceClass(service, *i)) { std::string msg; std::stringstream ss(msg); ss << "Service class " << service->GetNameOfClass() << " is not an instance of " << (*i) << ". Maybe you forgot to export the RTTI information for the interface."; throw std::invalid_argument(msg); } } } ServiceRegistration res(module, service, CreateServiceProperties(properties, classes)); { MutexLocker lock(mutex); services.insert(std::make_pair(res, classes)); serviceRegistrations.push_back(res); for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { std::list& s = classServices[*i]; std::list::iterator ip = std::lower_bound(s.begin(), s.end(), res, ServiceRegistrationComparator()); s.insert(ip, res); } } ServiceReference r = res.GetReference(); ServiceListeners::ServiceListenerEntries listeners; module->coreCtx->listeners.GetMatchingServiceListeners(r, listeners); module->coreCtx->listeners.ServiceChanged(listeners, ServiceEvent(ServiceEvent::REGISTERED, r)); return res; } void ServiceRegistry::UpdateServiceRegistrationOrder(const ServiceRegistration& sr, const std::list& classes) { MutexLocker lock(mutex); for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { std::list& s = classServices[*i]; std::remove(s.begin(), s.end(), sr); s.insert(std::lower_bound(s.begin(), s.end(), sr, ServiceRegistrationComparator()), sr); } } bool ServiceRegistry::CheckServiceClass(itk::LightObject* , const std::string& ) const { //return service->inherits(cls.toAscii()); // No possibility to check inheritance based on string literals. return true; } void ServiceRegistry::Get(const std::string& clazz, std::list& serviceRegs) const { MutexLocker lock(mutex); MapClassServices::const_iterator i = classServices.find(clazz); if (i != classServices.end()) { serviceRegs = i->second; } } ServiceReference ServiceRegistry::Get(ModulePrivate* module, const std::string& clazz) const { MutexLocker lock(mutex); try { std::list srs; Get_Unlocked(clazz, "", module, srs); MITK_INFO << "get service ref " << clazz << " for module " << module->info.name << " = " << srs.size() << " refs"; if (!srs.empty()) { return srs.front(); } } catch (const std::invalid_argument& ) { } return ServiceReference(); } void ServiceRegistry::Get(const std::string& clazz, const std::string& filter, ModulePrivate* module, std::list& res) const { MutexLocker lock(mutex); Get_Unlocked(clazz, filter, module, res); } void ServiceRegistry::Get_Unlocked(const std::string& clazz, const std::string& filter, ModulePrivate* /*module*/, std::list& res) const { std::list::const_iterator s; std::list::const_iterator send; std::list v; LDAPExpr ldap; if (clazz.empty()) { if (!filter.empty()) { ldap = LDAPExpr(filter); LDAPExpr::ObjectClassSet matched; if (ldap.GetMatchedObjectClasses(matched)) { v.clear(); for(LDAPExpr::ObjectClassSet::const_iterator className = matched.begin(); className != matched.end(); ++className) { MapClassServices::const_iterator i = classServices.find(*className); if (i != classServices.end()) { std::copy(i->second.begin(), i->second.end(), std::back_inserter(v)); } } if (!v.empty()) { s = v.begin(); send = v.end(); } else { return; } } else { s = serviceRegistrations.begin(); send = serviceRegistrations.end(); } } else { s = serviceRegistrations.begin(); send = serviceRegistrations.end(); } } else { MapClassServices::const_iterator it = classServices.find(clazz); if (it != classServices.end()) { s = it->second.begin(); send = it->second.end(); } else { return; } if (!filter.empty()) { ldap = LDAPExpr(filter); } } for (; s != send; ++s) { ServiceReference sri = s->GetReference(); if (filter.empty() || ldap.Evaluate(s->d->properties, false)) { res.push_back(sri); } } } void ServiceRegistry::RemoveServiceRegistration(const ServiceRegistration& sr) { MutexLocker lock(mutex); const std::list& classes = ref_any_cast >( sr.d->properties[ServiceConstants::OBJECTCLASS()]); services.erase(sr); serviceRegistrations.remove(sr); for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { std::list& s = classServices[*i]; if (s.size() > 1) { std::remove(s.begin(), s.end(), sr); } else { classServices.erase(*i); } } } void ServiceRegistry::GetRegisteredByModule(ModulePrivate* p, std::list& res) const { MutexLocker lock(mutex); for (std::list::const_iterator i = serviceRegistrations.begin(); i != serviceRegistrations.end(); ++i) { if (i->d->module == p) { res.push_back(*i); } } } void ServiceRegistry::GetUsedByModule(Module* p, std::list& res) const { MutexLocker lock(mutex); for (std::list::const_iterator i = serviceRegistrations.begin(); i != serviceRegistrations.end(); ++i) { if (i->d->IsUsedByModule(p)) { res.push_back(*i); } } } } // end namespace mitk diff --git a/Core/Code/Service/mitkServiceTracker.h b/Core/Code/Service/mitkServiceTracker.h index 88efdc10f1..c89894cb9f 100644 --- a/Core/Code/Service/mitkServiceTracker.h +++ b/Core/Code/Service/mitkServiceTracker.h @@ -1,429 +1,427 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKSERVICETRACKER_H #define MITKSERVICETRACKER_H -#include "mitkCommon.h" - #include "mitkServiceReference.h" #include "mitkServiceTrackerCustomizer.h" #include "mitkLDAPFilter.h" namespace mitk { template class TrackedService; template class ServiceTrackerPrivate; class ModuleContext; /** * \ingroup MicroServices * * The ServiceTracker class simplifies using services from the * framework's service registry. *

* A ServiceTracker object is constructed with search criteria and * a ServiceTrackerCustomizer object. A ServiceTracker * can use a ServiceTrackerCustomizer to customize the service * objects to be tracked. The ServiceTracker can then be opened to * begin tracking all services in the framework's service registry that match * the specified search criteria. The ServiceTracker correctly * handles all of the details of listening to ServiceEvents and * getting and ungetting services. *

* The GetServiceReferences method can be called to get references * to the services being tracked. The GetService and * GetServices methods can be called to get the service objects for * the tracked service. *

* The ServiceTracker class is thread-safe. It does not call a * ServiceTrackerCustomizer while holding any locks. * ServiceTrackerCustomizer implementations must also be * thread-safe. * * \tparam S The type of the service being tracked. The type must be an * assignable datatype. Further, if the * ServiceTracker(ModuleContext*, ServiceTrackerCustomizer*) * constructor is used, the type must have an associated interface id via * MITK_DECLARE_SERVICE_INTERFACE. * \tparam T The type of the tracked object. The type must be an assignable * datatype, provide a boolean conversion function, and provide * a constructor and an assignment operator which can handle 0 as an argument. * \remarks This class is thread safe. */ template class ServiceTracker : protected ServiceTrackerCustomizer { public: typedef std::map TrackingMap; ~ServiceTracker(); /** * Create a ServiceTracker on the specified * ServiceReference. * *

* The service referenced by the specified ServiceReference * will be tracked by this ServiceTracker. * * @param context The ModuleContext against which the tracking * is done. * @param reference The ServiceReference for the service to be * tracked. * @param customizer The customizer object to call when services are added, * modified, or removed in this ServiceTracker. If * customizer is null, then this * ServiceTracker will be used as the * ServiceTrackerCustomizer and this * ServiceTracker will call the * ServiceTrackerCustomizer methods on itself. */ ServiceTracker(ModuleContext* context, const ServiceReference& reference, ServiceTrackerCustomizer* customizer = 0); /** * Create a ServiceTracker on the specified class name. * *

* Services registered under the specified class name will be tracked by * this ServiceTracker. * * @param context The ModuleContext against which the tracking * is done. * @param clazz The class name of the services to be tracked. * @param customizer The customizer object to call when services are added, * modified, or removed in this ServiceTracker. If * customizer is null, then this * ServiceTracker will be used as the * ServiceTrackerCustomizer and this * ServiceTracker will call the * ServiceTrackerCustomizer methods on itself. */ ServiceTracker(ModuleContext* context, const std::string& clazz, ServiceTrackerCustomizer* customizer = 0); /** * Create a ServiceTracker on the specified * LDAPFilter object. * *

* Services which match the specified LDAPFilter object will be * tracked by this ServiceTracker. * * @param context The ModuleContext against which the tracking * is done. * @param filter The LDAPFilter to select the services to be * tracked. * @param customizer The customizer object to call when services are added, * modified, or removed in this ServiceTracker. If * customizer is null, then this ServiceTracker will be * used as the ServiceTrackerCustomizer and this * ServiceTracker will call the * ServiceTrackerCustomizer methods on itself. */ ServiceTracker(ModuleContext* context, const LDAPFilter& filter, ServiceTrackerCustomizer* customizer = 0); /** * Create a ServiceTracker on the class template * argument S. * *

* Services registered under the interface name of the class template * argument S will be tracked by this ServiceTracker. * * @param context The ModuleContext against which the tracking * is done. * @param customizer The customizer object to call when services are added, * modified, or removed in this ServiceTracker. If * customizer is null, then this ServiceTracker will be * used as the ServiceTrackerCustomizer and this * ServiceTracker will call the * ServiceTrackerCustomizer methods on itself. */ ServiceTracker(ModuleContext* context, ServiceTrackerCustomizer* customizer = 0); /** * Open this ServiceTracker and begin tracking services. * *

* Services which match the search criteria specified when this * ServiceTracker was created are now tracked by this * ServiceTracker. * * @throws std::logic_error If the ModuleContext * with which this ServiceTracker was created is no * longer valid. */ virtual void Open(); /** * Close this ServiceTracker. * *

* This method should be called when this ServiceTracker should * end the tracking of services. * *

* This implementation calls GetServiceReferences() to get the list * of tracked services to remove. */ virtual void Close(); /** * Wait for at least one service to be tracked by this * ServiceTracker. This method will also return when this * ServiceTracker is closed. * *

* It is strongly recommended that WaitForService is not used * during the calling of the ModuleActivator methods. * ModuleActivator methods are expected to complete in a short * period of time. * *

* This implementation calls GetService() to determine if a service * is being tracked. * * @return Returns the result of GetService(). */ virtual T WaitForService(); /** * Return a list of ServiceReferences for all services being * tracked by this ServiceTracker. * * @param refs List of ServiceReferences. */ virtual void GetServiceReferences(std::list& refs) const; /** * Returns a ServiceReference for one of the services being * tracked by this ServiceTracker. * *

* If multiple services are being tracked, the service with the highest * ranking (as specified in its service.ranking property) is * returned. If there is a tie in ranking, the service with the lowest * service ID (as specified in its service.id property); that * is, the service that was registered first is returned. This is the same * algorithm used by ModuleContext::GetServiceReference(). * *

* This implementation calls GetServiceReferences() to get the list * of references for the tracked services. * * @return A ServiceReference for a tracked service. * @throws ServiceException if no services are being tracked. */ virtual ServiceReference GetServiceReference() const; /** * Returns the service object for the specified * ServiceReference if the specified referenced service is * being tracked by this ServiceTracker. * * @param reference The reference to the desired service. * @return A service object or null if the service referenced * by the specified ServiceReference is not being * tracked. */ virtual T GetService(const ServiceReference& reference) const; /** * Return a list of service objects for all services being tracked by this * ServiceTracker. * *

* This implementation calls GetServiceReferences() to get the list * of references for the tracked services and then calls * GetService(const ServiceReference&) for each reference to get the * tracked service object. * * @param services A list of service objects or an empty list if no services * are being tracked. */ virtual void GetServices(std::list& services) const; /** * Returns a service object for one of the services being tracked by this * ServiceTracker. * *

* If any services are being tracked, this implementation returns the result * of calling %GetService(%GetServiceReference()). * * @return A service object or null if no services are being * tracked. */ virtual T GetService() const; /** * Remove a service from this ServiceTracker. * * The specified service will be removed from this * ServiceTracker. If the specified service was being tracked * then the ServiceTrackerCustomizer::RemovedService method will * be called for that service. * * @param reference The reference to the service to be removed. */ virtual void Remove(const ServiceReference& reference); /** * Return the number of services being tracked by this * ServiceTracker. * * @return The number of services being tracked. */ virtual int Size() const; /** * Returns the tracking count for this ServiceTracker. * * The tracking count is initialized to 0 when this * ServiceTracker is opened. Every time a service is added, * modified or removed from this ServiceTracker, the tracking * count is incremented. * *

* The tracking count can be used to determine if this * ServiceTracker has added, modified or removed a service by * comparing a tracking count value previously collected with the current * tracking count value. If the value has not changed, then no service has * been added, modified or removed from this ServiceTracker * since the previous tracking count was collected. * * @return The tracking count for this ServiceTracker or -1 if * this ServiceTracker is not open. */ virtual int GetTrackingCount() const; /** * Return a sorted map of the ServiceReferences and * service objects for all services being tracked by this * ServiceTracker. The map is sorted in natural order * of ServiceReference. That is, the last entry is the service * with the highest ranking and the lowest service id. * * @param tracked A TrackingMap with the ServiceReferences * and service objects for all services being tracked by this * ServiceTracker. If no services are being tracked, * then the returned map is empty. */ virtual void GetTracked(TrackingMap& tracked) const; /** * Return if this ServiceTracker is empty. * * @return true if this ServiceTracker is not tracking any * services. */ virtual bool IsEmpty() const; protected: /** * Default implementation of the * ServiceTrackerCustomizer::AddingService method. * *

* This method is only called when this ServiceTracker has been * constructed with a null ServiceTrackerCustomizer argument. * *

* This implementation returns the result of calling GetService * on the ModuleContext with which this * ServiceTracker was created passing the specified * ServiceReference. *

* This method can be overridden in a subclass to customize the service * object to be tracked for the service being added. In that case, take care * not to rely on the default implementation of * \link RemovedService(const ServiceReference&, T service) removedService\endlink * to unget the service. * * @param reference The reference to the service being added to this * ServiceTracker. * @return The service object to be tracked for the service added to this * ServiceTracker. * @see ServiceTrackerCustomizer::AddingService(const ServiceReference&) */ T AddingService(const ServiceReference& reference); /** * Default implementation of the * ServiceTrackerCustomizer::ModifiedService method. * *

* This method is only called when this ServiceTracker has been * constructed with a null ServiceTrackerCustomizer argument. * *

* This implementation does nothing. * * @param reference The reference to modified service. * @param service The service object for the modified service. * @see ServiceTrackerCustomizer::ModifiedService(const ServiceReference&, itk::LighObject*) */ void ModifiedService(const ServiceReference& reference, T service); /** * Default implementation of the * ServiceTrackerCustomizer::RemovedService method. * *

* This method is only called when this ServiceTracker has been * constructed with a null ServiceTrackerCustomizer argument. * *

* This implementation calls UngetService, on the * ModuleContext with which this ServiceTracker * was created, passing the specified ServiceReference. *

* This method can be overridden in a subclass. If the default * implementation of \link AddingService(const ServiceReference&) AddingService\endlink * method was used, this method must unget the service. * * @param reference The reference to removed service. * @param service The service object for the removed service. * @see ServiceTrackerCustomizer::RemovedService(const ServiceReference&, itk::LighObject*) */ void RemovedService(const ServiceReference& reference, T service); private: typedef ServiceTracker _ServiceTracker; typedef TrackedService _TrackedService; typedef ServiceTrackerPrivate _ServiceTrackerPrivate; typedef ServiceTrackerCustomizer _ServiceTrackerCustomizer; friend class TrackedService; friend class ServiceTrackerPrivate; _ServiceTrackerPrivate* const d; }; } #include "mitkServiceTracker.tpp" #endif // MITKSERVICETRACKER_H diff --git a/Core/Code/Service/mitkSharedData.h b/Core/Code/Service/mitkSharedData.h index f4f81e5bae..95c025c542 100644 --- a/Core/Code/Service/mitkSharedData.h +++ b/Core/Code/Service/mitkSharedData.h @@ -1,262 +1,262 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. Modified version of qshareddata.h from Qt 4.7.3 for MITK. Original copyright (c) Nokia Corporation. Usage covered by the GNU Lesser General Public License version 2.1 (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) and the Nokia Qt LGPL Exception version 1.1 (file LGPL_EXCEPTION.txt in Qt 4.7.3 package). =========================================================================*/ #ifndef MITKSHAREDDATA_H #define MITKSHAREDDATA_H #include #include -#include +#include #include "mitkAtomicInt.h" namespace mitk { template class SharedDataPointer; class MITK_CORE_EXPORT SharedData { public: mutable AtomicInt ref; inline SharedData() : ref(0) { } inline SharedData(const SharedData&) : ref(0) { } private: // using the assignment operator would lead to corruption in the ref-counting SharedData& operator=(const SharedData&); }; template class SharedDataPointer { public: typedef T Type; typedef T* pointer; inline void Detach() { if (d && d->ref != 1) Detach_helper(); } inline T& operator*() { Detach(); return *d; } inline const T& operator*() const { return *d; } inline T* operator->() { Detach(); return d; } inline const T* operator->() const { return d; } inline operator T*() { Detach(); return d; } inline operator const T*() const { return d; } inline T* Data() { Detach(); return d; } inline const T* Data() const { return d; } inline const T* ConstData() const { return d; } inline bool operator==(const SharedDataPointer& other) const { return d == other.d; } inline bool operator!=(const SharedDataPointer& other) const { return d != other.d; } inline SharedDataPointer() { d = 0; } inline ~SharedDataPointer() { if (d && !d->ref.Deref()) delete d; } explicit SharedDataPointer(T* data); inline SharedDataPointer(const SharedDataPointer& o) : d(o.d) { if (d) d->ref.Ref(); } inline SharedDataPointer & operator=(const SharedDataPointer& o) { if (o.d != d) { if (o.d) o.d->ref.Ref(); T *old = d; d = o.d; if (old && !old->ref.Deref()) delete old; } return *this; } inline SharedDataPointer &operator=(T *o) { if (o != d) { if (o) o->ref.Ref(); T *old = d; d = o; if (old && !old->ref.Deref()) delete old; } return *this; } inline bool operator!() const { return !d; } inline void Swap(SharedDataPointer& other) { using std::swap; swap(d, other.d); } protected: T* Clone(); private: void Detach_helper(); T *d; }; template class ExplicitlySharedDataPointer { public: typedef T Type; typedef T* pointer; inline T& operator*() const { return *d; } inline T* operator->() { return d; } inline T* operator->() const { return d; } inline T* Data() const { return d; } inline const T* ConstData() const { return d; } inline void Detach() { if (d && d->ref != 1) Detach_helper(); } inline void Reset() { if(d && !d->ref.Deref()) delete d; d = 0; } inline operator bool () const { return d != 0; } inline bool operator==(const ExplicitlySharedDataPointer& other) const { return d == other.d; } inline bool operator!=(const ExplicitlySharedDataPointer& other) const { return d != other.d; } inline bool operator==(const T* ptr) const { return d == ptr; } inline bool operator!=(const T* ptr) const { return d != ptr; } inline ExplicitlySharedDataPointer() { d = 0; } inline ~ExplicitlySharedDataPointer() { if (d && !d->ref.Deref()) delete d; } explicit ExplicitlySharedDataPointer(T* data); inline ExplicitlySharedDataPointer(const ExplicitlySharedDataPointer &o) : d(o.d) { if (d) d->ref.Ref(); } template inline ExplicitlySharedDataPointer(const ExplicitlySharedDataPointer& o) : d(static_cast(o.Data())) { if(d) d->ref.Ref(); } inline ExplicitlySharedDataPointer& operator=(const ExplicitlySharedDataPointer& o) { if (o.d != d) { if (o.d) o.d->ref.Ref(); T *old = d; d = o.d; if (old && !old->ref.Deref()) delete old; } return *this; } inline ExplicitlySharedDataPointer& operator=(T* o) { if (o != d) { if (o) o->ref.Ref(); T *old = d; d = o; if (old && !old->ref.Deref()) delete old; } return *this; } inline bool operator!() const { return !d; } inline void Swap(ExplicitlySharedDataPointer& other) { using std::swap; swap(d, other.d); } protected: T* Clone(); private: void Detach_helper(); T *d; }; template SharedDataPointer::SharedDataPointer(T* adata) : d(adata) { if (d) d->ref.Ref(); } template T* SharedDataPointer::Clone() { return new T(*d); } template void SharedDataPointer::Detach_helper() { T *x = Clone(); x->ref.Ref(); if (!d->ref.Deref()) delete d; d = x; } template T* ExplicitlySharedDataPointer::Clone() { return new T(*d); } template void ExplicitlySharedDataPointer::Detach_helper() { T *x = Clone(); x->ref.Ref(); if (!d->ref.Deref()) delete d; d = x; } template ExplicitlySharedDataPointer::ExplicitlySharedDataPointer(T* adata) : d(adata) { if (d) d->ref.Ref(); } template void swap(mitk::SharedDataPointer& p1, mitk::SharedDataPointer& p2) { p1.Swap(p2); } template void swap(mitk::ExplicitlySharedDataPointer& p1, mitk::ExplicitlySharedDataPointer& p2) { p1.Swap(p2); } } #endif // MITKSHAREDDATA_H