DependencyManager update

- Now need a call to DependencyManager::set(...) that support
	  variable arguments number and type
	- Now support destroy operation via DependencyManager::destroy()
	- Now support inheritance. All inheritance relationship need to
	  be specified via DependencyManager::registerInheritance<Base,
Derived>() before any call to the DepedencyManager involving Base.
	- Dependencies should now inherit from the class Dependency as
	  well as using SINGLETON_DEPENDENCY
This commit is contained in:
Atlante45 2015-01-13 20:27:38 -08:00
parent 4429e144f4
commit 27cc3d297e
2 changed files with 70 additions and 22 deletions

View file

@ -10,3 +10,9 @@
//
#include "DependencyManager.h"
DependencyManager DependencyManager::_manager;
QSharedPointer<Dependency>& DependencyManager::safeGet(size_t hashCode) {
return _instanceHash[hashCode];
}

View file

@ -12,29 +12,31 @@
#ifndef hifi_DependencyManager_h
#define hifi_DependencyManager_h
#include <QSharedPointer>
#include <QDebug>
#include <QHash>
#include <QSharedPointer>
#include <QWeakPointer>
#include <typeinfo>
#define SINGLETON_DEPENDENCY \
private:\
void customDeleter() {\
QObject* thisObject = dynamic_cast<QObject*>(this);\
if (thisObject && thisObject->parent()) {\
thisObject->deleteLater();\
} else {\
delete this;\
}\
}\
friend class DependencyManager;
class QObject;
class Dependency {
protected:
virtual ~Dependency() {}
virtual void customDeleter() {
delete this;
}
friend class DependencyManager;
};
// usage:
// T* instance = DependencyManager::get<T>();
// T* instance = DependencyManager::set<T>(Args... args);
// T* instance = DependencyManager::destroy<T>();
// auto instance = DependencyManager::get<T>();
// auto instance = DependencyManager::set<T>(Args... args);
// DependencyManager::destroy<T>();
// DependencyManager::registerInheritance<Base, Derived>();
class DependencyManager {
public:
template<typename T>
@ -46,32 +48,72 @@ public:
template<typename T>
static void destroy();
template<typename Base, typename Derived>
static void registerInheritance();
private:
static DependencyManager _manager;
template<typename T>
static QSharedPointer<T>& storage();
size_t getHashCode();
QSharedPointer<Dependency>& safeGet(size_t hashCode);
QHash<size_t, QSharedPointer<Dependency>> _instanceHash;
QHash<size_t, size_t> _inheritanceHash;
};
template <typename T>
QSharedPointer<T> DependencyManager::get() {
return storage<T>();
static size_t hashCode = _manager.getHashCode<T>();
static QWeakPointer<T> instance;
if (instance.isNull()) {
instance = qSharedPointerCast<T>(_manager.safeGet(hashCode));
if (instance.isNull()) {
qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name();
}
}
return instance.toStrongRef();
}
template <typename T, typename ...Args>
QSharedPointer<T> DependencyManager::set(Args&&... args) {
static size_t hashCode = _manager.getHashCode<T>();
QSharedPointer<T> instance(new T(args...), &T::customDeleter);
storage<T>().swap(instance);
return storage<T>();
QSharedPointer<Dependency> storedInstance = qSharedPointerCast<Dependency>(instance);
_manager.safeGet(hashCode).swap(storedInstance);
return instance;
}
template <typename T>
void DependencyManager::destroy() {
storage<T>().clear();
static size_t hashCode = _manager.getHashCode<T>();
_manager.safeGet(hashCode).clear();
}
template<typename Base, typename Derived>
void DependencyManager::registerInheritance() {
size_t baseHashCode = typeid(Base).hash_code();
size_t derivedHashCode = typeid(Derived).hash_code();
_manager._inheritanceHash.insert(baseHashCode, derivedHashCode);
}
template<typename T>
QSharedPointer<T>& DependencyManager::storage() {
static QSharedPointer<T> sharedPointer;
return sharedPointer;
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