// // DependencyManager.h // // // Created by Clément Brisset on 12/10/14. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #ifndef hifi_DependencyManager_h #define hifi_DependencyManager_h #include #include #include #include #include #include #define SINGLETON_DEPENDENCY \ friend class DependencyManager; class Dependency { public: typedef std::function DeleterFunction; protected: virtual ~Dependency() {} virtual void customDeleter() { _customDeleter(this); } void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; } DeleterFunction _customDeleter = [](Dependency* pointer) { delete pointer; }; friend class DependencyManager; }; // usage: // auto instance = DependencyManager::get(); // auto instance = DependencyManager::set(Args... args); // DependencyManager::destroy(); // DependencyManager::registerInheritance(); class DependencyManager { public: template static QSharedPointer get(); template static QSharedPointer set(Args&&... args); template static void destroy(); template static void registerInheritance(); private: static DependencyManager _manager; template size_t getHashCode(); QSharedPointer& safeGet(size_t hashCode); QHash> _instanceHash; QHash _inheritanceHash; }; template QSharedPointer DependencyManager::get() { static size_t hashCode = _manager.getHashCode(); static QWeakPointer instance; if (instance.isNull()) { instance = qSharedPointerCast(_manager.safeGet(hashCode)); if (instance.isNull()) { qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); } } return instance.toStrongRef(); } template QSharedPointer DependencyManager::set(Args&&... args) { static size_t hashCode = _manager.getHashCode(); QSharedPointer& instance = _manager.safeGet(hashCode); instance.clear(); // Clear instance before creation of new one to avoid edge cases QSharedPointer newInstance(new T(args...), &T::customDeleter); QSharedPointer storedInstance = qSharedPointerCast(newInstance); instance.swap(storedInstance); return newInstance; } template void DependencyManager::destroy() { static size_t hashCode = _manager.getHashCode(); _manager.safeGet(hashCode).clear(); } template void DependencyManager::registerInheritance() { size_t baseHashCode = typeid(Base).hash_code(); size_t derivedHashCode = typeid(Derived).hash_code(); _manager._inheritanceHash.insert(baseHashCode, derivedHashCode); } template size_t DependencyManager::getHashCode() { size_t hashCode = typeid(T).hash_code(); auto derivedHashCode = _inheritanceHash.find(hashCode); while (derivedHashCode != _inheritanceHash.end()) { hashCode = derivedHashCode.value(); derivedHashCode = _inheritanceHash.find(hashCode); } return hashCode; } #endif // hifi_DependencyManager_h