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*;
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;

View File

@ -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<int>(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;

View File

@ -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<DWORD>(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<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) {
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 static_cast<id_t>(h);

View File

@ -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();
}