mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
182 lines
5.8 KiB
C++
Executable File
182 lines
5.8 KiB
C++
Executable File
#include <iostream>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <memory>
|
|
#include <new>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
|
|
#include "prod_cons.h"
|
|
#include "policy.h"
|
|
#include "circ/elem_array.h"
|
|
#include "queue.h"
|
|
|
|
#include "test.h"
|
|
|
|
namespace {
|
|
|
|
struct msg_t {
|
|
int pid_;
|
|
int dat_;
|
|
|
|
msg_t() = default;
|
|
msg_t(int p, int d) : pid_(p), dat_(d) {}
|
|
};
|
|
|
|
template <ipc::relat Rp, ipc::relat Rc, ipc::trans Ts>
|
|
using queue_t = ipc::queue<msg_t, ipc::policy::choose<ipc::circ::elem_array, ipc::wr<Rp, Rc, Ts>>>;
|
|
|
|
template <ipc::relat Rp, ipc::relat Rc, ipc::trans Ts>
|
|
struct elems_t : public queue_t<Rp, Rc, Ts>::elems_t {};
|
|
|
|
bool operator==(msg_t const & m1, msg_t const & m2) noexcept {
|
|
return (m1.pid_ == m2.pid_) && (m1.dat_ == m2.dat_);
|
|
}
|
|
|
|
bool operator!=(msg_t const & m1, msg_t const & m2) noexcept {
|
|
return !(m1 == m2);
|
|
}
|
|
|
|
constexpr int LoopCount = 1000000;
|
|
constexpr int PushRetry = 1000000;
|
|
constexpr int ThreadMax = 8;
|
|
|
|
template <typename Que>
|
|
void push(Que & que, int p, int d) {
|
|
for (int n = 0; !que.push(p, d); ++n) {
|
|
ASSERT_NE(n, PushRetry);
|
|
std::this_thread::yield();
|
|
}
|
|
}
|
|
|
|
template <typename Que>
|
|
msg_t pop(Que & que) {
|
|
msg_t msg;
|
|
while (!que.pop(msg)) {
|
|
std::this_thread::yield();
|
|
}
|
|
return msg;
|
|
}
|
|
|
|
template <ipc::trans Ts>
|
|
struct quitter;
|
|
|
|
template <>
|
|
struct quitter<ipc::trans::unicast> {
|
|
template <typename Que>
|
|
static void emit(Que && que, int r_cnt) {
|
|
for (int k = 0; k < r_cnt; ++k) {
|
|
push(que, -1, -1);
|
|
}
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct quitter<ipc::trans::broadcast> {
|
|
template <typename Que>
|
|
static void emit(Que && que, int /*r_cnt*/) {
|
|
push(que, -1, -1);
|
|
}
|
|
};
|
|
|
|
template <ipc::relat Rp, ipc::relat Rc, ipc::trans Ts>
|
|
void test_sr(elems_t<Rp, Rc, Ts> && elems, int s_cnt, int r_cnt, char const * message) {
|
|
ipc_ut::sender().start(static_cast<std::size_t>(s_cnt));
|
|
ipc_ut::reader().start(static_cast<std::size_t>(r_cnt));
|
|
ipc_ut::test_stopwatch sw;
|
|
|
|
for (int k = 0; k < s_cnt; ++k) {
|
|
ipc_ut::sender() << [&elems, &sw, r_cnt, k] {
|
|
queue_t<Rp, Rc, Ts> que { &elems };
|
|
while (que.conn_count() != static_cast<std::size_t>(r_cnt)) {
|
|
std::this_thread::yield();
|
|
}
|
|
sw.start();
|
|
for (int i = 0; i < LoopCount; ++i) {
|
|
push(que, k, i);
|
|
}
|
|
};
|
|
}
|
|
for (int k = 0; k < r_cnt; ++k) {
|
|
ipc_ut::reader() << [&elems, k] {
|
|
queue_t<Rp, Rc, Ts> que { &elems };
|
|
ASSERT_TRUE(que.connect());
|
|
while (pop(que).pid_ >= 0) ;
|
|
EXPECT_TRUE(que.disconnect());
|
|
};
|
|
}
|
|
|
|
ipc_ut::sender().wait_for_done();
|
|
quitter<Ts>::emit(queue_t<Rp, Rc, Ts> { &elems }, r_cnt);
|
|
ipc_ut::reader().wait_for_done();
|
|
sw.print_elapsed(s_cnt, r_cnt, LoopCount, message);
|
|
}
|
|
|
|
} // internal-linkage
|
|
|
|
TEST(Queue, check_size) {
|
|
using el_t = elems_t<ipc::relat::single, ipc::relat::multi, ipc::trans::broadcast>;
|
|
|
|
std::cout << "cq_t::head_size = " << el_t::head_size << std::endl;
|
|
std::cout << "cq_t::data_size = " << el_t::data_size << std::endl;
|
|
std::cout << "cq_t::elem_size = " << el_t::elem_size << std::endl;
|
|
std::cout << "cq_t::block_size = " << el_t::block_size << std::endl;
|
|
|
|
EXPECT_EQ(static_cast<std::size_t>(el_t::data_size), sizeof(msg_t));
|
|
|
|
std::cout << "sizeof(elems_t<s, m, b>) = " << sizeof(el_t) << std::endl;
|
|
}
|
|
|
|
TEST(Queue, prod_cons_1v1_unicast) {
|
|
test_sr(elems_t<ipc::relat::single, ipc::relat::single, ipc::trans::unicast> {}, 1, 1, "ssu");
|
|
test_sr(elems_t<ipc::relat::single, ipc::relat::multi , ipc::trans::unicast> {}, 1, 1, "smu");
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::unicast> {}, 1, 1, "mmu");
|
|
}
|
|
|
|
TEST(Queue, prod_cons_1v1_broadcast) {
|
|
test_sr(elems_t<ipc::relat::single, ipc::relat::multi , ipc::trans::broadcast> {}, 1, 1, "smb");
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::broadcast> {}, 1, 1, "mmb");
|
|
}
|
|
|
|
TEST(Queue, prod_cons_1vN_unicast) {
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::single, ipc::relat::multi , ipc::trans::unicast> {}, 1, i, "smu");
|
|
}
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::unicast> {}, 1, i, "mmu");
|
|
}
|
|
}
|
|
|
|
TEST(Queue, prod_cons_1vN_broadcast) {
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::single, ipc::relat::multi , ipc::trans::broadcast> {}, 1, i, "smb");
|
|
}
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::broadcast> {}, 1, i, "mmb");
|
|
}
|
|
}
|
|
|
|
TEST(Queue, prod_cons_NvN_unicast) {
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::unicast> {}, 1, i, "mmu");
|
|
}
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::unicast> {}, i, 1, "mmu");
|
|
}
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::unicast> {}, i, i, "mmu");
|
|
}
|
|
}
|
|
|
|
TEST(Queue, prod_cons_NvN_broadcast) {
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::broadcast> {}, 1, i, "mmb");
|
|
}
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::broadcast> {}, i, 1, "mmb");
|
|
}
|
|
for (int i = 1; i <= ThreadMax; ++i) {
|
|
test_sr(elems_t<ipc::relat::multi , ipc::relat::multi , ipc::trans::broadcast> {}, i, i, "mmb");
|
|
}
|
|
}
|