diff --git a/src/data/setting.hpp b/src/data/setting.hpp index 7068ebf7..8872ee49 100644 --- a/src/data/setting.hpp +++ b/src/data/setting.hpp @@ -7,6 +7,7 @@ #include "delegates.hpp" #include "typedefs.hpp" +#include "util/observer_handler.hpp" enum class setting_format { simple, percent }; @@ -47,9 +48,8 @@ public: if (callOnStart) { callback(value); } - return std::shared_ptr(new int(id), [this](int* id) { //-V508 - observers.erase(*id); - delete id; + return observer_handler([this, id]() { + observers.erase(id); }); } diff --git a/src/logic/scripting/lua/libs/libinput.cpp b/src/logic/scripting/lua/libs/libinput.cpp index 5299656e..cd9325d0 100644 --- a/src/logic/scripting/lua/libs/libinput.cpp +++ b/src/logic/scripting/lua/libs/libinput.cpp @@ -1,5 +1,3 @@ -#include - #include "engine/Engine.hpp" #include "frontend/hud.hpp" #include "frontend/screens/Screen.hpp" @@ -8,6 +6,7 @@ #include "io/io.hpp" #include "libgui.hpp" #include "util/stringutil.hpp" +#include "util/observer_handler.hpp" #include "window/Events.hpp" #include "window/input.hpp" #include "coders/toml.hpp" @@ -61,13 +60,13 @@ static int l_add_callback(lua::State* L) { } if (hud) { - hud->keepAlive(handler); + hud->keepAlive(std::move(handler)); return 0; } else if (lua::gettop(L) >= 3) { auto node = get_document_node(L, 3); if (auto container = std::dynamic_pointer_cast(node.node)) { - container->keepAlive(handler); + container->keepAlive(std::move(handler)); return 0; } throw std::runtime_error("owner expected to be a container"); diff --git a/src/typedefs.hpp b/src/typedefs.hpp index b3266aea..1a41fd69 100644 --- a/src/typedefs.hpp +++ b/src/typedefs.hpp @@ -4,7 +4,8 @@ #include using scriptenv = std::shared_ptr; -using observer_handler = std::shared_ptr; + +class observer_handler; /// @brief dynamic integer type (64 bit signed integer) using integer_t = int64_t; diff --git a/src/util/HandlersList.hpp b/src/util/HandlersList.hpp index 9cda6572..9f3a74b9 100644 --- a/src/util/HandlersList.hpp +++ b/src/util/HandlersList.hpp @@ -7,6 +7,7 @@ #include "delegates.hpp" #include "typedefs.hpp" +#include "util/observer_handler.hpp" namespace util { template @@ -35,13 +36,12 @@ namespace util { int id = nextid++; handlers[id] = std::move(handler); order.push_back(id); - return observer_handler(new int(id), [this](int* id) { //-V508 + return observer_handler([this, id]() { std::lock_guard lock(mutex); - handlers.erase(*id); + handlers.erase(id); order.erase( - std::remove(order.begin(), order.end(), *id), order.end() + std::remove(order.begin(), order.end(), id), order.end() ); - delete id; }); } diff --git a/src/util/ObjectsKeeper.hpp b/src/util/ObjectsKeeper.hpp index 74a5a36b..2cd079d3 100644 --- a/src/util/ObjectsKeeper.hpp +++ b/src/util/ObjectsKeeper.hpp @@ -3,20 +3,39 @@ #include #include +#include "util/observer_handler.hpp" + namespace util { /// @brief Keeps shared pointers alive until destruction class ObjectsKeeper { std::vector> ptrs; + std::vector handlers; public: + ObjectsKeeper() = default; + + ObjectsKeeper(const ObjectsKeeper&) = delete; + + ObjectsKeeper(ObjectsKeeper&& keeper) noexcept + : ptrs(std::move(keeper.ptrs)), + handlers(std::move(keeper.handlers)) { + } + + ObjectsKeeper& operator=(ObjectsKeeper&& keeper) noexcept = default; + virtual ~ObjectsKeeper() { } virtual void keepAlive(std::shared_ptr ptr) { - ptrs.push_back(ptr); + ptrs.push_back(std::move(ptr)); + } + + virtual void keepAlive(observer_handler&& ptr) { + handlers.emplace_back(std::move(ptr)); } virtual void clearKeepedObjects() { ptrs.clear(); + handlers.clear(); } }; } diff --git a/src/util/observer_handler.hpp b/src/util/observer_handler.hpp new file mode 100644 index 00000000..2a636a77 --- /dev/null +++ b/src/util/observer_handler.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include + +class observer_handler { +public: + observer_handler() = default; + + observer_handler(std::function destructor) + : destructor(std::move(destructor)) { + } + + observer_handler(const observer_handler&) = delete; + + observer_handler(observer_handler&& handler) noexcept + : destructor(std::move(handler.destructor)) { + } + + ~observer_handler() { + if (destructor) { + destructor(); + } + } + + bool operator==(std::nullptr_t) const { + return destructor == nullptr; + } + + observer_handler& operator=(const observer_handler& handler) = delete; + + observer_handler& operator=(observer_handler&& handler) noexcept { + if (destructor) { + destructor(); + } + destructor = std::move(handler.destructor); + return *this; + } +private: + std::function destructor; +};