mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
modify producer-consumer policy flag
This commit is contained in:
parent
bb21429d0d
commit
e86d3e10e1
@ -9,7 +9,7 @@ A high-performance inter-process communication using shared memory on Linux/Wind
|
|||||||
* 除STL外,无其他依赖
|
* 除STL外,无其他依赖
|
||||||
* 无锁(lock-free)或轻量级spin-lock
|
* 无锁(lock-free)或轻量级spin-lock
|
||||||
* 底层数据结构为循环数组(circular array)
|
* 底层数据结构为循环数组(circular array)
|
||||||
* `ipc::route`支持单生产多消费,`ipc::channel`支持多生产多消费
|
* `ipc::route`支持单写多读,`ipc::channel`支持多写多读
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
@ -13,8 +13,7 @@ DESTDIR = ../output
|
|||||||
-Wno-attributes \
|
-Wno-attributes \
|
||||||
-Wno-missing-field-initializers \
|
-Wno-missing-field-initializers \
|
||||||
-Wno-unused-variable \
|
-Wno-unused-variable \
|
||||||
-Wno-unused-function \
|
-Wno-unused-function
|
||||||
-Wno-class-memaccess
|
|
||||||
|
|
||||||
INCLUDEPATH += \
|
INCLUDEPATH += \
|
||||||
../test \
|
../test \
|
||||||
|
|||||||
@ -6,7 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
find_package(Qt5 COMPONENTS Core Test REQUIRED)
|
find_package(Qt5 COMPONENTS Core Test REQUIRED)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
add_compile_options(-Wno-attributes -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-function -Wno-class-memaccess)
|
add_compile_options(-Wno-attributes -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-function)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(../../include ../../src ../../test ../../test/capo)
|
include_directories(../../include ../../src ../../test ../../test/capo)
|
||||||
|
|||||||
@ -44,10 +44,10 @@ enum class trans { // transmission
|
|||||||
// producer-consumer policy flag
|
// producer-consumer policy flag
|
||||||
|
|
||||||
template <relat Rp, relat Rc, trans Ts>
|
template <relat Rp, relat Rc, trans Ts>
|
||||||
struct prod_cons {};
|
struct wr {};
|
||||||
|
|
||||||
// implement with multi routes
|
// implement with multi routes
|
||||||
struct prod_cons_routes {};
|
struct wr_routes {};
|
||||||
|
|
||||||
// concept helpers
|
// concept helpers
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ using handle_t = void*;
|
|||||||
using buff_t = buffer;
|
using buff_t = buffer;
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
struct IPC_EXPORT channel_detail {
|
struct IPC_EXPORT chan_impl {
|
||||||
static handle_t connect (char const * name);
|
static handle_t connect (char const * name);
|
||||||
static void disconnect(handle_t h);
|
static void disconnect(handle_t h);
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ struct IPC_EXPORT channel_detail {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct IPC_EXPORT channel_detail<prod_cons_routes> {
|
struct IPC_EXPORT chan_impl<wr_routes> {
|
||||||
static handle_t connect (char const * name);
|
static handle_t connect (char const * name);
|
||||||
static void disconnect(handle_t h);
|
static void disconnect(handle_t h);
|
||||||
|
|
||||||
@ -38,34 +38,34 @@ struct IPC_EXPORT channel_detail<prod_cons_routes> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
class channel_impl {
|
class chan_wrapper {
|
||||||
private:
|
private:
|
||||||
using detail_t = channel_detail<Flag>;
|
using detail_t = chan_impl<Flag>;
|
||||||
|
|
||||||
handle_t h_ = nullptr;
|
handle_t h_ = nullptr;
|
||||||
std::string n_;
|
std::string n_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
channel_impl() = default;
|
chan_wrapper() = default;
|
||||||
|
|
||||||
explicit channel_impl(char const * name) {
|
explicit chan_wrapper(char const * name) {
|
||||||
this->connect(name);
|
this->connect(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_impl(channel_impl&& rhs) {
|
chan_wrapper(chan_wrapper&& rhs) {
|
||||||
swap(rhs);
|
swap(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
~channel_impl() {
|
~chan_wrapper() {
|
||||||
disconnect();
|
disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(channel_impl& rhs) {
|
void swap(chan_wrapper& rhs) {
|
||||||
std::swap(h_, rhs.h_);
|
std::swap(h_, rhs.h_);
|
||||||
n_.swap(rhs.n_);
|
n_.swap(rhs.n_);
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_impl& operator=(channel_impl rhs) {
|
chan_wrapper& operator=(chan_wrapper rhs) {
|
||||||
swap(rhs);
|
swap(rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -82,8 +82,8 @@ public:
|
|||||||
return (handle() != nullptr);
|
return (handle() != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_impl clone() const {
|
chan_wrapper clone() const {
|
||||||
return channel_impl { name() };
|
return chan_wrapper { name() };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool connect(char const * name) {
|
bool connect(char const * name) {
|
||||||
@ -109,7 +109,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool wait_for_recv(char const * name, std::size_t r_count) {
|
static bool wait_for_recv(char const * name, std::size_t r_count) {
|
||||||
return channel_impl(name).wait_for_recv(r_count);
|
return chan_wrapper(name).wait_for_recv(r_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool send(void const * data, std::size_t size) {
|
bool send(void const * data, std::size_t size) {
|
||||||
@ -129,6 +129,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Flag>
|
||||||
|
using chan = chan_wrapper<Flag>;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* class route
|
* class route
|
||||||
*
|
*
|
||||||
@ -137,19 +140,19 @@ public:
|
|||||||
* would receive your sent messages.
|
* would receive your sent messages.
|
||||||
*
|
*
|
||||||
* A route could only be used in 1 to N
|
* A route could only be used in 1 to N
|
||||||
* (one producer/server/sender to multi consumers/clients/receivers)
|
* (one producer/writer to multi consumers/readers)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using route = channel_impl<ipc::prod_cons<relat::single, relat::multi, trans::broadcast>>;
|
using route = chan<ipc::wr<relat::single, relat::multi, trans::broadcast>>;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* class channel
|
* class channel
|
||||||
*
|
*
|
||||||
* You could use multi producers/servers/senders for sending messages to a channel,
|
* You could use multi producers/writers for sending messages to a channel,
|
||||||
* then all the consumers/clients/receivers which are receiving with this channel,
|
* then all the consumers/readers which are receiving with this channel,
|
||||||
* would receive your sent messages.
|
* would receive your sent messages.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using channel = channel_impl<ipc::prod_cons<relat::multi, relat::multi, trans::broadcast>>;
|
using channel = chan<ipc::wr<relat::multi, relat::multi, trans::broadcast>>;
|
||||||
|
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
|||||||
@ -88,26 +88,26 @@ struct ch_multi_routes {
|
|||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
ipc::handle_t channel_detail<prod_cons_routes>::connect(char const * /*name*/) {
|
ipc::handle_t chan_impl<wr_routes>::connect(char const * /*name*/) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void channel_detail<prod_cons_routes>::disconnect(ipc::handle_t /*h*/) {
|
void chan_impl<wr_routes>::disconnect(ipc::handle_t /*h*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t channel_detail<prod_cons_routes>::recv_count(ipc::handle_t /*h*/) {
|
std::size_t chan_impl<wr_routes>::recv_count(ipc::handle_t /*h*/) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool channel_detail<prod_cons_routes>::wait_for_recv(ipc::handle_t /*h*/, std::size_t /*r_count*/) {
|
bool chan_impl<wr_routes>::wait_for_recv(ipc::handle_t /*h*/, std::size_t /*r_count*/) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool channel_detail<prod_cons_routes>::send(ipc::handle_t /*h*/, void const * /*data*/, std::size_t /*size*/) {
|
bool chan_impl<wr_routes>::send(ipc::handle_t /*h*/, void const * /*data*/, std::size_t /*size*/) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
buff_t channel_detail<prod_cons_routes>::recv(ipc::handle_t /*h*/) {
|
buff_t chan_impl<wr_routes>::recv(ipc::handle_t /*h*/) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
src/ipc.cpp
22
src/ipc.cpp
@ -214,39 +214,39 @@ using policy_t = policy::choose<circ::elem_array, Flag>;
|
|||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
ipc::handle_t channel_detail<Flag>::connect(char const * name) {
|
ipc::handle_t chan_impl<Flag>::connect(char const * name) {
|
||||||
return detail_impl<policy_t<Flag>>::connect(name);
|
return detail_impl<policy_t<Flag>>::connect(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
void channel_detail<Flag>::disconnect(ipc::handle_t h) {
|
void chan_impl<Flag>::disconnect(ipc::handle_t h) {
|
||||||
detail_impl<policy_t<Flag>>::disconnect(h);
|
detail_impl<policy_t<Flag>>::disconnect(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
std::size_t channel_detail<Flag>::recv_count(ipc::handle_t h) {
|
std::size_t chan_impl<Flag>::recv_count(ipc::handle_t h) {
|
||||||
return detail_impl<policy_t<Flag>>::recv_count(h);
|
return detail_impl<policy_t<Flag>>::recv_count(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
bool channel_detail<Flag>::wait_for_recv(ipc::handle_t h, std::size_t r_count) {
|
bool chan_impl<Flag>::wait_for_recv(ipc::handle_t h, std::size_t r_count) {
|
||||||
return detail_impl<policy_t<Flag>>::wait_for_recv(h, r_count);
|
return detail_impl<policy_t<Flag>>::wait_for_recv(h, r_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
bool channel_detail<Flag>::send(ipc::handle_t h, void const * data, std::size_t size) {
|
bool chan_impl<Flag>::send(ipc::handle_t h, void const * data, std::size_t size) {
|
||||||
return detail_impl<policy_t<Flag>>::send(h, data, size);
|
return detail_impl<policy_t<Flag>>::send(h, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Flag>
|
template <typename Flag>
|
||||||
buff_t channel_detail<Flag>::recv(ipc::handle_t h) {
|
buff_t chan_impl<Flag>::recv(ipc::handle_t h) {
|
||||||
return detail_impl<policy_t<Flag>>::recv(h);
|
return detail_impl<policy_t<Flag>>::recv(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
template struct channel_detail<ipc::prod_cons<relat::single, relat::single, trans::unicast >>;
|
template struct chan_impl<ipc::wr<relat::single, relat::single, trans::unicast >>;
|
||||||
template struct channel_detail<ipc::prod_cons<relat::single, relat::multi , trans::unicast >>;
|
template struct chan_impl<ipc::wr<relat::single, relat::multi , trans::unicast >>;
|
||||||
template struct channel_detail<ipc::prod_cons<relat::multi , relat::multi , trans::unicast >>;
|
template struct chan_impl<ipc::wr<relat::multi , relat::multi , trans::unicast >>;
|
||||||
template struct channel_detail<ipc::prod_cons<relat::single, relat::multi , trans::broadcast>>;
|
template struct chan_impl<ipc::wr<relat::single, relat::multi , trans::broadcast>>;
|
||||||
template struct channel_detail<ipc::prod_cons<relat::multi , relat::multi , trans::broadcast>>;
|
template struct chan_impl<ipc::wr<relat::multi , relat::multi , trans::broadcast>>;
|
||||||
|
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
|||||||
@ -19,7 +19,7 @@ template <typename Flag>
|
|||||||
struct prod_cons_impl;
|
struct prod_cons_impl;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct prod_cons_impl<prod_cons<relat::single, relat::single, trans::unicast>> {
|
struct prod_cons_impl<wr<relat::single, relat::single, trans::unicast>> {
|
||||||
std::atomic<circ::u2_t> rd_; // read index
|
std::atomic<circ::u2_t> rd_; // read index
|
||||||
std::atomic<circ::u2_t> wt_; // write index
|
std::atomic<circ::u2_t> wt_; // write index
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ struct prod_cons_impl<prod_cons<relat::single, relat::single, trans::unicast>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct prod_cons_impl<prod_cons<relat::single, relat::multi , trans::unicast>>
|
struct prod_cons_impl<wr<relat::single, relat::multi , trans::unicast>>
|
||||||
: prod_cons_impl<prod_cons<relat::single, relat::single, trans::unicast>> {
|
: prod_cons_impl<wr<relat::single, relat::single, trans::unicast>> {
|
||||||
|
|
||||||
template <typename E, typename F, typename EB>
|
template <typename E, typename F, typename EB>
|
||||||
bool pop(E* /*elems*/, circ::u2_t& /*cur*/, F&& f, EB* elem_start) {
|
bool pop(E* /*elems*/, circ::u2_t& /*cur*/, F&& f, EB* elem_start) {
|
||||||
@ -86,8 +86,8 @@ struct prod_cons_impl<prod_cons<relat::single, relat::multi , trans::unicast>>
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct prod_cons_impl<prod_cons<relat::multi , relat::multi, trans::unicast>>
|
struct prod_cons_impl<wr<relat::multi , relat::multi, trans::unicast>>
|
||||||
: prod_cons_impl<prod_cons<relat::single, relat::multi, trans::unicast>> {
|
: prod_cons_impl<wr<relat::single, relat::multi, trans::unicast>> {
|
||||||
|
|
||||||
std::atomic<circ::u2_t> ct_; // commit index
|
std::atomic<circ::u2_t> ct_; // commit index
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ struct prod_cons_impl<prod_cons<relat::multi , relat::multi, trans::unicast>>
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct prod_cons_impl<prod_cons<relat::single, relat::multi, trans::broadcast>> {
|
struct prod_cons_impl<wr<relat::single, relat::multi, trans::broadcast>> {
|
||||||
std::atomic<circ::u2_t> wt_; // write index
|
std::atomic<circ::u2_t> wt_; // write index
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
#if __cplusplus >= 201703L
|
||||||
@ -180,8 +180,8 @@ struct prod_cons_impl<prod_cons<relat::single, relat::multi, trans::broadcast>>
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct prod_cons_impl<prod_cons<relat::multi , relat::multi, trans::broadcast>>
|
struct prod_cons_impl<wr<relat::multi , relat::multi, trans::broadcast>>
|
||||||
: prod_cons_impl<prod_cons<relat::single, relat::multi, trans::broadcast>> {
|
: prod_cons_impl<wr<relat::single, relat::multi, trans::broadcast>> {
|
||||||
|
|
||||||
std::atomic<circ::u2_t> ct_; // commit index
|
std::atomic<circ::u2_t> ct_; // commit index
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ struct msg_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <ipc::relat Rp, ipc::relat Rc, ipc::trans Ts>
|
template <ipc::relat Rp, ipc::relat Rc, ipc::trans Ts>
|
||||||
using pc_t = ipc::prod_cons_impl<ipc::prod_cons<Rp, Rc, Ts>>;
|
using pc_t = ipc::prod_cons_impl<ipc::wr<Rp, Rc, Ts>>;
|
||||||
|
|
||||||
template <std::size_t DataSize, typename Policy>
|
template <std::size_t DataSize, typename Policy>
|
||||||
struct ea_t : public ipc::circ::elem_array<Policy, DataSize> {
|
struct ea_t : public ipc::circ::elem_array<Policy, DataSize> {
|
||||||
@ -372,7 +372,7 @@ void Unit::test_prod_cons_performance() {
|
|||||||
void Unit::test_queue() {
|
void Unit::test_queue() {
|
||||||
using queue_t = ipc::queue<msg_t, ipc::policy::choose<
|
using queue_t = ipc::queue<msg_t, ipc::policy::choose<
|
||||||
ipc::circ::elem_array,
|
ipc::circ::elem_array,
|
||||||
ipc::prod_cons<ipc::relat::single, ipc::relat::multi, ipc::trans::broadcast>
|
ipc::wr<ipc::relat::single, ipc::relat::multi, ipc::trans::broadcast>
|
||||||
>>;
|
>>;
|
||||||
queue_t queue;
|
queue_t queue;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user