support for specified shm modes

This commit is contained in:
mutouyun 2019-03-27 22:55:36 +08:00
parent adbc187ffe
commit 10e6cca8b0
4 changed files with 50 additions and 18 deletions

View File

@ -9,7 +9,12 @@ namespace shm {
using id_t = void*; 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 * to_mem (id_t id);
IPC_EXPORT void release(id_t id, void * mem, std::size_t size); IPC_EXPORT void release(id_t id, void * mem, std::size_t size);
IPC_EXPORT void remove (char const * name); IPC_EXPORT void remove (char const * name);
@ -17,7 +22,7 @@ IPC_EXPORT void remove (char const * name);
class IPC_EXPORT handle { class IPC_EXPORT handle {
public: public:
handle(); 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(handle&& rhs);
~handle(); ~handle();
@ -29,7 +34,7 @@ public:
std::size_t size () const; std::size_t size () const;
char const * name () 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 release();
void* get() const; void* get() const;

View File

@ -40,7 +40,7 @@ inline auto& str_of(void* mem, std::size_t size) {
namespace ipc { namespace ipc {
namespace shm { 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) { if (name == nullptr || name[0] == '\0' || size == 0) {
return nullptr; return nullptr;
} }
@ -49,8 +49,22 @@ id_t acquire(char const * name, std::size_t size) {
ipc::error("name is too long!: [%d]%s\n", static_cast<int>(op_name.size()), op_name.c_str()); ipc::error("name is too long!: [%d]%s\n", static_cast<int>(op_name.size()), op_name.c_str());
return nullptr; return nullptr;
} }
int fd = ::shm_open(op_name.c_str(), O_CREAT | O_RDWR, // Open the object for read-write access.
S_IRUSR | S_IWUSR | 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_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH); S_IROTH | S_IWOTH);
if (fd == -1) { if (fd == -1) {

View File

@ -13,16 +13,29 @@
namespace ipc { namespace ipc {
namespace shm { 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) { if (name == nullptr || name[0] == '\0' || size == 0) {
return nullptr; return nullptr;
} }
HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, HANDLE h;
PAGE_READWRITE | SEC_COMMIT, auto fmt_name = ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name);
0, static_cast<DWORD>(size), // Opens a named file mapping object.
ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name).c_str()); 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<DWORD>(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) { if (h == NULL) {
ipc::error("fail CreateFileMapping[%d]: %s\n", static_cast<int>(::GetLastError()), name); ipc::error("fail CreateFileMapping/OpenFileMapping[%d]: %s\n", static_cast<int>(::GetLastError()), name);
return nullptr; return nullptr;
} }
return static_cast<id_t>(h); return static_cast<id_t>(h);

View File

@ -21,9 +21,9 @@ handle::handle()
: p_(p_->make()) { : p_(p_->make()) {
} }
handle::handle(char const * name, std::size_t size) handle::handle(char const * name, std::size_t size, unsigned mode)
: handle() { : handle() {
acquire(name, size); acquire(name, size, mode);
} }
handle::handle(handle&& rhs) handle::handle(handle&& rhs)
@ -57,10 +57,10 @@ char const * handle::name() const {
return impl(p_)->n_.c_str(); 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(); release();
impl(p_)->id_ = shm::acquire((impl(p_)->n_ = name).c_str(), 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_); impl(p_)->m_ = shm::to_mem (impl(p_)->id_);
return valid(); return valid();
} }