From 89f1c684d73ce275671f2cf5c312dd75af1f18d8 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Wed, 21 Oct 2020 03:39:05 +0300 Subject: add Shared{Memory,Object} classes --- include/winapi/shmem.hpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 include/winapi/shmem.hpp (limited to 'include') diff --git a/include/winapi/shmem.hpp b/include/winapi/shmem.hpp new file mode 100644 index 0000000..0fb2b76 --- /dev/null +++ b/include/winapi/shmem.hpp @@ -0,0 +1,125 @@ +// Copyright (c) 2020 Egor Tensin +// This file is part of the "winapi-common" project. +// For details, see https://github.com/egor-tensin/winapi-common. +// Distributed under the MIT License. + +#pragma once + +#include "handle.hpp" + +#include + +#include +#include +#include +#include +#include + +namespace winapi { + +class SharedMemory { +public: + static SharedMemory create(const std::string& name, std::size_t nb); + static SharedMemory open(const std::string& name); + + // VS 2013 won't generate these automatically: + SharedMemory(SharedMemory&&) BOOST_NOEXCEPT_OR_NOTHROW; + SharedMemory& operator=(SharedMemory) BOOST_NOEXCEPT_OR_NOTHROW; + void swap(SharedMemory&) BOOST_NOEXCEPT_OR_NOTHROW; + SharedMemory(const SharedMemory&) = delete; + + void* get() const { return m_addr.get(); } + void* ptr() const { return get(); } + +private: + struct Unmap { + void operator()(void*) const; + }; + + SharedMemory() = default; + + SharedMemory(Handle&& handle, void* addr) : m_handle{std::move(handle)}, m_addr{addr} {} + + Handle m_handle; + std::unique_ptr m_addr; +}; + +inline void swap(SharedMemory& a, SharedMemory& b) BOOST_NOEXCEPT_OR_NOTHROW { + a.swap(b); +} + +template +class SharedObject { +public: + typedef typename std::aligned_storage::type AlignedType; + + template + static SharedObject create(const std::string& name, Args&&... args) { + SharedObject obj{SharedMemory::create(name, sizeof(AlignedType))}; + new (obj.ptr()) T(std::forward(args)...); + obj.m_destruct = true; + return obj; + } + + static SharedObject open(const std::string& name) { + SharedObject obj{SharedMemory::open(name)}; + return obj; + } + + SharedObject(SharedObject&& other) BOOST_NOEXCEPT_OR_NOTHROW + : m_shmem{std::move(other.m_shmem)}, + m_destruct{other.m_destruct} {} + + SharedObject& operator=(SharedObject other) BOOST_NOEXCEPT_OR_NOTHROW { + swap(other); + return *this; + } + + ~SharedObject() { + if (m_destruct && ptr()) { + ptr()->~T(); + } + } + + void swap(SharedObject& other) BOOST_NOEXCEPT_OR_NOTHROW { + using std::swap; + swap(m_shmem, other.m_shmem); + swap(m_destruct, other.m_destruct); + } + + T* ptr() const { return reinterpret_cast(m_shmem.ptr()); } + T& get() const { return *ptr(); } + + T* operator->() const { return ptr(); } + T& operator*() const { return get(); } + +private: + explicit SharedObject(SharedMemory&& shmem) : m_shmem{std::move(shmem)} {} + + SharedMemory m_shmem; + // Destruct only once, no matter the number of mappings. + bool m_destruct = false; + + SharedObject(const SharedObject&) = delete; +}; + +template +inline void swap(SharedObject& a, SharedObject& b) BOOST_NOEXCEPT_OR_NOTHROW { + a.swap(b); +} + +} // namespace winapi + +namespace std { + +template <> +inline void swap(winapi::SharedMemory& a, winapi::SharedMemory& b) BOOST_NOEXCEPT_OR_NOTHROW { + a.swap(b); +} + +template +inline void swap(winapi::SharedObject& a, winapi::SharedObject& b) BOOST_NOEXCEPT_OR_NOTHROW { + a.swap(b); +} + +} // namespace std -- cgit v1.2.3