UI: IocContainer is non-intrusive.

This commit is contained in:
Nodir Temirkhodjaev 2021-06-01 12:49:21 +03:00
parent c28e626dbd
commit e0748c4ee9
11 changed files with 125 additions and 92 deletions

View File

@ -5,16 +5,16 @@
#include <googletest.h>
#include <util/ioc/ioccontainer.h>
#include <util/ioc/iocobject.h>
#include <util/ioc/iocservice.h>
namespace IocTest {
class A : public IocObject
class A : public IocService
{
public:
void setUp() override
{
IocObject::setUp();
IocService::setUp();
setIsA(true);
}
@ -37,12 +37,12 @@ public:
MOCK_METHOD1(setIsA, void(bool v));
};
class B : public IocObject
class B : public IocService
{
public:
void setUp() override
{
IocObject::setUp();
IocService::setUp();
IoC()->setUpDependency<A>();
}
};
@ -82,10 +82,10 @@ TEST_F(IocContainerTest, insert)
IocContainer container;
auto a2 = new IocTest::A2();
container.insert<IocTest::A>(a2);
container.setService<IocTest::A>(a2);
IocTest::B b;
container.insert<IocTest::B>(b);
container.setService<IocTest::B>(b);
ASSERT_EQ(container.resolve<IocTest::A>(), a2);
ASSERT_TRUE(container.pinToThread());
@ -97,7 +97,7 @@ TEST_F(IocContainerTest, setUp)
IocContainer container;
auto a2 = new IocTest::A2();
container.insert<IocTest::A>(a2);
container.setService<IocTest::A>(a2);
ASSERT_FALSE(a2->isA());
container.setUpAll();
@ -115,10 +115,10 @@ TEST_F(IocContainerTest, mockSetUp)
ASSERT_TRUE(container.pinToThread());
NiceMock<IocTest::MockA> mockA;
container.insert<IocTest::A>(&mockA);
container.setService<IocTest::A>(&mockA);
auto b = new IocTest::B();
container.insert<IocTest::B>(b);
container.setService<IocTest::B>(b);
EXPECT_CALL(mockA, setIsA(true)).Times(1);
container.setUpAll();
@ -127,7 +127,7 @@ TEST_F(IocContainerTest, mockSetUp)
EXPECT_CALL(mockA, tearDown()).Times(1);
container.tearDownAll();
const int containerSize = container.objects().size();
container.insert<IocTest::A>(nullptr);
ASSERT_EQ(container.objects().size(), containerSize);
const int containerSize = container.size();
container.remove<IocTest::A>();
ASSERT_EQ(container.size(), containerSize);
}

View File

@ -275,7 +275,7 @@ HEADERS += \
util/ini/mapsettings.h \
util/ini/settings.h \
util/ioc/ioccontainer.h \
util/ioc/iocobject.h \
util/ioc/iocservice.h \
util/json/jsonutil.h \
util/json/mapwrapper.h \
util/logger.h \

View File

@ -5,7 +5,6 @@
#include <QVariant>
#include "../util/classhelpers.h"
#include "../util/ioc/iocobject.h"
#include "control.h"
QT_FORWARD_DECLARE_CLASS(QLocalServer)
@ -17,7 +16,7 @@ class FortManager;
class FortSettings;
class RpcManager;
class ControlManager : public QObject, public IocObject
class ControlManager : public QObject
{
Q_OBJECT

View File

@ -4,7 +4,6 @@
#include <QObject>
#include "util/classhelpers.h"
#include "util/ioc/iocobject.h"
class AppInfoCache;
class AppInfoManager;
@ -34,7 +33,7 @@ class UserSettings;
class ZoneListModel;
class ZonesWindow;
class FortManager : public QObject, public IocObject
class FortManager : public QObject
{
Q_OBJECT

View File

@ -2,12 +2,11 @@
#define FORTSETTINGS_H
#include "util/ini/settings.h"
#include "util/ioc/iocobject.h"
class EnvManager;
class FirewallConf;
class FortSettings : public Settings, public IocObject
class FortSettings : public Settings
{
Q_OBJECT

View File

@ -4,9 +4,7 @@
#include <QHash>
#include <QObject>
#include "ioc/iocobject.h"
class EnvManager : public QObject, public IocObject
class EnvManager : public QObject
{
Q_OBJECT

View File

@ -5,7 +5,7 @@
#define WIN32_LEAN_AND_MEAN
#include <qt_windows.h>
#include "iocobject.h"
#include "iocservice.h"
namespace {
@ -20,10 +20,8 @@ IocContainer::~IocContainer()
{
tearDownAll();
for (IocObject *obj : qAsConst(m_objects)) {
if (obj && obj->autoDelete()) {
delete obj;
}
for (int i = 0; i < m_size; ++i) {
autoDelete(i);
}
if (g_tlsIndex != -1) {
@ -32,18 +30,23 @@ IocContainer::~IocContainer()
}
}
void IocContainer::insertObject(int typeId, IocObject *obj, bool autoDelete)
void IocContainer::setObject(int typeId, IocObject *obj, quint8 flags)
{
const int newSize = typeId + 1;
if (newSize > m_objects.size()) {
if (newSize > m_size) {
if (newSize >= IOC_MAX_SIZE) {
qCritical() << "IoC Container size error" << IOC_MAX_SIZE << newSize;
Q_UNREACHABLE();
}
m_size = newSize;
m_objects.resize(newSize);
m_objectFlags.resize(newSize);
}
m_objects[typeId] = obj;
if (obj) {
obj->setAutoDelete(autoDelete);
}
Q_ASSERT(obj || flags == 0);
m_objectFlags[typeId] = flags;
}
IocObject *IocContainer::resolveObject(int typeId) const
@ -53,29 +56,52 @@ IocObject *IocContainer::resolveObject(int typeId) const
return obj;
}
IocService *IocContainer::resolveService(int typeId) const
{
return static_cast<IocService *>(resolveObject(typeId));
}
void IocContainer::setUpAll()
{
for (IocObject *obj : qAsConst(m_objects)) {
if (obj) {
setUp(obj);
}
for (int i = 0; i < m_size; ++i) {
setUp(i);
}
}
void IocContainer::tearDownAll()
{
for (IocObject *obj : qAsConst(m_objects)) {
if (obj) {
obj->tearDown();
}
for (int i = 0; i < m_size; ++i) {
tearDown(i);
}
}
void IocContainer::setUp(IocObject *obj)
void IocContainer::setUp(int typeId)
{
if (!obj->wasSetUp()) {
obj->setUp();
}
const quint8 flags = m_objectFlags[typeId];
if ((flags & (IsService | WasSetUp)) != IsService)
return;
m_objectFlags[typeId] = (flags | WasSetUp);
resolveService(typeId)->setUp();
}
void IocContainer::tearDown(int typeId)
{
const quint8 flags = m_objectFlags[typeId];
if (!(flags & IsService))
return;
resolveService(typeId)->tearDown();
}
void IocContainer::autoDelete(int typeId)
{
const quint8 flags = m_objectFlags[typeId];
if ((flags & (AutoDelete | IsService)) != (AutoDelete | IsService))
return;
delete resolveService(typeId);
}
bool IocContainer::pinToThread()

View File

@ -2,40 +2,56 @@
#define IOCCONTAINER_H
#include <QObject>
#include <QVector>
#include <QVarLengthArray>
class IocObject;
class IocService;
using IocObject = void;
constexpr int IOC_MAX_SIZE = 32;
class IocContainer : public QObject
{
Q_OBJECT
public:
enum IocFlag : quint8 { AutoDelete = 0x01, IsService = 0x02, WasSetUp = 0x04 };
explicit IocContainer(QObject *parent = nullptr);
~IocContainer() override;
const QVector<IocObject *> &objects() const { return m_objects; }
const int size() const { return m_size; }
template<class T>
void put(T *obj)
void set(T &obj)
{
QObject *qObj = qobject_cast<QObject *>(obj);
Q_ASSERT(qObj);
qObj->setParent(this);
insert(obj);
setObject(getTypeId<T>(), &obj);
}
template<class T>
void insert(T *obj)
void set(T *obj)
{
insertObject(getTypeId<T>(), obj);
setObject(getTypeId<T>(), obj, AutoDelete);
}
template<class T>
void insert(T &obj)
void remove()
{
insertObject(getTypeId<T>(), &obj, false);
setObject(getTypeId<T>(), nullptr);
}
template<class T>
void setService(T &obj)
{
Q_ASSERT(static_cast<IocService *>(&obj));
setObject(getTypeId<T>(), &obj, IsService);
}
template<class T>
void setService(T *obj)
{
Q_ASSERT(static_cast<IocService *>(obj));
setObject(getTypeId<T>(), obj, AutoDelete | IsService);
}
template<class T>
@ -50,11 +66,9 @@ public:
template<class T>
void setUpDependency()
{
setUp(resolve<T>());
setUp(getTypeId<T>());
}
void setUp(IocObject *obj);
bool pinToThread();
static IocContainer *getPinned();
@ -62,18 +76,26 @@ public:
template<class T>
static int getTypeId()
{
static int typeId = getNextTypeId();
static const int typeId = getNextTypeId();
return typeId;
}
private:
void insertObject(int typeId, IocObject *obj, bool autoDelete = true);
void setObject(int typeId, IocObject *obj, quint8 flags = 0);
IocObject *resolveObject(int typeId) const;
IocService *resolveService(int typeId) const;
void setUp(int typeId);
void tearDown(int typeId);
void autoDelete(int typeId);
static int getNextTypeId();
private:
QVector<IocObject *> m_objects;
int m_size = 0;
QVarLengthArray<IocObject *, IOC_MAX_SIZE> m_objects;
QVarLengthArray<quint8, IOC_MAX_SIZE> m_objectFlags;
};
template<class T>

View File

@ -1,24 +0,0 @@
#ifndef IOCOBJECT_H
#define IOCOBJECT_H
class IocObject
{
public:
explicit IocObject() : m_autoDelete(true), m_wasSetUp(false) { }
virtual ~IocObject() = default;
virtual void setUp() { setWasSetUp(true); }
virtual void tearDown() { }
bool autoDelete() const { return m_autoDelete; }
void setAutoDelete(bool v) { m_autoDelete = v; }
bool wasSetUp() const { return m_wasSetUp; }
void setWasSetUp(bool v) { m_wasSetUp = v; }
private:
bool m_autoDelete : 1;
bool m_wasSetUp : 1;
};
#endif // IOCOBJECT_H

View File

@ -0,0 +1,14 @@
#ifndef IOCSERVICE_H
#define IOCSERVICE_H
class IocService
{
public:
explicit IocService() = default;
virtual ~IocService() = default;
virtual void setUp() { }
virtual void tearDown() { }
};
#endif // IOCSERVICE_H

View File

@ -121,10 +121,10 @@ int main(int argc, char *argv[])
// Setup IoC Container
IocContainer ioc;
ioc.pinToThread();
ioc.insert<FortSettings>(settings);
ioc.insert<EnvManager>(envManager);
ioc.insert<ControlManager>(controlManager);
ioc.insert<FortManager>(fortManager);
ioc.set<FortSettings>(settings);
ioc.set<EnvManager>(envManager);
ioc.set<ControlManager>(controlManager);
ioc.set<FortManager>(fortManager);
// Check running instance
if (!fortManager.checkRunningInstance())