From 10e6cca8b08999fc3091ec130f9cdf109644fa9d Mon Sep 17 00:00:00 2001 From: mutouyun Date: Wed, 27 Mar 2019 22:55:36 +0800 Subject: [PATCH] support for specified shm modes --- include/shm.h | 11 ++++++++--- src/platform/shm_linux.cpp | 24 +++++++++++++++++++----- src/platform/shm_win.cpp | 25 +++++++++++++++++++------ src/shm.cpp | 8 ++++---- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/include/shm.h b/include/shm.h index b48ed8c..a7a0886 100644 --- a/include/shm.h +++ b/include/shm.h @@ -9,7 +9,12 @@ namespace shm { using id_t = void*; -IPC_EXPORT id_t acquire(char const * name, std::size_t size); +enum : unsigned { + create = 0x01, + open = 0x02 +}; + +IPC_EXPORT id_t acquire(char const * name, std::size_t size, unsigned mode = create | open); IPC_EXPORT void * to_mem (id_t id); IPC_EXPORT void release(id_t id, void * mem, std::size_t size); IPC_EXPORT void remove (char const * name); @@ -17,7 +22,7 @@ IPC_EXPORT void remove (char const * name); class IPC_EXPORT handle { public: handle(); - handle(char const * name, std::size_t size); + handle(char const * name, std::size_t size, unsigned mode = create | open); handle(handle&& rhs); ~handle(); @@ -29,7 +34,7 @@ public: std::size_t size () const; char const * name () const; - bool acquire(char const * name, std::size_t size); + bool acquire(char const * name, std::size_t size, unsigned mode = create | open); void release(); void* get() const; diff --git a/src/platform/shm_linux.cpp b/src/platform/shm_linux.cpp index c568c38..bd89215 100644 --- a/src/platform/shm_linux.cpp +++ b/src/platform/shm_linux.cpp @@ -40,7 +40,7 @@ inline auto& str_of(void* mem, std::size_t size) { namespace ipc { namespace shm { -id_t acquire(char const * name, std::size_t size) { +id_t acquire(char const * name, std::size_t size, unsigned mode) { if (name == nullptr || name[0] == '\0' || size == 0) { return nullptr; } @@ -49,10 +49,24 @@ id_t acquire(char const * name, std::size_t size) { ipc::error("name is too long!: [%d]%s\n", static_cast(op_name.size()), op_name.c_str()); return nullptr; } - int fd = ::shm_open(op_name.c_str(), O_CREAT | O_RDWR, - S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP | - S_IROTH | S_IWOTH); + // Open the object for read-write access. + int flag = O_RDWR; + switch (mode) { + case open: + break; + // The check for the existence of the object, + // and its creation if it does not exist, are performed atomically. + case create: + flag |= O_CREAT | O_EXCL; + break; + // Create the shared memory object if it does not exist. + default: + flag |= O_CREAT; + break; + } + int fd = ::shm_open(op_name.c_str(), flag, S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IROTH | S_IWOTH); if (fd == -1) { ipc::error("fail shm_open[%d]: %s\n", errno, name); return nullptr; diff --git a/src/platform/shm_win.cpp b/src/platform/shm_win.cpp index e3398e4..3b3cb08 100644 --- a/src/platform/shm_win.cpp +++ b/src/platform/shm_win.cpp @@ -13,16 +13,29 @@ namespace ipc { namespace shm { -id_t acquire(char const * name, std::size_t size) { +id_t acquire(char const * name, std::size_t size, unsigned mode) { if (name == nullptr || name[0] == '\0' || size == 0) { return nullptr; } - HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, - PAGE_READWRITE | SEC_COMMIT, - 0, static_cast(size), - ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name).c_str()); + HANDLE h; + auto fmt_name = ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name); + // Opens a named file mapping object. + if (mode == open) { + h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, fmt_name.c_str()); + } + // Creates or opens a named file mapping object for a specified file. + else { + h = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, + 0, static_cast(size), fmt_name.c_str()); + // If the object exists before the function call, the function returns a handle to the existing object + // (with its current size, not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS. + if ((mode == create) && (::GetLastError() == ERROR_ALREADY_EXISTS)) { + ::CloseHandle(h); + h = NULL; + } + } if (h == NULL) { - ipc::error("fail CreateFileMapping[%d]: %s\n", static_cast(::GetLastError()), name); + ipc::error("fail CreateFileMapping/OpenFileMapping[%d]: %s\n", static_cast(::GetLastError()), name); return nullptr; } return static_cast(h); diff --git a/src/shm.cpp b/src/shm.cpp index 0b5356e..efeaba6 100644 --- a/src/shm.cpp +++ b/src/shm.cpp @@ -21,9 +21,9 @@ handle::handle() : p_(p_->make()) { } -handle::handle(char const * name, std::size_t size) +handle::handle(char const * name, std::size_t size, unsigned mode) : handle() { - acquire(name, size); + acquire(name, size, mode); } handle::handle(handle&& rhs) @@ -57,10 +57,10 @@ char const * handle::name() const { return impl(p_)->n_.c_str(); } -bool handle::acquire(char const * name, std::size_t size) { +bool handle::acquire(char const * name, std::size_t size, unsigned mode) { release(); impl(p_)->id_ = shm::acquire((impl(p_)->n_ = name).c_str(), - impl(p_)->s_ = size); + impl(p_)->s_ = size, mode); impl(p_)->m_ = shm::to_mem (impl(p_)->id_); return valid(); }