try using ipc::string

This commit is contained in:
zhangyi 2019-06-18 19:29:58 +08:00
parent 89a4722b20
commit a2d918dec2
11 changed files with 132 additions and 66 deletions

View File

@ -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 {

View File

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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -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)) {

View File

@ -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() {

View File

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