From ff382b0e51c05880f94d736d85846aa5fb0386a1 Mon Sep 17 00:00:00 2001 From: Moritz Martinius Date: Thu, 1 Feb 2024 21:48:04 +0100 Subject: [PATCH] Some fiddeling as a POC --- .vscode/settings.json | 84 +---------------------------- src/main.cpp | 21 ++++++++ src/shmem.hpp | 119 ++++++++++++++++++++++++++++++++++++++++++ tests/meson.build | 2 +- 4 files changed, 143 insertions(+), 83 deletions(-) create mode 100644 src/shmem.hpp diff --git a/.vscode/settings.json b/.vscode/settings.json index c86af4b..c4d4e45 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,87 +2,7 @@ "clangd.arguments": ["-background-index", "-compile-commands-dir=builddir/"], "editor.formatOnType": false, "editor.formatOnSave": true, - "files.associations": { - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "array": "cpp", - "atomic": "cpp", - "strstream": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cfenv": "cpp", - "chrono": "cpp", - "codecvt": "cpp", - "compare": "cpp", - "complex": "cpp", - "concepts": "cpp", - "condition_variable": "cpp", - "cstdint": "cpp", - "deque": "cpp", - "forward_list": "cpp", - "list": "cpp", - "map": "cpp", - "set": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "source_location": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "numbers": "cpp", - "ostream": "cpp", - "semaphore": "cpp", - "shared_mutex": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "stop_token": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp", - "csignal": "cpp", - "any": "cpp", - "regex": "cpp", - "future": "cpp", - "charconv": "cpp", - "*.ipp": "cpp" - }, "clang-tidy.buildPath": "builddir/", - "clangd.onConfigChanged": "restart",] + "clangd.onConfigChanged": "restart", + "C_Cpp.default.compileCommands": "/home/moritz/src/shmem/builddir/compile_commands.json" } diff --git a/src/main.cpp b/src/main.cpp index 187a582..905a963 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,27 @@ #include +#include +#include +#include +#include +#include + +#include "shmem.hpp" + +class foo { + public: + std::array data; +}; + int main(int, char**) { spdlog::info("shmem version {}", PROJ_VERSION); + shmem::shmem_ptr shmString("/shared_foobaz"); + + std::srand(std::time(nullptr)); + + int random_delay = 1 + std::rand() / ((RAND_MAX + 1u) / 30); + spdlog::info("Sleeping for {}s", random_delay); + std::this_thread::sleep_for(std::chrono::seconds(random_delay)); + return 0; } \ No newline at end of file diff --git a/src/shmem.hpp b/src/shmem.hpp new file mode 100644 index 0000000..829de20 --- /dev/null +++ b/src/shmem.hpp @@ -0,0 +1,119 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace shmem { + +struct meminfo { + std::array magic{'s', 'h', 'm', 'e', 'm'}; + uint64_t refcount = 0; + std::atomic_bool lock{false}; +}; + +template +class shmem_ptr { + public: + /** + * @brief Construct a new shmem ptr object using the provided file descriptor + * + * @param fd file descriptor + */ + shmem_ptr(int fd) { spdlog::error("Not implemented"); } + + /** + * @brief Constructs a shmem_ptr using the provided name and permissions. If the shared memory does not exist, it will be created. Memory must be read-write and will be created read-write. + * + * @param name shared memory identifier, max 255 chars. Usually begins with /, i.e. /somename + */ + shmem_ptr(const std::string& name) + : mFd(shm_open(name.c_str(), O_RDWR | O_CREAT, 0660)), mName(name) { + spdlog::info("ctor"); + if (mFd <= 0) { + spdlog::critical("Bad alloc: {}", strerror(mFd)); + throw std::bad_alloc(); + } + int ret = ftruncate(mFd, mSize); + if (ret < 0) { + spdlog::critical("Error resizing shared memory: {}", strerror(ret)); + throw std::bad_alloc(); + } + + void* mShmPtr = mmap(nullptr, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, 0); + if (mShmPtr == MAP_FAILED) { + spdlog::critical("Can't map shared memory: {}", strerror(ret)); + throw std::bad_alloc(); + } + + // the fun begins + mMeminfo = reinterpret_cast(mShmPtr); + void* rawTPtr = mMeminfo + sizeof(meminfo); + mPtr = reinterpret_cast(rawTPtr); + + if (strncmp("shmem", mMeminfo->magic.data(), 5) != 0) { + spdlog::info("Creating fresh mem info"); + meminfo freshMemInfo{}; + memcpy(mMeminfo, &freshMemInfo, sizeof(meminfo)); + } + // mutex start + while ((mMeminfo->lock.load(std::memory_order_acquire))) + ; + mMeminfo->lock.store(true, std::memory_order_release); + ++mMeminfo->refcount; + spdlog::info("Refcount is {}", mMeminfo->refcount); + mMeminfo->lock.store(false, std::memory_order_release); + }; + + shmem_ptr(const shmem_ptr&) { spdlog::error("Not implemented"); } + + shmem_ptr& operator=(const shmem_ptr&) { spdlog::error("Not implemented"); } + + shmem_ptr(const shmem_ptr&&) { spdlog::error("Not implemented"); } + + shmem_ptr& operator=(shmem_ptr&&) { spdlog::error("Not implemented"); } + + ~shmem_ptr() { + spdlog::info("dtor"); + // mutex start + while ((mMeminfo->lock.load(std::memory_order_acquire))) + ; + mMeminfo->lock.store(true, std::memory_order_release); + //mMeminfo->refcount = -3; + --mMeminfo->refcount; + spdlog::info("Refcount is {}", mMeminfo->refcount); + if (0 == mMeminfo->refcount) { + munmap(mShmPtr, mSize); + auto ret = shm_unlink(mName.c_str()); + if (-1 == ret) { + spdlog::error("Failed unlinking shared memory, nothing we can do about it..."); + } + } else { + mMeminfo->lock.store(false, std::memory_order_release); + munmap(mShmPtr, mSize); + } + } + + private: + void* mShmPtr{nullptr}; + T* mPtr{nullptr}; + size_t mSize{sizeof(meminfo) + sizeof(T)}; + int mFd{0}; + struct meminfo* mMeminfo{nullptr}; + std::string mName = ""; +}; + +template +shmem_ptr make_shmem(Args&&... args) {} + +} // namespace shmem \ No newline at end of file diff --git a/tests/meson.build b/tests/meson.build index 2b4da13..b97669c 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -6,7 +6,7 @@ foreach test : tests executable(test.get(1), sources: test.get(2), include_directories: incdir, - dependencies: [gtest_dep, usb_dep, log_dep, pangocairo_dep, cli11_dep] + dependencies: [gtest_dep, log_dep] ) ) endforeach \ No newline at end of file