48 using Identifier =
const char*;
68 inline void increaseCounter()
74 virtual ~FuncWrapperBase();
77 template<
typename T,
typename ... Args>
78 class FuncWrapper final
79 :
public FuncWrapperBase
82 const std::function<
T(Args ...)> mFunc;
85 explicit FuncWrapper(std::function<
T(Args ...)> pFunc)
86 : mFunc(std::move(pFunc))
91 T operator()(Args&& ... pArgs)
94 return mFunc(pArgs ...);
100 using Wrapper = QSharedPointer<FuncWrapperBase>;
101 QList<Wrapper> mInstancesCreator;
102 QMap<Identifier, void*> mInstancesSingleton;
103 mutable QReadWriteLock mLock;
106 QPointer<QObjectCleanupHandler> mSingletonHandler;
107 QList<std::function<
void* (bool)>> mSingletonCreator;
109 QMap<Identifier, QWeakPointer<QObject>> mSharedInstances;
110 mutable QReadWriteLock mSharedInstancesLock;
112 static Env& getInstance();
117 Q_ASSERT(!mSingletonHandler.isNull());
119 if (!QCoreApplication::startingUp() && !QCoreApplication::applicationName().startsWith(QLatin1String(
"Test_")))
121 Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String(
"MainThread"));
125 qDebug() <<
"Create singleton:" << T::staticMetaObject.className();
128 if constexpr (std::is_abstract_v<T>&& std::is_destructible_v<T>)
137 QObject::connect(ptr, &QObject::destroyed, ptr, [] {
138 qDebug() <<
"Destroy singleton:" << T::staticMetaObject.className();
140 mSingletonHandler->add(ptr);
141 mSingletonCreator << std::bind(&Env::getOrCreateSingleton<T>,
this, std::placeholders::_1);
148 T* getOrCreateSingleton(
bool pCreate =
false)
150 static QPointer<T> instance = createSingleton<T>();
152 if (Q_UNLIKELY(pCreate))
155 Q_ASSERT(instance.isNull());
156 instance = createSingleton<T>();
164 inline T* fetchRealSingleton()
166 if constexpr (QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value)
168 return getOrCreateSingleton<T>();
172 if constexpr (std::is_abstract_v<T>&& std::is_destructible_v<T>)
174 static_assert(std::has_virtual_destructor_v<T>,
"Destructor must be virtual");
179 return &T::getInstance();
186 inline T* checkObjectInfo(Identifier pId,
T* pObject)
const
188 static_assert(QtPrivate::IsGadgetHelper<T>::IsRealGadget || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
189 "Object needs to be a Q_GADGET or an QObject/Q_OBJECT");
191 if constexpr (QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value)
193 if (!std::is_base_of<ThreadSafe, T>() && pObject->thread() != QThread::currentThread())
195 qWarning() << pId <<
"was created in" << pObject->thread()->objectName() <<
"but is requested by" << QThread::currentThread()->objectName();
197 Q_ASSERT(QCoreApplication::applicationName().startsWith(QLatin1String(
"Test_global_Env")));
207 inline T* fetchSingleton()
209 static_assert(QtPrivate::IsGadgetHelper<T>::IsRealGadget || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
210 "Singletons needs to be a Q_GADGET or an QObject/Q_OBJECT");
212 const Identifier
id = T::staticMetaObject.className();
215 const QReadLocker locker(&mLock);
216 obj = mInstancesSingleton.value(
id);
219 obj = fetchRealSingleton<T>();
221 return checkObjectInfo(
id,
static_cast<T*
>(obj));
225 template<
typename T,
typename ... Args>
226 inline T newObject(Args&& ... pArgs)
const
228 if constexpr (std::is_constructible_v<std::remove_pointer_t<T>, Args ...>)
230 if constexpr (std::is_pointer_v<T>)
232 using t = std::remove_pointer_t<T>;
233 return new t(std::forward<Args>(pArgs) ...);
237 return T(std::forward<Args>(pArgs) ...);
242 static_assert(std::is_pointer_v<T>,
"It is impossible to return implementation of interface by value. Use pointer or add constructor!");
250 template<
typename T,
typename ... Args>
251 T createObject(Args&& ... pArgs)
const
255 QReadLocker locker(&mLock);
259 for (
auto mock : std::as_const(mInstancesCreator))
261 auto creator = mock.dynamicCast<FuncWrapper<
T, Args ...>>();
265 return (*creator)(std::forward<Args>(pArgs) ...);
271 return newObject<T>(std::forward<Args>(pArgs) ...);
277 Q_ASSERT(mSingletonHandler.isNull());
278 mSingletonHandler =
new QObjectCleanupHandler();
279 QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, mSingletonHandler.data(), &QObject::deleteLater);
281 const auto copy = mSingletonCreator;
282 mSingletonCreator.clear();
283 for (
const auto& func : copy)
296 getInstance().initialize();
303 return getInstance().fetchSingleton<
T>();
307 template<
typename T,
typename ... Args>
310 return getInstance().createObject<
T>(std::forward<Args>(pArgs) ...);
317 static_assert(QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
"Shared class needs to be an QObject/Q_OBJECT");
319 const Identifier className = T::staticMetaObject.className();
321 auto& holder = getInstance();
322 holder.mSharedInstancesLock.lockForRead();
323 QSharedPointer<T> shared = qSharedPointerCast<T>(holder.mSharedInstances.value(className));
324 holder.mSharedInstancesLock.unlock();
326 if (!shared && pSpawn)
328 const QWriteLocker locker(&holder.mSharedInstancesLock);
329 shared = qSharedPointerCast<T>(holder.mSharedInstances.value(className));
332 qDebug() <<
"Spawn shared instance:" << className;
333 shared = QSharedPointer<T>::create();
334 holder.mSharedInstances.insert(className, shared.toWeakRef());
345 static void set(
const QMetaObject& pMetaObject,
void* pObject =
nullptr);
347 template<
typename T,
typename ... Args>
350 auto& holder = getInstance();
351 const QReadLocker locker(&holder.mLock);
353 for (
const auto& mock : std::as_const(holder.mInstancesCreator))
355 if (mock.dynamicCast<FuncWrapper<T, Args ...>>())
357 return mock->getCounter();
365 template<
typename T,
typename ... Args>
370 const auto& value = QSharedPointer<FuncWrapper<
T, Args ...>>
::create(std::move(pFunc));
372 auto& holder = getInstance();
373 const QWriteLocker locker(&holder.mLock);
375 QMutableListIterator<Wrapper> iter(holder.mInstancesCreator);
376 while (iter.hasNext())
379 if (iter.value().dynamicCast<FuncWrapper<T, Args ...>>())
381 iter.setValue(value);
386 holder.mInstancesCreator << value;
390 static void setShared(
const QMetaObject& pMetaObject,
const QSharedPointer<QObject>& pObject);