diff --git a/src/tests/UtilTest/tst_ioccontainer.h b/src/tests/UtilTest/tst_ioccontainer.h index 53564089..1cb5307a 100644 --- a/src/tests/UtilTest/tst_ioccontainer.h +++ b/src/tests/UtilTest/tst_ioccontainer.h @@ -5,16 +5,16 @@ #include #include -#include +#include 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(); } }; @@ -82,10 +82,10 @@ TEST_F(IocContainerTest, insert) IocContainer container; auto a2 = new IocTest::A2(); - container.insert(a2); + container.setService(a2); IocTest::B b; - container.insert(b); + container.setService(b); ASSERT_EQ(container.resolve(), a2); ASSERT_TRUE(container.pinToThread()); @@ -97,7 +97,7 @@ TEST_F(IocContainerTest, setUp) IocContainer container; auto a2 = new IocTest::A2(); - container.insert(a2); + container.setService(a2); ASSERT_FALSE(a2->isA()); container.setUpAll(); @@ -115,10 +115,10 @@ TEST_F(IocContainerTest, mockSetUp) ASSERT_TRUE(container.pinToThread()); NiceMock mockA; - container.insert(&mockA); + container.setService(&mockA); auto b = new IocTest::B(); - container.insert(b); + container.setService(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(nullptr); - ASSERT_EQ(container.objects().size(), containerSize); + const int containerSize = container.size(); + container.remove(); + ASSERT_EQ(container.size(), containerSize); } diff --git a/src/ui/FortFirewallUI.pro b/src/ui/FortFirewallUI.pro index aab43fdd..73d69f52 100644 --- a/src/ui/FortFirewallUI.pro +++ b/src/ui/FortFirewallUI.pro @@ -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 \ diff --git a/src/ui/control/controlmanager.h b/src/ui/control/controlmanager.h index 6588cd04..57694d43 100644 --- a/src/ui/control/controlmanager.h +++ b/src/ui/control/controlmanager.h @@ -5,7 +5,6 @@ #include #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 diff --git a/src/ui/fortmanager.h b/src/ui/fortmanager.h index 257a1f65..2686cc9c 100644 --- a/src/ui/fortmanager.h +++ b/src/ui/fortmanager.h @@ -4,7 +4,6 @@ #include #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 diff --git a/src/ui/fortsettings.h b/src/ui/fortsettings.h index 2967e1cc..05d9d3a0 100644 --- a/src/ui/fortsettings.h +++ b/src/ui/fortsettings.h @@ -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 diff --git a/src/ui/util/envmanager.h b/src/ui/util/envmanager.h index 1223415d..8739a99b 100644 --- a/src/ui/util/envmanager.h +++ b/src/ui/util/envmanager.h @@ -4,9 +4,7 @@ #include #include -#include "ioc/iocobject.h" - -class EnvManager : public QObject, public IocObject +class EnvManager : public QObject { Q_OBJECT diff --git a/src/ui/util/ioc/ioccontainer.cpp b/src/ui/util/ioc/ioccontainer.cpp index 21938ebf..157f0221 100644 --- a/src/ui/util/ioc/ioccontainer.cpp +++ b/src/ui/util/ioc/ioccontainer.cpp @@ -5,7 +5,7 @@ #define WIN32_LEAN_AND_MEAN #include -#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(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() diff --git a/src/ui/util/ioc/ioccontainer.h b/src/ui/util/ioc/ioccontainer.h index 84606b53..efa5d589 100644 --- a/src/ui/util/ioc/ioccontainer.h +++ b/src/ui/util/ioc/ioccontainer.h @@ -2,40 +2,56 @@ #define IOCCONTAINER_H #include -#include +#include -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 &objects() const { return m_objects; } + const int size() const { return m_size; } template - void put(T *obj) + void set(T &obj) { - QObject *qObj = qobject_cast(obj); - Q_ASSERT(qObj); - qObj->setParent(this); - - insert(obj); + setObject(getTypeId(), &obj); } template - void insert(T *obj) + void set(T *obj) { - insertObject(getTypeId(), obj); + setObject(getTypeId(), obj, AutoDelete); } template - void insert(T &obj) + void remove() { - insertObject(getTypeId(), &obj, false); + setObject(getTypeId(), nullptr); + } + + template + void setService(T &obj) + { + Q_ASSERT(static_cast(&obj)); + setObject(getTypeId(), &obj, IsService); + } + + template + void setService(T *obj) + { + Q_ASSERT(static_cast(obj)); + setObject(getTypeId(), obj, AutoDelete | IsService); } template @@ -50,11 +66,9 @@ public: template void setUpDependency() { - setUp(resolve()); + setUp(getTypeId()); } - void setUp(IocObject *obj); - bool pinToThread(); static IocContainer *getPinned(); @@ -62,18 +76,26 @@ public: template 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 m_objects; + int m_size = 0; + QVarLengthArray m_objects; + QVarLengthArray m_objectFlags; }; template diff --git a/src/ui/util/ioc/iocobject.h b/src/ui/util/ioc/iocobject.h deleted file mode 100644 index 831cc111..00000000 --- a/src/ui/util/ioc/iocobject.h +++ /dev/null @@ -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 diff --git a/src/ui/util/ioc/iocservice.h b/src/ui/util/ioc/iocservice.h new file mode 100644 index 00000000..ac0d5aaf --- /dev/null +++ b/src/ui/util/ioc/iocservice.h @@ -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 diff --git a/src/ui_bin/main.cpp b/src/ui_bin/main.cpp index 47c53f36..53305f44 100644 --- a/src/ui_bin/main.cpp +++ b/src/ui_bin/main.cpp @@ -121,10 +121,10 @@ int main(int argc, char *argv[]) // Setup IoC Container IocContainer ioc; ioc.pinToThread(); - ioc.insert(settings); - ioc.insert(envManager); - ioc.insert(controlManager); - ioc.insert(fortManager); + ioc.set(settings); + ioc.set(envManager); + ioc.set(controlManager); + ioc.set(fortManager); // Check running instance if (!fortManager.checkRunningInstance())