10 #include <type_traits>
12 #include <QCoreApplication>
15 #include <QMetaObject>
18 #include <QObjectCleanupHandler>
20 #include <QReadLocker>
21 #include <QReadWriteLock>
22 #include <QSharedPointer>
24 #include <QWeakPointer>
25 #include <QWriteLocker>
28 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
29 #include <QMutableVectorIterator>
49 friend class ::test_Env;
51 using Identifier =
const char*;
72 virtual ~FuncWrapperBase();
75 template<
typename T,
typename ... Args>
76 class FuncWrapper final
77 :
public FuncWrapperBase
80 const std::function<
T(Args ...)> mFunc;
83 explicit FuncWrapper(std::function<
T(Args ...)> pFunc)
84 : mFunc(std::move(pFunc))
89 T operator()(Args&& ... pArgs)
92 return mFunc(pArgs ...);
98 using Wrapper = QSharedPointer<FuncWrapperBase>;
99 QVector<Wrapper> mInstancesCreator;
100 QMap<Identifier, void*> mInstancesSingleton;
101 mutable QReadWriteLock mLock;
104 QPointer<QObjectCleanupHandler> mSingletonHandler;
105 QVector<std::function<
void* (bool)>> mSingletonCreator;
107 QMap<Identifier, QWeakPointer<QObject>> mSharedInstances;
108 mutable QReadWriteLock mSharedInstancesLock;
110 static Env& getInstance();
115 Q_ASSERT(!mSingletonHandler.isNull());
117 if (!QCoreApplication::startingUp() && !QCoreApplication::applicationName().startsWith(QLatin1String(
"Test_")))
119 Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String(
"MainThread"));
123 qDebug() <<
"Create singleton:" << T::staticMetaObject.className();
126 if constexpr (std::is_abstract<T>::value && std::is_destructible<T>::value)
128 ptr = createNewObject<T*>();
135 QObject::connect(ptr, &QObject::destroyed, ptr, [] {
136 qDebug() <<
"Destroy singleton:" << T::staticMetaObject.className();
138 mSingletonHandler->add(ptr);
139 mSingletonCreator << std::bind(&Env::getOrCreateSingleton<T>,
this, std::placeholders::_1);
146 T* getOrCreateSingleton(
bool pCreate =
false)
148 static QPointer<T> instance = createSingleton<T>();
150 if (Q_UNLIKELY(pCreate))
153 Q_ASSERT(instance.isNull());
154 instance = createSingleton<T>();
162 inline T* fetchRealSingleton()
164 if constexpr (QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value)
166 return getOrCreateSingleton<T>();
170 if constexpr (std::is_abstract<T>::value && std::is_destructible<T>::value)
172 static_assert(std::has_virtual_destructor<T>::value,
"Destructor must be virtual");
173 return singleton<T>();
177 return &T::getInstance();
184 inline typename std::enable_if<QtPrivate::IsGadgetHelper<T>::IsRealGadget,
T*>::type checkObjectInfo(Identifier pId,
T* pObject)
const
192 inline typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
T*>::type checkObjectInfo(Identifier pId,
T* pObject)
const
194 if (!std::is_base_of<ThreadSafe, T>() && pObject->thread() != QThread::currentThread())
196 qWarning() << pId <<
"was created in" << pObject->thread()->objectName() <<
"but is requested by" << QThread::currentThread()->objectName();
198 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<
typename std::remove_pointer<T>::type, Args ...>::value)
230 if constexpr (std::is_pointer<T>::value)
232 using t =
typename std::remove_pointer<T>::type;
233 return new t(std::forward<Args>(pArgs) ...);
237 return T(std::forward<Args>(pArgs) ...);
242 static_assert(std::is_pointer<T>::value,
"It is impossible to return implementation of interface by value. Use pointer or add constructor!");
243 auto obj = createNewObject<T>(std::forward<Args>(pArgs) ...);
250 template<
typename T,
typename ... Args>
251 T createObject(Args&& ... pArgs)
const
255 QReadLocker locker(&mLock);
259 for (
auto mock : qAsConst(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::IsGadgetHelper<T>::IsRealGadget || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
318 "Shared class needs to be a Q_GADGET or an QObject/Q_OBJECT");
320 const Identifier className = T::staticMetaObject.className();
322 auto& holder = getInstance();
323 holder.mSharedInstancesLock.lockForRead();
324 QSharedPointer<T> shared = qSharedPointerCast<T>(holder.mSharedInstances.value(className));
325 holder.mSharedInstancesLock.unlock();
329 const QWriteLocker locker(&holder.mSharedInstancesLock);
330 shared = qSharedPointerCast<T>(holder.mSharedInstances.value(className));
333 qDebug() <<
"Spawn shared instance:" << className;
334 shared = QSharedPointer<T>::create();
335 holder.mSharedInstances.insert(className, shared.toWeakRef());
346 static void set(
const QMetaObject& pMetaObject,
void* pObject =
nullptr);
348 template<
typename T,
typename ... Args>
351 auto& holder = getInstance();
352 const QReadLocker locker(&holder.mLock);
354 for (
const auto& mock : qAsConst(holder.mInstancesCreator))
356 if (mock.dynamicCast<FuncWrapper<T, Args ...>>())
358 return mock->getCounter();
366 template<
typename T,
typename ... Args>
371 const auto& value = QSharedPointer<FuncWrapper<
T, Args ...>>
::create(std::move(pFunc));
373 auto& holder = getInstance();
374 const QWriteLocker locker(&holder.mLock);
376 QMutableVectorIterator<Wrapper> iter(holder.mInstancesCreator);
377 while (iter.hasNext())
380 if (iter.value().dynamicCast<FuncWrapper<T, Args ...>>())
382 iter.setValue(value);
387 holder.mInstancesCreator << value;
391 static void setShared(
const QMetaObject& pMetaObject,
const QSharedPointer<QObject>& pObject);
static void setCreator(std::function< T(Args ...)> pFunc)
Definition: Env.h:367
static QSharedPointer< T > getShared()
Definition: Env.h:315
static int getCounter()
Definition: Env.h:349
static void set(const QMetaObject &pMetaObject, void *pObject=nullptr)
Definition: Env.cpp:59
static void clear()
Definition: Env.cpp:46
Env()
Definition: Env.cpp:27
static void resetCounter()
Definition: Env.cpp:37
static T create(Args &&... pArgs)
Definition: Env.h:308
static void init()
Definition: Env.h:294
static void setShared(const QMetaObject &pMetaObject, const QSharedPointer< QObject > &pObject)
Definition: Env.cpp:80
static T * getSingleton()
Definition: Env.h:301
#define T(v)
Definition: http_parser.cpp:237
Implementation of ActivationContext for Intent based activation on Android systems.
Definition: ActivationContext.h:15
T createNewObject(Args &&... pArgs)