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>
46 friend class ::test_Env;
52 using Identifier =
const char*;
72 inline void increaseCounter()
78 virtual ~FuncWrapperBase();
81 template<
typename T,
typename ... Args>
82 class FuncWrapper final
83 :
public FuncWrapperBase
86 const std::function<
T(Args ...)> mFunc;
89 explicit FuncWrapper(std::function<
T(Args ...)> pFunc)
90 : mFunc(std::move(pFunc))
95 T operator()(Args&& ... pArgs)
98 return mFunc(pArgs ...);
104 using Wrapper = QSharedPointer<FuncWrapperBase>;
105 QVector<Wrapper> mInstancesCreator;
106 QMap<Identifier, void*> mInstancesSingleton;
107 mutable QReadWriteLock mLock;
110 QPointer<QObjectCleanupHandler> mSingletonHandler;
111 QVector<std::function<
void* (bool)>> mSingletonCreator;
113 QMap<Identifier, QWeakPointer<QObject>> mSharedInstances;
114 mutable QReadWriteLock mSharedInstancesLock;
116 static Env& getInstance();
121 Q_ASSERT(!mSingletonHandler.isNull());
123 if (!QCoreApplication::startingUp() && !QCoreApplication::applicationName().startsWith(QLatin1String(
"Test_")))
125 Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String(
"MainThread"));
129 qDebug() <<
"Create singleton:" << T::staticMetaObject.className();
132 if constexpr (std::is_abstract_v<T> && std::is_destructible_v<T>)
134 ptr = createNewObject<T*>();
141 QObject::connect(ptr, &QObject::destroyed, ptr, [] {
142 qDebug() <<
"Destroy singleton:" << T::staticMetaObject.className();
144 mSingletonHandler->add(ptr);
145 mSingletonCreator << std::bind(&Env::getOrCreateSingleton<T>,
this, std::placeholders::_1);
152 T* getOrCreateSingleton(
bool pCreate =
false)
154 static QPointer<T> instance = createSingleton<T>();
156 if (Q_UNLIKELY(pCreate))
159 Q_ASSERT(instance.isNull());
160 instance = createSingleton<T>();
168 inline T* fetchRealSingleton()
170 if constexpr (QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value)
172 return getOrCreateSingleton<T>();
176 if constexpr (std::is_abstract_v<T> && std::is_destructible_v<T>)
178 static_assert(std::has_virtual_destructor_v<T>,
"Destructor must be virtual");
179 return singleton<T>();
183 return &T::getInstance();
190 inline std::enable_if_t<QtPrivate::IsGadgetHelper<T>::IsRealGadget,
T*> checkObjectInfo(Identifier pId,
T* pObject)
const
198 inline std::enable_if_t<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
T*> checkObjectInfo(Identifier pId,
T* pObject)
const
200 if (!std::is_base_of<ThreadSafe, T>() && pObject->thread() != QThread::currentThread())
202 qWarning() << pId <<
"was created in" << pObject->thread()->objectName() <<
"but is requested by" << QThread::currentThread()->objectName();
204 Q_ASSERT(QCoreApplication::applicationName().startsWith(QLatin1String(
"Test_global_Env")));
213 inline T* fetchSingleton()
215 static_assert(QtPrivate::IsGadgetHelper<T>::IsRealGadget || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
216 "Singletons needs to be a Q_GADGET or an QObject/Q_OBJECT");
218 const Identifier
id = T::staticMetaObject.className();
221 const QReadLocker locker(&mLock);
222 obj = mInstancesSingleton.value(
id);
225 obj = fetchRealSingleton<T>();
227 return checkObjectInfo(
id,
static_cast<T*
>(obj));
231 template<
typename T,
typename ... Args>
232 inline T newObject(Args&& ... pArgs)
const
234 if constexpr (std::is_constructible_v<std::remove_pointer_t<T>, Args ...>)
236 if constexpr (std::is_pointer_v<T>)
238 using t = std::remove_pointer_t<T>;
239 return new t(std::forward<Args>(pArgs) ...);
243 return T(std::forward<Args>(pArgs) ...);
248 static_assert(std::is_pointer_v<T>,
"It is impossible to return implementation of interface by value. Use pointer or add constructor!");
249 auto obj = createNewObject<T>(std::forward<Args>(pArgs) ...);
256 template<
typename T,
typename ... Args>
257 T createObject(Args&& ... pArgs)
const
261 QReadLocker locker(&mLock);
265 for (
auto mock : std::as_const(mInstancesCreator))
267 auto creator = mock.dynamicCast<FuncWrapper<
T, Args ...>>();
271 return (*creator)(std::forward<Args>(pArgs) ...);
277 return newObject<T>(std::forward<Args>(pArgs) ...);
283 Q_ASSERT(mSingletonHandler.isNull());
284 mSingletonHandler =
new QObjectCleanupHandler();
285 QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, mSingletonHandler.data(), &QObject::deleteLater);
287 const auto copy = mSingletonCreator;
288 mSingletonCreator.clear();
289 for (
const auto& func : copy)
302 getInstance().initialize();
309 return getInstance().fetchSingleton<
T>();
313 template<
typename T,
typename ... Args>
316 return getInstance().createObject<
T>(std::forward<Args>(pArgs) ...);
323 static_assert(QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
"Shared class needs to be an QObject/Q_OBJECT");
325 const Identifier className = T::staticMetaObject.className();
327 auto& holder = getInstance();
328 holder.mSharedInstancesLock.lockForRead();
329 QSharedPointer<T> shared = qSharedPointerCast<T>(holder.mSharedInstances.value(className));
330 holder.mSharedInstancesLock.unlock();
334 const QWriteLocker locker(&holder.mSharedInstancesLock);
335 shared = qSharedPointerCast<T>(holder.mSharedInstances.value(className));
338 qDebug() <<
"Spawn shared instance:" << className;
339 shared = QSharedPointer<T>::create();
340 holder.mSharedInstances.insert(className, shared.toWeakRef());
351 static void set(
const QMetaObject& pMetaObject,
void* pObject =
nullptr);
353 template<
typename T,
typename ... Args>
356 auto& holder = getInstance();
357 const QReadLocker locker(&holder.mLock);
359 for (
const auto& mock : std::as_const(holder.mInstancesCreator))
361 if (mock.dynamicCast<FuncWrapper<T, Args ...>>())
363 return mock->getCounter();
371 template<
typename T,
typename ... Args>
376 const auto& value = QSharedPointer<FuncWrapper<
T, Args ...>>
::create(std::move(pFunc));
378 auto& holder = getInstance();
379 const QWriteLocker locker(&holder.mLock);
381 QMutableVectorIterator<Wrapper> iter(holder.mInstancesCreator);
382 while (iter.hasNext())
385 if (iter.value().dynamicCast<FuncWrapper<T, Args ...>>())
387 iter.setValue(value);
392 holder.mInstancesCreator << value;
396 static void setShared(
const QMetaObject& pMetaObject,
const QSharedPointer<QObject>& pObject);
static void setCreator(std::function< T(Args ...)> pFunc)
Definition: Env.h:372
static QSharedPointer< T > getShared()
Definition: Env.h:321
static int getCounter()
Definition: Env.h:354
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:314
static void init()
Definition: Env.h:300
static void setShared(const QMetaObject &pMetaObject, const QSharedPointer< QObject > &pObject)
Definition: Env.cpp:80
static T * getSingleton()
Definition: Env.h:307
#define T(v)
Definition: http_parser.cpp:237
Implementation of GeneralAuthenticate response APDUs.
Definition: CommandApdu.h:16
T createNewObject(Args &&... pArgs)