// 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; } void swap(SharedObject& other) BOOST_NOEXCEPT_OR_NOTHROW { using std::swap; swap(m_shmem, other.m_shmem); swap(m_destruct, other.m_destruct); } SharedObject(const SharedObject&) = delete; ~SharedObject() { if (m_destruct && ptr()) { ptr()->~T(); } } 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; }; 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); } } // namespace std