Skip to content

Commit 4ca300b

Browse files
committed
Merge branch 'issue-61' into develop
2 parents ca9c5d1 + be6f16f commit 4ca300b

File tree

8 files changed

+140
-45
lines changed

8 files changed

+140
-45
lines changed

CMakeLists.txt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ if(NOT MSVC)
1313
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
1414
endif()
1515

16-
if (MSVC AND LIBIPC_USE_STATIC_CRT)
16+
if (MSVC)
1717
set(CompilerFlags
1818
CMAKE_CXX_FLAGS
1919
CMAKE_CXX_FLAGS_DEBUG
@@ -22,9 +22,17 @@ if (MSVC AND LIBIPC_USE_STATIC_CRT)
2222
CMAKE_C_FLAGS_DEBUG
2323
CMAKE_C_FLAGS_RELEASE
2424
)
25-
foreach(CompilerFlag ${CompilerFlags})
26-
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
27-
endforeach()
25+
if (LIBIPC_USE_STATIC_CRT)
26+
foreach(CompilerFlag ${CompilerFlags})
27+
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
28+
string(REPLACE "/MDd" "/MTd" ${CompilerFlag} "${${CompilerFlag}}")
29+
endforeach()
30+
else()
31+
foreach(CompilerFlag ${CompilerFlags})
32+
string(REPLACE "/MT" "/MD" ${CompilerFlag} "${${CompilerFlag}}")
33+
string(REPLACE "/MTd" "/MDd" ${CompilerFlag} "${${CompilerFlag}}")
34+
endforeach()
35+
endif()
2836
endif()
2937

3038
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
@@ -50,6 +58,7 @@ endif()
5058
if (LIBIPC_BUILD_DEMOS)
5159
add_subdirectory(demo/chat)
5260
add_subdirectory(demo/msg_que)
61+
add_subdirectory(demo/send_recv)
5362
endif()
5463

5564
install(

demo/msg_que/main.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,10 @@ int main(int argc, char ** argv) {
127127
::signal(SIGHUP , exit);
128128
#endif
129129

130-
if (std::string{ argv[1] } == mode_s__) {
130+
std::string mode {argv[1]};
131+
if (mode == mode_s__) {
131132
do_send();
132-
}
133-
else if (std::string{ argv[1] } == mode_r__) {
133+
} else if (mode == mode_r__) {
134134
do_recv();
135135
}
136136
return 0;

demo/send_recv/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
project(send_recv)
2+
3+
include_directories(
4+
${LIBIPC_PROJECT_DIR}/3rdparty)
5+
6+
file(GLOB SRC_FILES ./*.cpp)
7+
file(GLOB HEAD_FILES ./*.h)
8+
9+
add_executable(${PROJECT_NAME} ${SRC_FILES} ${HEAD_FILES})
10+
11+
target_link_libraries(${PROJECT_NAME} ipc)

demo/send_recv/main.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
#include <iostream>
3+
#include <string>
4+
#include <thread>
5+
#include <chrono>
6+
7+
#include "libipc/ipc.h"
8+
9+
namespace {
10+
11+
void do_send(int size, int interval) {
12+
ipc::channel ipc {"ipc", ipc::sender};
13+
std::string buffer(size, 'A');
14+
while (true) {
15+
std::cout << "send size: " << buffer.size() + 1 << "\n";
16+
ipc.send(buffer, 0/*tm*/);
17+
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
18+
}
19+
}
20+
21+
void do_recv(int interval) {
22+
ipc::channel ipc {"ipc", ipc::receiver};
23+
while (true) {
24+
ipc::buff_t recv;
25+
for (int k = 1; recv.empty(); ++k) {
26+
std::cout << "recv waiting... " << k << "\n";
27+
recv = ipc.recv(interval);
28+
}
29+
std::cout << "recv size: " << recv.size() << "\n";
30+
}
31+
}
32+
33+
} // namespace
34+
35+
int main(int argc, char ** argv) {
36+
if (argc < 3) return -1;
37+
std::string mode {argv[1]};
38+
if (mode == "send") {
39+
if (argc < 4) return -1;
40+
do_send(std::stoi(argv[2]) /*size*/,
41+
std::stoi(argv[3]) /*interval*/);
42+
} else if (mode == "recv") {
43+
do_recv(std::stoi(argv[2]) /*interval*/);
44+
}
45+
return 0;
46+
}

src/libipc/platform/waiter_linux.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,6 @@ class sem_helper {
223223
static bool wait(handle_t h, std::uint64_t tm = invalid_value) {
224224
if (h == invalid()) return false;
225225
switch (tm) {
226-
case 0:
227-
return true;
228226
case invalid_value:
229227
IPC_SEMAPHORE_FUNC_(sem_wait, h);
230228
default: {

src/libipc/waiter_helper.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace detail {
1313
struct waiter_helper {
1414

1515
struct wait_counter {
16-
std::atomic<unsigned> waiting_ { 0 };
16+
std::atomic<long> waiting_ { 0 };
1717
long counter_ = 0;
1818
};
1919

@@ -33,14 +33,18 @@ struct waiter_helper {
3333
auto & counter = ctrl.counter();
3434
counter.waiting_.fetch_add(1, std::memory_order_release);
3535
flags.is_waiting_.store(true, std::memory_order_relaxed);
36-
auto finally = ipc::guard([&counter, &flags] {
37-
counter.waiting_.fetch_sub(1, std::memory_order_release);
36+
auto finally = ipc::guard([&ctrl, &counter, &flags] {
37+
for (auto curr_wait = counter.waiting_.load(std::memory_order_relaxed); curr_wait > 0;) {
38+
if (counter.waiting_.compare_exchange_weak(curr_wait, curr_wait - 1, std::memory_order_acq_rel)) {
39+
break;
40+
}
41+
}
3842
flags.is_waiting_.store(false, std::memory_order_relaxed);
3943
});
4044
{
4145
IPC_UNUSED_ auto guard = ctrl.get_lock();
4246
if (!std::forward<F>(pred)()) return true;
43-
counter.counter_ += 1;
47+
counter.counter_ = counter.waiting_.load(std::memory_order_relaxed);
4448
}
4549
mtx.unlock();
4650

@@ -69,6 +73,11 @@ struct waiter_helper {
6973
return ret;
7074
}
7175

76+
template <typename Ctrl>
77+
static void clear_handshake(Ctrl & ctrl) {
78+
while (ctrl.handshake_wait(0)) ;
79+
}
80+
7281
template <typename Ctrl>
7382
static bool notify(Ctrl & ctrl) {
7483
auto & counter = ctrl.counter();
@@ -77,6 +86,7 @@ struct waiter_helper {
7786
}
7887
bool ret = true;
7988
IPC_UNUSED_ auto guard = ctrl.get_lock();
89+
clear_handshake(ctrl);
8090
if (counter.counter_ > 0) {
8191
ret = ctrl.sema_post(1);
8292
counter.counter_ -= 1;
@@ -93,12 +103,15 @@ struct waiter_helper {
93103
}
94104
bool ret = true;
95105
IPC_UNUSED_ auto guard = ctrl.get_lock();
106+
clear_handshake(ctrl);
96107
if (counter.counter_ > 0) {
97108
ret = ctrl.sema_post(counter.counter_);
109+
auto tm = default_timeout / counter.counter_;
98110
do {
99111
counter.counter_ -= 1;
100-
ret = ret && ctrl.handshake_wait(default_timeout);
112+
ret = ret && ctrl.handshake_wait(tm);
101113
} while (counter.counter_ > 0);
114+
counter.waiting_.store(0, std::memory_order_release);
102115
}
103116
return ret;
104117
}
@@ -116,6 +129,7 @@ struct waiter_helper {
116129
}
117130
bool ret = true;
118131
IPC_UNUSED_ auto guard = ctrl.get_lock();
132+
clear_handshake(ctrl);
119133
if (counter.counter_ > 0) {
120134
ret = ctrl.sema_post(counter.counter_);
121135
counter.counter_ -= 1;

test/test_ipc.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ using namespace ipc;
1818

1919
namespace {
2020

21-
constexpr int LoopCount = 10000;
22-
constexpr int MultiMax = 8;
21+
constexpr int LoopCount = 10000;
22+
constexpr int MultiMax = 8;
23+
constexpr int TestBuffMax = 65536;
2324

2425
struct msg_head {
2526
int id_;
@@ -28,7 +29,7 @@ struct msg_head {
2829
class rand_buf : public buffer {
2930
public:
3031
rand_buf() {
31-
int size = capo::random<>{sizeof(msg_head), 65536}();
32+
int size = capo::random<>{sizeof(msg_head), TestBuffMax}();
3233
*this = buffer(new char[size], size, [](void * p, std::size_t) {
3334
delete [] static_cast<char *>(p);
3435
});
@@ -98,6 +99,22 @@ class data_set {
9899
}
99100
} const data_set__;
100101

102+
#define IPC_ASSERT_TRUE(condition) \
103+
do { \
104+
bool check = !!(condition); \
105+
GTEST_TEST_BOOLEAN_(check, #condition, false, true, \
106+
GTEST_NONFATAL_FAILURE_); \
107+
if (!check) return; \
108+
} while (0)
109+
110+
#define IPC_ASSERT_FALSE(condition) \
111+
do { \
112+
bool check = !!(condition); \
113+
GTEST_TEST_BOOLEAN_(!check, #condition, true, false, \
114+
GTEST_NONFATAL_FAILURE_); \
115+
if (check) return; \
116+
} while (0)
117+
101118
template <relat Rp, relat Rc, trans Ts, typename Que = chan<Rp, Rc, Ts>>
102119
void test_sr(char const * name, int s_cnt, int r_cnt) {
103120
ipc_ut::sender().start(static_cast<std::size_t>(s_cnt));
@@ -109,10 +126,10 @@ void test_sr(char const * name, int s_cnt, int r_cnt) {
109126
for (int k = 0; k < s_cnt; ++k) {
110127
ipc_ut::sender() << [name, &sw, r_cnt, k] {
111128
Que que { name, ipc::sender };
112-
EXPECT_TRUE(que.wait_for_recv(r_cnt));
129+
IPC_ASSERT_TRUE(que.wait_for_recv(r_cnt));
113130
sw.start();
114131
for (int i = 0; i < (int)data_set__.get().size(); ++i) {
115-
EXPECT_TRUE(que.send(data_set__.get()[i]));
132+
IPC_ASSERT_TRUE(que.send(data_set__.get()[i]));
116133
}
117134
};
118135
}
@@ -122,25 +139,25 @@ void test_sr(char const * name, int s_cnt, int r_cnt) {
122139
Que que { name, ipc::receiver };
123140
for (;;) {
124141
rand_buf got { que.recv() };
125-
ASSERT_FALSE(got.empty());
142+
IPC_ASSERT_FALSE(got.empty());
126143
int i = got.get_id();
127144
if (i == -1) {
128145
return;
129146
}
130-
ASSERT_TRUE((i >= 0) && (i < (int)data_set__.get().size()));
147+
IPC_ASSERT_TRUE((i >= 0) && (i < (int)data_set__.get().size()));
131148
auto const &data_set = data_set__.get()[i];
132149
if (data_set != got) {
133150
printf("data_set__.get()[%d] != got, size = %zd/%zd\n",
134151
i, data_set.size(), got.size());
135-
EXPECT_TRUE(false);
152+
IPC_ASSERT_TRUE(false);
136153
}
137154
}
138155
};
139156
}
140157

141158
ipc_ut::sender().wait_for_done();
142159
Que que { name };
143-
EXPECT_TRUE(que.wait_for_recv(r_cnt));
160+
IPC_ASSERT_TRUE(que.wait_for_recv(r_cnt));
144161
for (int k = 0; k < r_cnt; ++k) {
145162
que.send(rand_buf{msg_head{-1}});
146163
}

0 commit comments

Comments
 (0)