diff --git a/build/src.pro b/build/src.pro index e29d0c8..5dbd16f 100644 --- a/build/src.pro +++ b/build/src.pro @@ -17,10 +17,12 @@ HEADERS += \ ../include/shm.h \ ../include/circ_elem_array.h \ ../include/circ_queue.h \ - ../include/ipc.h + ../include/ipc.h \ + ../include/def.h SOURCES += \ - ../src/shm.cpp + ../src/shm.cpp \ + ../src/ipc.cpp unix { diff --git a/include/circ_elem_array.h b/include/circ_elem_array.h index 3be3e9a..198a075 100644 --- a/include/circ_elem_array.h +++ b/include/circ_elem_array.h @@ -1,18 +1,14 @@ #pragma once -#include -#include #include #include #include -#include #include #include +#include "def.h" + namespace ipc { - -using byte_t = std::uint8_t; - namespace circ { struct alignas(std::max_align_t) elem_array_head { diff --git a/include/circ_queue.h b/include/circ_queue.h index c5fc6e5..71ddddd 100644 --- a/include/circ_queue.h +++ b/include/circ_queue.h @@ -6,14 +6,10 @@ #include #include +#include "def.h" #include "circ_elem_array.h" namespace ipc { - -enum : std::size_t { - error_count = std::numeric_limits::max() -}; - namespace circ { template @@ -24,6 +20,7 @@ public: private: array_t* elems_ = nullptr; typename std::result_of::type cursor_ = 0; + bool connected_ = false; public: queue(void) = default; @@ -52,19 +49,31 @@ public: std::size_t connect(void) { if (elems_ == nullptr) return error_count; - cursor_ = elems_->cursor(); + if (connected_) return error_count; + connected_ = true; return elems_->connect(); } std::size_t disconnect(void) { if (elems_ == nullptr) return error_count; + if (!connected_) return error_count; + connected_ = false; return elems_->disconnect(); } + std::size_t conn_count(void) const { + return (elems_ == nullptr) ? error_count : elems_->conn_count(); + } + + bool connected(void) const { + return connected_; + } + array_t* attach(array_t* arr) { if (arr == nullptr) return nullptr; auto old = elems_; - elems_ = arr; + elems_ = arr; + cursor_ = elems_->cursor(); return old; } @@ -75,16 +84,13 @@ public: return old; } - std::size_t conn_count(void) const { - return (elems_ == nullptr) ? error_count : elems_->conn_count(); - } - template - void push(P&&... params) { - if (elems_ == nullptr) return; + bool push(P&&... params) { + if (elems_ == nullptr) return false; auto ptr = elems_->acquire(); ::new (ptr) T { std::forward

(params)... }; elems_->commit(ptr); + return true; } T pop(void) { diff --git a/include/def.h b/include/def.h new file mode 100644 index 0000000..67b4785 --- /dev/null +++ b/include/def.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +namespace ipc { + +// types + +using byte_t = std::uint8_t; + +// constants + +enum : std::size_t { + error_count = std::numeric_limits::max(), + data_length = 16 +}; + +} // namespace ipc diff --git a/include/ipc.h b/include/ipc.h index 68a795b..dd5a4e4 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -1,9 +1,19 @@ #pragma once +#include + #include "export.h" +#include "def.h" +#include "shm.h" namespace ipc { +using shm::handle_t; +IPC_EXPORT handle_t connect (std::string const & name); +IPC_EXPORT void disconnect(handle_t h); + +IPC_EXPORT bool send(handle_t h, byte_t* data, int size); +IPC_EXPORT std::vector recv(handle_t h); } // namespace ipc diff --git a/src/ipc.cpp b/src/ipc.cpp new file mode 100644 index 0000000..5b388bf --- /dev/null +++ b/src/ipc.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include + +#include "ipc.h" +#include "circ_queue.h" + +namespace { + +using namespace ipc; + +using data_t = byte_t[data_length]; + +struct msg_t { + int remain_; + data_t data_; +}; + +using queue_t = circ::queue; +using guard_t = std::unique_ptr, void(*)(handle_t)>; + +std::unordered_map h2q__; + +queue_t* queue_of(handle_t h) { + if (h == nullptr) { + return nullptr; + } + auto it = h2q__.find(h); + if (it == h2q__.end()) { + return nullptr; + } + if (it->second.elems() == nullptr) { + return nullptr; + } + return &(it->second); +} + +} // internal-linkage + +namespace ipc { + +handle_t connect(std::string const & name) { + auto h = shm::acquire(name, sizeof(queue_t)); + if (h == nullptr) { + return nullptr; + } + guard_t h_guard { + h, [](handle_t h) { shm::release(h, sizeof(queue_t)); } + }; + auto mem = shm::open(h); + if (mem == nullptr) { + return nullptr; + } + h2q__[h].attach(static_cast(mem)); + h_guard.release(); + return h; +} + +void disconnect(handle_t h) { + auto it = h2q__.find(h); + if (it == h2q__.end()) return; + it->second.disconnect(); + shm::close(it->second.detach()); + shm::release(h, sizeof(queue_t)); + h2q__.erase(it); +} + +bool send(handle_t h, byte_t* data, int size) { + if (data == nullptr) { + return false; + } + if (size <= 0) { + return false; + } + auto queue = queue_of(h); + if (queue == nullptr) { + return false; + } + queue_t drop_box { queue->elems() }; + int offset = 0; + for (int i = 0; i < (size / static_cast(data_length)); ++i, offset += data_length) { + msg_t msg { + size - offset - static_cast(data_length), + { 0 } + }; + std::memcpy(msg.data_, data + offset, data_length); + drop_box.push(msg); + } + int remain = size - offset; + if (remain > 0) { + msg_t msg { remain - static_cast(data_length), { 0 } }; + std::memcpy(msg.data_, data + offset, static_cast(remain)); + drop_box.push(msg); + } + return true; +} + +std::vector recv(handle_t h) { + std::vector all; + auto queue = queue_of(h); + if (queue == nullptr) { + return all; + } + if (!queue->connected()) { + queue->connect(); + } + do { + auto msg = queue->pop(); + auto last_size = all.size(); + if (msg.remain_ > 0) { + all.resize(last_size + data_length); + std::memcpy(all.data() + last_size, msg.data_, data_length); + } + else { + // remain_ is minus & abs(remain_) < data_length + std::size_t remain = static_cast( + static_cast(data_length) + msg.remain_); + all.resize(last_size + remain); + std::memcpy(all.data() + last_size, msg.data_, remain); + break; + } + } while(1); + return all; +} + +} // namespace ipc diff --git a/src/platform/shm_linux.cpp b/src/platform/shm_linux.cpp index 414fab3..7d8897d 100644 --- a/src/platform/shm_linux.cpp +++ b/src/platform/shm_linux.cpp @@ -1,11 +1,11 @@ -#include "shm.h" - #include #include #include #include #include +#include "shm.h" + namespace ipc { namespace shm { diff --git a/src/platform/shm_win.cpp b/src/platform/shm_win.cpp index c5082b2..7caa421 100644 --- a/src/platform/shm_win.cpp +++ b/src/platform/shm_win.cpp @@ -1,11 +1,11 @@ -#include "shm.h" - #include #include #include #include +#include "shm.h" + namespace { template diff --git a/src/shm.cpp b/src/shm.cpp index ac694dc..f60f6ea 100644 --- a/src/shm.cpp +++ b/src/shm.cpp @@ -1,7 +1,7 @@ -#include "shm.h" - #include +#include "shm.h" + namespace ipc { namespace shm {