12 #ifndef hifi_DependencyManager_h
13 #define hifi_DependencyManager_h
18 #include <QtCore/QSharedPointer>
19 #include <QWeakPointer>
25 #define SINGLETON_DEPENDENCY \
26 friend class ::DependencyManager;
30 typedef std::function<void(Dependency* pointer)> DeleterFunction;
33 virtual ~Dependency() {}
34 virtual void customDeleter() {
38 void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; }
39 DeleterFunction _customDeleter = [](Dependency* pointer) {
delete pointer; };
41 friend class DependencyManager;
49 class DependencyManager {
52 static QSharedPointer<T> get();
57 template<
typename T,
typename ...Args>
58 static QSharedPointer<T> set(Args&&... args);
60 template<
typename T,
typename I,
typename ...Args>
61 static QSharedPointer<T> set(Args&&... args);
64 static void destroy();
66 template<
typename Base,
typename Derived>
67 static void registerInheritance();
70 static size_t typeHash() {
72 size_t hashCode = std::hash<std::string>{}(
typeid(T).name() );
74 size_t hashCode =
typeid(T).hash_code();
79 static void prepareToExit() { manager()._exiting =
true; }
82 static DependencyManager& manager();
85 size_t getHashCode()
const;
87 QSharedPointer<Dependency> safeGet(
size_t hashCode)
const;
89 QHash<size_t, QSharedPointer<Dependency>> _instanceHash;
90 QHash<size_t, size_t> _inheritanceHash;
92 mutable QRecursiveMutex _instanceHashMutex;
93 mutable QMutex _inheritanceHashMutex;
95 bool _exiting {
false };
99 QSharedPointer<T> DependencyManager::get() {
100 static size_t hashCode = manager().getHashCode<T>();
101 static QWeakPointer<T> instance;
103 if (instance.isNull()) {
104 instance = qSharedPointerCast<T>(manager().safeGet(hashCode));
108 if (instance.isNull()) {
109 qWarning() <<
"DependencyManager::get(): No instance available for" <<
typeid(T).name();
115 if (!manager()._exiting && instance.isNull()) {
116 qWarning() <<
"DependencyManager::get(): No instance available for" <<
typeid(T).name();
121 return instance.toStrongRef();
124 template <
typename T>
125 bool DependencyManager::isSet() {
126 static size_t hashCode = manager().getHashCode<T>();
128 QSharedPointer<Dependency> instance = manager().safeGet(hashCode);
129 return !instance.isNull();
132 template <
typename T,
typename ...Args>
133 QSharedPointer<T> DependencyManager::set(Args&&... args) {
134 static size_t hashCode = manager().getHashCode<T>();
135 QMutexLocker lock(&manager()._instanceHashMutex);
138 auto iter = manager()._instanceHash.find(hashCode);
139 if (iter != manager()._instanceHash.end()) {
140 iter.value().clear();
143 QSharedPointer<T> newInstance(
new T(args...), &T::customDeleter);
144 manager()._instanceHash.insert(hashCode, newInstance);
149 template <
typename T,
typename I,
typename ...Args>
150 QSharedPointer<T> DependencyManager::set(Args&&... args) {
151 static size_t hashCode = manager().getHashCode<T>();
152 QMutexLocker lock(&manager()._instanceHashMutex);
155 auto iter = manager()._instanceHash.find(hashCode);
156 if (iter != manager()._instanceHash.end()) {
157 iter.value().clear();
160 QSharedPointer<T> newInstance(
new I(args...), &I::customDeleter);
161 manager()._instanceHash.insert(hashCode, newInstance);
166 template <
typename T>
167 void DependencyManager::destroy() {
168 static size_t hashCode = manager().getHashCode<T>();
170 QMutexLocker lock(&manager()._instanceHashMutex);
171 QSharedPointer<Dependency> shared = manager()._instanceHash.take(hashCode);
172 QWeakPointer<Dependency> weak = shared;
177 qWarning() <<
"DependencyManager::destroy():" <<
typeid(T).name() <<
"was not properly destroyed!";
181 template<
typename Base,
typename Derived>
182 void DependencyManager::registerInheritance() {
183 size_t baseHashCode = typeHash<Base>();
184 size_t derivedHashCode = typeHash<Derived>();
185 QMutexLocker lock(&manager()._inheritanceHashMutex);
186 manager()._inheritanceHash.insert(baseHashCode, derivedHashCode);
190 size_t DependencyManager::getHashCode()
const {
191 size_t hashCode = typeHash<T>();
192 QMutexLocker lock(&_inheritanceHashMutex);
193 auto derivedHashCode = _inheritanceHash.find(hashCode);
195 while (derivedHashCode != _inheritanceHash.end()) {
196 hashCode = derivedHashCode.value();
197 derivedHashCode = _inheritanceHash.find(hashCode);