mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
try using ipc::string
This commit is contained in:
parent
89a4722b20
commit
a2d918dec2
@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "export.h"
|
||||
#include "def.h"
|
||||
#include "buffer.h"
|
||||
@ -23,6 +20,8 @@ struct IPC_EXPORT chan_impl {
|
||||
static handle_t connect (char const * name, unsigned mode);
|
||||
static void disconnect(handle_t h);
|
||||
|
||||
static char const * name(handle_t h);
|
||||
|
||||
static std::size_t recv_count(handle_t h);
|
||||
static bool wait_for_recv(handle_t h, std::size_t r_count, std::size_t tm);
|
||||
|
||||
@ -37,9 +36,7 @@ template <typename Flag>
|
||||
class chan_wrapper {
|
||||
private:
|
||||
using detail_t = chan_impl<Flag>;
|
||||
|
||||
handle_t h_ = nullptr;
|
||||
std::string n_;
|
||||
handle_t h_ = nullptr;
|
||||
|
||||
public:
|
||||
chan_wrapper() = default;
|
||||
@ -58,7 +55,6 @@ public:
|
||||
|
||||
void swap(chan_wrapper& rhs) {
|
||||
std::swap(h_, rhs.h_);
|
||||
n_.swap(rhs.n_);
|
||||
}
|
||||
|
||||
chan_wrapper& operator=(chan_wrapper rhs) {
|
||||
@ -67,7 +63,7 @@ public:
|
||||
}
|
||||
|
||||
char const * name() const {
|
||||
return n_.c_str();
|
||||
return detail_t::name(h_);
|
||||
}
|
||||
|
||||
handle_t handle() const {
|
||||
@ -85,7 +81,7 @@ public:
|
||||
bool connect(char const * name, unsigned mode = sender | receiver) {
|
||||
if (name == nullptr || name[0] == '\0') return false;
|
||||
this->disconnect();
|
||||
h_ = detail_t::connect((n_ = name).c_str(), mode);
|
||||
h_ = detail_t::connect(name, mode);
|
||||
return valid();
|
||||
}
|
||||
|
||||
@ -93,7 +89,6 @@ public:
|
||||
if (!valid()) return;
|
||||
detail_t::disconnect(h_);
|
||||
h_ = nullptr;
|
||||
n_.clear();
|
||||
}
|
||||
|
||||
std::size_t recv_count() const {
|
||||
|
||||
67
src/ipc.cpp
67
src/ipc.cpp
@ -84,7 +84,19 @@ struct cache_t {
|
||||
}
|
||||
};
|
||||
|
||||
auto& recv_cache() {
|
||||
struct conn_info_head {
|
||||
using acc_t = std::atomic<msg_id_t>;
|
||||
|
||||
static auto cc_acc() {
|
||||
static shm::handle acc_h("__CA_CONN__", sizeof(acc_t));
|
||||
return static_cast<acc_t*>(acc_h.get());
|
||||
}
|
||||
|
||||
ipc::string name_;
|
||||
msg_id_t cc_id_; // connection-info id
|
||||
waiter cc_waiter_, wt_waiter_, rd_waiter_;
|
||||
shm::handle acc_h_;
|
||||
|
||||
/*
|
||||
<Remarks> thread_local may have some bugs.
|
||||
See: https://sourceforge.net/p/mingw-w64/bugs/727/
|
||||
@ -94,20 +106,7 @@ auto& recv_cache() {
|
||||
https://developercommunity.visualstudio.com/content/problem/124121/thread-local-variables-fail-to-be-initialized-when.html
|
||||
https://software.intel.com/en-us/forums/intel-c-compiler/topic/684827
|
||||
*/
|
||||
static tls::pointer<mem::unordered_map<msg_id_t, cache_t>> rc;
|
||||
return *rc.create();
|
||||
}
|
||||
|
||||
struct conn_info_head {
|
||||
using acc_t = std::atomic<msg_id_t>;
|
||||
|
||||
static auto acc() {
|
||||
static shm::handle acc_h("__AC_CONN__", sizeof(acc_t));
|
||||
return static_cast<acc_t*>(acc_h.get());
|
||||
}
|
||||
|
||||
msg_id_t cc_id_; // connection-info id
|
||||
waiter cc_waiter_, wt_waiter_, rd_waiter_;
|
||||
tls::pointer<ipc::unordered_map<msg_id_t, cache_t>> recv_cache_;
|
||||
|
||||
struct simple_push {
|
||||
|
||||
@ -131,18 +130,28 @@ struct conn_info_head {
|
||||
circ::elem_array<simple_push, sizeof(shm::id_t)> msg_datas_;
|
||||
|
||||
conn_info_head(char const * name)
|
||||
: cc_id_ ((acc() == nullptr) ? 0 : acc()->fetch_add(1, std::memory_order_relaxed))
|
||||
, cc_waiter_((std::string { "__CC_CONN__" } + name).c_str())
|
||||
, wt_waiter_((std::string { "__WT_CONN__" } + name).c_str())
|
||||
, rd_waiter_((std::string { "__RD_CONN__" } + name).c_str()) {
|
||||
: name_ (name)
|
||||
, cc_id_ ((cc_acc() == nullptr) ? 0 : cc_acc()->fetch_add(1, std::memory_order_relaxed))
|
||||
, cc_waiter_(("__CC_CONN__" + name_).c_str())
|
||||
, wt_waiter_(("__WT_CONN__" + name_).c_str())
|
||||
, rd_waiter_(("__RD_CONN__" + name_).c_str())
|
||||
, acc_h_ (("__AC_CONN__" + name_).c_str(), sizeof(acc_t)) {
|
||||
}
|
||||
|
||||
auto acc() {
|
||||
return static_cast<acc_t*>(acc_h_.get());
|
||||
}
|
||||
|
||||
auto& recv_cache() {
|
||||
return *recv_cache_.create();
|
||||
}
|
||||
|
||||
static shm::id_t apply_storage(msg_id_t msg_id, std::size_t size) {
|
||||
return shm::acquire(("__ST_CONN__" + std::to_string(msg_id)).c_str(), size, shm::create);
|
||||
return shm::acquire(("__ST_CONN__" + ipc::to_string(msg_id)).c_str(), size, shm::create);
|
||||
}
|
||||
|
||||
static shm::id_t apply_storage(msg_id_t msg_id) {
|
||||
return shm::acquire(("__ST_CONN__" + std::to_string(msg_id)).c_str(), 0, shm::open);
|
||||
return shm::acquire(("__ST_CONN__" + ipc::to_string(msg_id)).c_str(), 0, shm::open);
|
||||
}
|
||||
|
||||
void store(shm::id_t dat) {
|
||||
@ -153,7 +162,9 @@ struct conn_info_head {
|
||||
|
||||
void clear_store() {
|
||||
msg_datas_.push([](shm::id_t * id) {
|
||||
if (*id != nullptr) shm::remove(*id);
|
||||
if (*id == nullptr) return;
|
||||
shm::remove(*id);
|
||||
(*id) = nullptr;
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -189,8 +200,8 @@ struct queue_generator {
|
||||
conn_info_t(char const * name)
|
||||
: conn_info_head(name)
|
||||
, que_(("__QU_CONN__" +
|
||||
std::to_string(DataSize ) + "__" +
|
||||
std::to_string(AlignSize) + "__" + name).c_str()) {
|
||||
ipc::to_string(DataSize) + "__" +
|
||||
ipc::to_string(AlignSize) + "__" + name).c_str()) {
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -345,7 +356,7 @@ static buff_t recv(ipc::handle_t h, std::size_t tm) {
|
||||
if (que->connect()) { // wouldn't connect twice
|
||||
info_of(h)->cc_waiter_.broadcast();
|
||||
}
|
||||
auto& rc = recv_cache();
|
||||
auto& rc = info_of(h)->recv_cache();
|
||||
while (1) {
|
||||
// pop a new message
|
||||
typename queue_t::value_t msg;
|
||||
@ -430,6 +441,12 @@ void chan_impl<Flag>::disconnect(ipc::handle_t h) {
|
||||
detail_impl<policy_t<Flag>>::disconnect(h);
|
||||
}
|
||||
|
||||
template <typename Flag>
|
||||
char const * chan_impl<Flag>::name(ipc::handle_t h) {
|
||||
auto info = detail_impl<policy_t<Flag>>::info_of(h);
|
||||
return (info == nullptr) ? nullptr : info->name_.c_str();
|
||||
}
|
||||
|
||||
template <typename Flag>
|
||||
std::size_t chan_impl<Flag>::recv_count(ipc::handle_t h) {
|
||||
return detail_impl<policy_t<Flag>>::recv_count(h);
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include "def.h"
|
||||
|
||||
@ -28,13 +29,42 @@ using sync_pool_alloc = mem::detail::pool_alloc<sync_fixed>;
|
||||
template <typename T>
|
||||
using allocator = allocator_wrapper<T, sync_pool_alloc>;
|
||||
|
||||
} // namespace mem
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char const * pf(int) { return "%d" ; }
|
||||
constexpr char const * pf(long) { return "%ld" ; }
|
||||
constexpr char const * pf(long long) { return "%lld"; }
|
||||
constexpr char const * pf(unsigned int) { return "%u" ; }
|
||||
constexpr char const * pf(unsigned long) { return "%lu" ; }
|
||||
constexpr char const * pf(unsigned long long) { return "%llu"; }
|
||||
constexpr char const * pf(float) { return "%f" ; }
|
||||
constexpr char const * pf(double) { return "%f" ; }
|
||||
constexpr char const * pf(long double) { return "%Lf" ; }
|
||||
|
||||
} // internal-linkage
|
||||
|
||||
template <typename Key, typename T>
|
||||
using unordered_map = std::unordered_map<
|
||||
Key, T, std::hash<Key>, std::equal_to<Key>, allocator<std::pair<const Key, T>>
|
||||
Key, T, std::hash<Key>, std::equal_to<Key>, ipc::mem::allocator<std::pair<const Key, T>>
|
||||
>;
|
||||
|
||||
using string = std::basic_string<
|
||||
char, std::char_traits<char>, ipc::mem::allocator<char>
|
||||
>;
|
||||
|
||||
using wstring = std::basic_string<
|
||||
wchar_t, std::char_traits<wchar_t>, ipc::mem::allocator<wchar_t>
|
||||
>;
|
||||
|
||||
template <typename T>
|
||||
using vector = std::vector<T, allocator<T>>;
|
||||
ipc::string to_string(T val) {
|
||||
char buf[std::numeric_limits<T>::digits10 + 1] {};
|
||||
if (std::snprintf(buf, sizeof(buf), pf(val), val) > 0) {
|
||||
return buf;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace mem
|
||||
} // namespace ipc
|
||||
|
||||
@ -36,6 +36,7 @@ public:
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef AllocP alloc_policy;
|
||||
|
||||
private:
|
||||
@ -103,8 +104,13 @@ public:
|
||||
template <class AllocP>
|
||||
class allocator_wrapper<void, AllocP> {
|
||||
public:
|
||||
typedef void value_type;
|
||||
typedef AllocP alloc_policy;
|
||||
// type definitions
|
||||
typedef void value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef AllocP alloc_policy;
|
||||
};
|
||||
|
||||
template <typename T, typename U, class AllocP>
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
#include "log.h"
|
||||
#include "pool_alloc.h"
|
||||
|
||||
#include "memory/resource.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct info_t {
|
||||
@ -27,7 +29,7 @@ struct id_info_t {
|
||||
int fd_ = -1;
|
||||
void* mem_ = nullptr;
|
||||
std::size_t size_ = 0;
|
||||
std::string name_;
|
||||
ipc::string name_;
|
||||
};
|
||||
|
||||
constexpr std::size_t calc_size(std::size_t size) {
|
||||
@ -48,7 +50,7 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) {
|
||||
ipc::error("fail acquire: name is empty\n");
|
||||
return nullptr;
|
||||
}
|
||||
std::string op_name = std::string{"__IPC_SHM__"} + name;
|
||||
ipc::string op_name = ipc::string{"__IPC_SHM__"} + name;
|
||||
// Open the object for read-write access.
|
||||
int flag = O_RDWR;
|
||||
switch (mode) {
|
||||
@ -163,7 +165,7 @@ void remove(char const * name) {
|
||||
ipc::error("fail remove: name is empty\n");
|
||||
return;
|
||||
}
|
||||
::shm_unlink((std::string{"__IPC_SHM__"} + name).c_str());
|
||||
::shm_unlink((ipc::string{"__IPC_SHM__"} + name).c_str());
|
||||
}
|
||||
|
||||
} // namespace shm
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "pool_alloc.h"
|
||||
|
||||
#include "platform/to_tchar.h"
|
||||
#include "memory/resource.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -30,7 +31,7 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) {
|
||||
return nullptr;
|
||||
}
|
||||
HANDLE h;
|
||||
auto fmt_name = ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name);
|
||||
auto fmt_name = ipc::detail::to_tchar(ipc::string{"__IPC_SHM__"} + name);
|
||||
// Opens a named file mapping object.
|
||||
if (mode == open) {
|
||||
h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, fmt_name.c_str());
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "concept.h"
|
||||
|
||||
#include "platform/detail.h"
|
||||
#include "memory/resource.h"
|
||||
|
||||
namespace ipc::detail {
|
||||
|
||||
@ -33,13 +34,18 @@ using IsSameChar = ipc::Requires<is_same_char<T, S>::value, R>;
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T = TCHAR>
|
||||
constexpr auto to_tchar(std::string && str) -> IsSameChar<T, std::string, std::string &&> {
|
||||
constexpr auto to_tchar(ipc::string && str) -> IsSameChar<T, ipc::string, ipc::string &&> {
|
||||
return std::move(str);
|
||||
}
|
||||
|
||||
template <typename T = TCHAR>
|
||||
constexpr auto to_tchar(std::string && str) -> IsSameChar<T, std::wstring> {
|
||||
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>{}.from_bytes(std::move(str));
|
||||
constexpr auto to_tchar(ipc::string && str) -> IsSameChar<T, ipc::wstring> {
|
||||
return std::wstring_convert<
|
||||
std::codecvt_utf8_utf16<wchar_t>,
|
||||
wchar_t,
|
||||
ipc::mem::allocator<wchar_t>,
|
||||
ipc::mem::allocator<char>
|
||||
>{}.from_bytes(std::move(str));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -49,7 +55,12 @@ inline auto to_tchar(T* dst, char const * src, std::size_t size) -> IsSameChar<T
|
||||
|
||||
template <typename T>
|
||||
inline auto to_tchar(T* dst, char const * src, std::size_t size) -> IsSameChar<T, wchar_t, void> {
|
||||
auto wstr = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>{}.from_bytes(src, src + size);
|
||||
auto wstr = std::wstring_convert<
|
||||
std::codecvt_utf8_utf16<wchar_t>,
|
||||
wchar_t,
|
||||
ipc::mem::allocator<wchar_t>,
|
||||
ipc::mem::allocator<char>
|
||||
>{}.from_bytes(src, src + size);
|
||||
std::memcpy(dst, wstr.data(), (ipc::detail::min)(wstr.size(), size));
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "log.h"
|
||||
|
||||
#include "platform/detail.h"
|
||||
#include "memory/resource.h"
|
||||
|
||||
namespace ipc {
|
||||
namespace detail {
|
||||
@ -209,13 +210,13 @@ class waiter_helper {
|
||||
long counter_ = 0;
|
||||
|
||||
public:
|
||||
using handle_t = std::tuple<std::string, sem_helper::handle_t, sem_helper::handle_t>;
|
||||
using handle_t = std::tuple<ipc::string, sem_helper::handle_t, sem_helper::handle_t>;
|
||||
|
||||
static handle_t invalid() noexcept {
|
||||
return std::make_tuple(std::string{}, sem_helper::invalid(), sem_helper::invalid());
|
||||
return std::make_tuple(ipc::string{}, sem_helper::invalid(), sem_helper::invalid());
|
||||
}
|
||||
|
||||
handle_t open_h(std::string && name) {
|
||||
handle_t open_h(ipc::string && name) {
|
||||
auto sem = sem_helper::open(("__WAITER_HELPER_SEM__" + name).c_str(), 0);
|
||||
if (sem == sem_helper::invalid()) {
|
||||
return invalid();
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "platform/to_tchar.h"
|
||||
#include "platform/detail.h"
|
||||
#include "memory/resource.h"
|
||||
|
||||
namespace ipc {
|
||||
namespace detail {
|
||||
@ -22,7 +23,7 @@ class semaphore {
|
||||
public:
|
||||
static void remove(char const * /*name*/) {}
|
||||
|
||||
bool open(std::string && name, long count = 0, long limit = LONG_MAX) {
|
||||
bool open(ipc::string && name, long count = 0, long limit = LONG_MAX) {
|
||||
h_ = ::CreateSemaphore(NULL, count, limit, ipc::detail::to_tchar(std::move(name)).c_str());
|
||||
if (h_ == NULL) {
|
||||
ipc::error("fail CreateSemaphore[%lu]: %s\n", ::GetLastError(), name.c_str());
|
||||
@ -62,7 +63,7 @@ class mutex : public semaphore {
|
||||
using semaphore::post;
|
||||
|
||||
public:
|
||||
bool open(std::string && name) {
|
||||
bool open(ipc::string && name) {
|
||||
return semaphore::open(std::move(name), 1, 1);
|
||||
}
|
||||
|
||||
@ -87,12 +88,12 @@ public:
|
||||
}
|
||||
|
||||
static void remove(char const * name) {
|
||||
semaphore::remove((std::string{ "__COND_HAN__" } + name).c_str());
|
||||
semaphore::remove((std::string{ "__COND_SEM__" } + name).c_str());
|
||||
mutex ::remove((std::string{ "__COND_MTX__" } + name).c_str());
|
||||
semaphore::remove((ipc::string{ "__COND_HAN__" } + name).c_str());
|
||||
semaphore::remove((ipc::string{ "__COND_SEM__" } + name).c_str());
|
||||
mutex ::remove((ipc::string{ "__COND_MTX__" } + name).c_str());
|
||||
}
|
||||
|
||||
bool open(std::string const & name, std::atomic<unsigned> * waiting, long * counter) {
|
||||
bool open(ipc::string const & name, std::atomic<unsigned> * waiting, long * counter) {
|
||||
if (lock_ .open("__COND_MTX__" + name) &&
|
||||
sema_ .open("__COND_SEM__" + name) &&
|
||||
handshake_.open("__COND_HAN__" + name)) {
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
#include "shm.h"
|
||||
|
||||
#include "memory/resource.h"
|
||||
#include "platform/detail.h"
|
||||
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || \
|
||||
defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
|
||||
@ -26,12 +27,12 @@ class condition_impl : public ipc::detail::condition {
|
||||
public:
|
||||
static void remove(char const * name) {
|
||||
ipc::detail::condition::remove(name);
|
||||
std::string n = name;
|
||||
ipc::string n = name;
|
||||
ipc::shm::remove((n + "__COND_CNT__" ).c_str());
|
||||
ipc::shm::remove((n + "__COND_WAIT__").c_str());
|
||||
}
|
||||
|
||||
bool open(std::string const & name) {
|
||||
bool open(ipc::string const & name) {
|
||||
if (wait_h_.acquire((name + "__COND_WAIT__").c_str(), sizeof(std::atomic<unsigned>)) &&
|
||||
cnt_h_ .acquire((name + "__COND_CNT__" ).c_str(), sizeof(long))) {
|
||||
return ipc::detail::condition::open(name,
|
||||
@ -129,7 +130,7 @@ public:
|
||||
class semaphore_impl {
|
||||
sem_helper::handle_t h_;
|
||||
ipc::shm::handle opened_; // std::atomic<unsigned>
|
||||
std::string name_;
|
||||
ipc::string name_;
|
||||
|
||||
auto cnt() {
|
||||
return static_cast<std::atomic<unsigned>*>(opened_.get());
|
||||
@ -137,8 +138,8 @@ class semaphore_impl {
|
||||
|
||||
public:
|
||||
static void remove(char const * name) {
|
||||
sem_helper::destroy((std::string{ "__SEMAPHORE_IMPL_SEM__" } + name).c_str());
|
||||
ipc::shm::remove ((std::string{ "__SEMAPHORE_IMPL_CNT__" } + name).c_str());
|
||||
sem_helper::destroy((ipc::string{ "__SEMAPHORE_IMPL_SEM__" } + name).c_str());
|
||||
ipc::shm::remove ((ipc::string{ "__SEMAPHORE_IMPL_CNT__" } + name).c_str());
|
||||
}
|
||||
|
||||
bool open(char const * name, long count) {
|
||||
@ -269,11 +270,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
if (!shm_.acquire((std::string{ "__SHM_WAITER__" } + name).c_str(), sizeof(waiter_t))) {
|
||||
if (!shm_.acquire((ipc::string{ "__SHM_WAITER__" } + name).c_str(), sizeof(waiter_t))) {
|
||||
return false;
|
||||
}
|
||||
attach(static_cast<waiter_t*>(shm_.get()));
|
||||
return detail::waiter_wrapper::open((std::string{ "__IMP_WAITER__" } + name).c_str());
|
||||
return detail::waiter_wrapper::open((ipc::string{ "__IMP_WAITER__" } + name).c_str());
|
||||
}
|
||||
|
||||
void close() {
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "pimpl.h"
|
||||
#include "memory/resource.h"
|
||||
|
||||
namespace ipc {
|
||||
namespace shm {
|
||||
@ -13,7 +14,7 @@ public:
|
||||
shm::id_t id_ = nullptr;
|
||||
void* m_ = nullptr;
|
||||
|
||||
std::string n_;
|
||||
ipc::string n_;
|
||||
std::size_t s_ = 0;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user