From e847ef8bbd5accd36a3287c686894418721c6798 Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Fri, 2 Nov 2018 17:29:15 -0700 Subject: handle/copyable: Implement copyable handle This is a generic handle type that holds a resource and uses RAII to call a user defined function when the resource is copied or destroyed. Tested: Built and run through unit tests. Change-Id: I3d23544b2e7c8d8c6686effc03b3b7433ea18bf5 Signed-off-by: William A. Kennington III --- src/Makefile.am | 2 + src/meson.build | 1 + src/stdplus/handle/copyable.hpp | 112 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 src/stdplus/handle/copyable.hpp (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 57af82a..d45007e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,6 +4,8 @@ lib_LTLIBRARIES = libstdplus.la libstdplus_la_SOURCES = libstdplus_la_LIBADD = $(COMMON_LIBS) +nobase_include_HEADERS += stdplus/handle/copyable.hpp + nobase_include_HEADERS += stdplus/handle/managed.hpp nobase_include_HEADERS += stdplus/signal.hpp diff --git a/src/meson.build b/src/meson.build index 6b1fea9..a6ff714 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,5 +20,6 @@ install_headers( subdir: 'stdplus') install_headers( + 'stdplus/handle/copyable.hpp', 'stdplus/handle/managed.hpp', subdir: 'stdplus/handle') diff --git a/src/stdplus/handle/copyable.hpp b/src/stdplus/handle/copyable.hpp new file mode 100644 index 0000000..df383db --- /dev/null +++ b/src/stdplus/handle/copyable.hpp @@ -0,0 +1,112 @@ +#pragma once +#include +#include +#include + +namespace stdplus +{ + +/** @brief Similar to the Managed Handle, but also allows for copying + * and performs an operation during that copy. + */ +template +struct Copyable +{ + template + class Handle : public Managed::template Handle + { + public: + using MHandle = typename Managed::template Handle; + + /** @brief Creates a handle referencing the object + * + * @param[in] maybeV - Optional object being managed + */ + template + constexpr explicit Handle(const std::optional& maybeV, Vs&&... vs) : + MHandle(std::nullopt, std::forward(vs)...) + { + reset(maybeV); + } + template + constexpr explicit Handle(const T& maybeV, Vs&&... vs) : + MHandle(std::nullopt, std::forward(vs)...) + { + reset(maybeV); + } + + /** @brief Creates a handle owning the object + * + * @param[in] maybeV - Maybe the object being managed + */ + template + constexpr explicit Handle(std::optional&& maybeV, + Vs&&... vs) noexcept : + MHandle(std::move(maybeV), std::forward(vs)...) + { + } + template + constexpr explicit Handle(T&& maybeV, Vs&&... vs) noexcept : + MHandle(std::move(maybeV), std::forward(vs)...) + { + } + + constexpr Handle(const Handle& other) : MHandle(std::nullopt, other.as) + { + reset(other.maybe_value()); + } + + constexpr Handle(Handle&& other) noexcept : MHandle(std::move(other)) + { + } + + constexpr Handle& operator=(const Handle& other) + { + if (this != &other) + { + reset(); + this->as = other.as; + reset(other.maybe_value()); + } + return *this; + } + + constexpr Handle& operator=(Handle&& other) noexcept + { + MHandle::operator=(std::move(other)); + return *this; + } + + using MHandle::reset; + + /** @brief Resets the managed value to a new value + * Takes a new reference on the value + * + * @param[in] maybeV - Maybe the new value + */ + constexpr void reset(const std::optional& maybeV) + { + if (maybeV) + { + reset(doRef(*maybeV, std::index_sequence_for())); + } + else + { + reset(std::nullopt); + } + } + constexpr void reset(const T& maybeV) + { + reset(doRef(maybeV, std::index_sequence_for())); + } + + private: + template + T doRef(const T& v, std::index_sequence) + { + return ref(v, std::get(this->as)...); + } + }; +}; + +} // namespace stdplus -- cgit v1.2.3