Skip to content

Commit 0cccdac

Browse files
committed
merge issue-61; add condition for linux
1 parent 4ca300b commit 0cccdac

File tree

13 files changed

+191
-33
lines changed

13 files changed

+191
-33
lines changed

include/libipc/condition.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <cstdint> // std::uint64_t
4+
5+
#include "libipc/export.h"
6+
#include "libipc/def.h"
7+
#include "libipc/mutex.h"
8+
9+
namespace ipc {
10+
namespace sync {
11+
12+
class IPC_EXPORT condition {
13+
condition(condition const &) = delete;
14+
condition &operator=(condition const &) = delete;
15+
16+
public:
17+
condition();
18+
explicit condition(char const *name);
19+
~condition();
20+
21+
void const *native() const noexcept;
22+
void *native() noexcept;
23+
24+
bool valid() const noexcept;
25+
26+
bool open(char const *name) noexcept;
27+
void close() noexcept;
28+
29+
bool wait(ipc::sync::mutex &mtx, std::uint64_t tm = ipc::invalid_value) noexcept;
30+
bool notify() noexcept;
31+
bool broadcast() noexcept;
32+
33+
private:
34+
class condition_;
35+
condition_* p_;
36+
};
37+
38+
} // namespace sync
39+
} // namespace ipc

src/CMakeLists.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ if(UNIX)
55
else()
66
file(GLOB SRC_FILES ${LIBIPC_PROJECT_DIR}/src/libipc/platform/*_win.cpp)
77
endif()
8-
aux_source_directory(${LIBIPC_PROJECT_DIR}/src SRC_FILES)
8+
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES)
9+
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/sync SRC_FILES)
910

1011
file(GLOB HEAD_FILES
1112
${LIBIPC_PROJECT_DIR}/include/libipc/*.h
@@ -37,8 +38,8 @@ set_target_properties(${PROJECT_NAME}
3738
# set version
3839
set_target_properties(${PROJECT_NAME}
3940
PROPERTIES
40-
VERSION 1.0.0
41-
SOVERSION 1)
41+
VERSION 1.1.0
42+
SOVERSION 2)
4243

4344
target_include_directories(${PROJECT_NAME}
4445
PUBLIC ${LIBIPC_PROJECT_DIR}/include
File renamed without changes.
File renamed without changes.

src/libipc/platform/condition_linux.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
#pragma once
22

33
#include <cstdint>
4+
#include <cstring>
45

56
#include <pthread.h>
67

7-
#include "libipc/utility/log.h"
88
#include "libipc/platform/get_wait_time.h"
9+
#include "libipc/utility/log.h"
10+
#include "libipc/utility/scope_guard.h"
911
#include "libipc/mutex.h"
12+
#include "libipc/shm.h"
1013

1114
namespace ipc {
1215
namespace detail {
@@ -89,7 +92,7 @@ class condition {
8992
return true;
9093
case invalid_value: {
9194
int eno;
92-
if ((eno = ::pthread_cond_wait(cond_, mtx.native())) != 0) {
95+
if ((eno = ::pthread_cond_wait(cond_, static_cast<pthread_mutex_t *>(mtx.native()))) != 0) {
9396
ipc::error("fail pthread_cond_wait[%d]\n", eno);
9497
return false;
9598
}
@@ -98,7 +101,7 @@ class condition {
98101
default: {
99102
auto ts = detail::make_timespec(tm);
100103
int eno;
101-
if ((eno = ::pthread_cond_timedwait(cond_, mtx.native(), &ts)) != 0) {
104+
if ((eno = ::pthread_cond_timedwait(cond_, static_cast<pthread_mutex_t *>(mtx.native()), &ts)) != 0) {
102105
if (eno != ETIMEDOUT) {
103106
ipc::error("fail pthread_cond_timedwait[%d]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
104107
eno, tm, ts.tv_sec, ts.tv_nsec);
File renamed without changes.
File renamed without changes.

src/libipc/sync/condition.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
#include "libipc/condition.h"
3+
4+
#include "libipc/utility/pimpl.h"
5+
#include "libipc/memory/resource.h"
6+
#include "libipc/platform/detail.h"
7+
#if defined(IPC_OS_WINDOWS_)
8+
#include "libipc/platform/condition_win.h"
9+
#elif defined(IPC_OS_LINUX_)
10+
#include "libipc/platform/condition_linux.h"
11+
#else/*linux*/
12+
# error "Unsupported platform."
13+
#endif
14+
15+
namespace ipc {
16+
namespace sync {
17+
18+
class condition::condition_ : public ipc::pimpl<condition_> {
19+
public:
20+
ipc::detail::sync::condition cond_;
21+
};
22+
23+
condition::condition()
24+
: p_(p_->make()) {
25+
}
26+
27+
condition::condition(char const * name)
28+
: condition() {
29+
open(name);
30+
}
31+
32+
condition::~condition() {
33+
close();
34+
p_->clear();
35+
}
36+
37+
void const *condition::native() const noexcept {
38+
return impl(p_)->cond_.native();
39+
}
40+
41+
void *condition::native() noexcept {
42+
return impl(p_)->cond_.native();
43+
}
44+
45+
bool condition::valid() const noexcept {
46+
return impl(p_)->cond_.valid();
47+
}
48+
49+
bool condition::open(char const *name) noexcept {
50+
return impl(p_)->cond_.open(name);
51+
}
52+
53+
void condition::close() noexcept {
54+
impl(p_)->cond_.close();
55+
}
56+
57+
bool condition::wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept {
58+
return impl(p_)->cond_.wait(mtx, tm);
59+
}
60+
61+
bool condition::notify() noexcept {
62+
return impl(p_)->cond_.notify();
63+
}
64+
65+
bool condition::broadcast() noexcept {
66+
return impl(p_)->cond_.broadcast();
67+
}
68+
69+
} // namespace sync
70+
} // namespace ipc
File renamed without changes.
File renamed without changes.
File renamed without changes.

test/test_ipc.cpp

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,6 @@ class data_set {
9999
}
100100
} const data_set__;
101101

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-
118102
template <relat Rp, relat Rc, trans Ts, typename Que = chan<Rp, Rc, Ts>>
119103
void test_sr(char const * name, int s_cnt, int r_cnt) {
120104
ipc_ut::sender().start(static_cast<std::size_t>(s_cnt));
@@ -126,10 +110,10 @@ void test_sr(char const * name, int s_cnt, int r_cnt) {
126110
for (int k = 0; k < s_cnt; ++k) {
127111
ipc_ut::sender() << [name, &sw, r_cnt, k] {
128112
Que que { name, ipc::sender };
129-
IPC_ASSERT_TRUE(que.wait_for_recv(r_cnt));
113+
ASSERT_TRUE(que.wait_for_recv(r_cnt));
130114
sw.start();
131115
for (int i = 0; i < (int)data_set__.get().size(); ++i) {
132-
IPC_ASSERT_TRUE(que.send(data_set__.get()[i]));
116+
ASSERT_TRUE(que.send(data_set__.get()[i]));
133117
}
134118
};
135119
}
@@ -139,25 +123,25 @@ void test_sr(char const * name, int s_cnt, int r_cnt) {
139123
Que que { name, ipc::receiver };
140124
for (;;) {
141125
rand_buf got { que.recv() };
142-
IPC_ASSERT_FALSE(got.empty());
126+
ASSERT_FALSE(got.empty());
143127
int i = got.get_id();
144128
if (i == -1) {
145129
return;
146130
}
147-
IPC_ASSERT_TRUE((i >= 0) && (i < (int)data_set__.get().size()));
131+
ASSERT_TRUE((i >= 0) && (i < (int)data_set__.get().size()));
148132
auto const &data_set = data_set__.get()[i];
149133
if (data_set != got) {
150134
printf("data_set__.get()[%d] != got, size = %zd/%zd\n",
151135
i, data_set.size(), got.size());
152-
IPC_ASSERT_TRUE(false);
136+
ASSERT_TRUE(false);
153137
}
154138
}
155139
};
156140
}
157141

158142
ipc_ut::sender().wait_for_done();
159143
Que que { name };
160-
IPC_ASSERT_TRUE(que.wait_for_recv(r_cnt));
144+
ASSERT_TRUE(que.wait_for_recv(r_cnt));
161145
for (int k = 0; k < r_cnt; ++k) {
162146
que.send(rand_buf{msg_head{-1}});
163147
}

test/test_sync.cpp

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <iostream>
44
#include <mutex>
55
#include <chrono>
6+
#include <deque>
7+
#include <cstdio>
68

79
#include "test.h"
810

@@ -57,7 +59,7 @@ TEST(Sync, Mutex) {
5759
ipc::sync::mutex lock;
5860
EXPECT_TRUE(lock.open("test-mutex-robust"));
5961
std::thread{[] {
60-
ipc::sync::mutex lock{"test-mutex-robust"};
62+
ipc::sync::mutex lock {"test-mutex-robust"};
6163
EXPECT_TRUE(lock.valid());
6264
EXPECT_TRUE(lock.lock());
6365
}}.join();
@@ -68,7 +70,7 @@ TEST(Sync, Mutex) {
6870
EXPECT_TRUE(lock.lock());
6971
i = 100;
7072
auto t2 = std::thread{[&i] {
71-
ipc::sync::mutex lock{"test-mutex-robust"};
73+
ipc::sync::mutex lock {"test-mutex-robust"};
7274
EXPECT_TRUE(lock.valid());
7375
EXPECT_FALSE(lock.try_lock());
7476
EXPECT_TRUE(lock.lock());
@@ -88,12 +90,71 @@ TEST(Sync, Semaphore) {
8890
ipc::sync::semaphore sem;
8991
EXPECT_TRUE(sem.open("test-sem"));
9092
std::thread{[] {
91-
ipc::sync::semaphore sem{"test-sem"};
92-
EXPECT_TRUE(sem.post(10));
93+
ipc::sync::semaphore sem {"test-sem"};
94+
EXPECT_TRUE(sem.post(1000));
9395
}}.join();
9496

95-
for (int i = 0; i < 10; ++i) {
97+
for (int i = 0; i < 1000; ++i) {
9698
EXPECT_TRUE(sem.wait(0));
9799
}
98100
EXPECT_FALSE(sem.wait(0));
101+
}
102+
103+
#include "libipc/condition.h"
104+
105+
TEST(Sync, Condition) {
106+
ipc::sync::condition cond;
107+
EXPECT_TRUE(cond.open("test-cond"));
108+
ipc::sync::mutex lock;
109+
EXPECT_TRUE(lock.open("test-mutex"));
110+
std::deque<int> que;
111+
112+
auto job = [&que](int num) {
113+
ipc::sync::condition cond {"test-cond"};
114+
ipc::sync::mutex lock {"test-mutex"};
115+
for (;;) {
116+
int val = 0;
117+
{
118+
std::lock_guard<ipc::sync::mutex> guard {lock};
119+
while (que.empty()) {
120+
ASSERT_TRUE(cond.wait(lock));
121+
}
122+
val = que.front();
123+
que.pop_front();
124+
}
125+
if (val == 0) {
126+
std::printf("test-cond-%d: exit.\n", num);
127+
return;
128+
}
129+
std::printf("test-cond-%d: %d\n", num, val);
130+
}
131+
};
132+
std::thread test_cond1 {job, 1};
133+
std::thread test_cond2 {job, 2};
134+
135+
for (int i = 1; i < 100; ++i) {
136+
{
137+
std::lock_guard<ipc::sync::mutex> guard {lock};
138+
que.push_back(i);
139+
}
140+
cond.notify();
141+
std::this_thread::sleep_for(std::chrono::milliseconds(20));
142+
}
143+
for (int i = 1; i < 100; ++i) {
144+
{
145+
std::lock_guard<ipc::sync::mutex> guard {lock};
146+
que.push_back(i);
147+
}
148+
cond.broadcast();
149+
std::this_thread::sleep_for(std::chrono::milliseconds(20));
150+
}
151+
{
152+
std::lock_guard<ipc::sync::mutex> guard {lock};
153+
que.push_back(0);
154+
que.push_back(0);
155+
}
156+
cond.broadcast();
157+
158+
test_cond1.join();
159+
test_cond2.join();
99160
}

0 commit comments

Comments
 (0)