Skip to content

Commit d37a674

Browse files
committed
add ut for sync::semaphore
1 parent d0e2a4d commit d37a674

File tree

9 files changed

+125
-29
lines changed

9 files changed

+125
-29
lines changed

include/libipc/semaphore.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ class IPC_EXPORT semaphore {
1414

1515
public:
1616
semaphore();
17-
explicit semaphore(char const *name, std::uint32_t count = 0, std::uint32_t limit = ipc::invalid_value);
17+
explicit semaphore(char const *name, std::uint32_t count = 0);
1818
~semaphore();
1919

2020
void const *native() const noexcept;
2121
void *native() noexcept;
2222

2323
bool valid() const noexcept;
2424

25-
bool open(char const *name, std::uint32_t count = 0, std::uint32_t limit = ipc::invalid_value) noexcept;
25+
bool open(char const *name, std::uint32_t count = 0) noexcept;
2626
void close() noexcept;
2727

2828
bool wait(std::uint64_t tm = ipc::invalid_value) noexcept;

src/libipc/platform/condition_linux.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ class condition {
2626

2727
public:
2828
condition() = default;
29-
explicit condition(char const *name) noexcept {
30-
open(name);
31-
}
32-
3329
~condition() = default;
3430

3531
pthread_cond_t const *native() const noexcept {

src/libipc/platform/condition_win.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ class condition {
1616

1717
public:
1818
condition() noexcept = default;
19-
explicit condition(char const *name) noexcept {
20-
open(name);
21-
}
22-
2319
~condition() noexcept = default;
2420

2521
HANDLE native() const noexcept {

src/libipc/platform/mutex_linux.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@ class mutex {
5050

5151
public:
5252
mutex() = default;
53-
explicit mutex(char const *name) noexcept {
54-
open(name);
55-
}
56-
5753
~mutex() = default;
5854

5955
pthread_mutex_t const *native() const noexcept {

src/libipc/platform/mutex_win.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ class mutex {
1919

2020
public:
2121
mutex() noexcept = default;
22-
explicit mutex(char const *name) noexcept {
23-
open(name);
24-
}
25-
2622
~mutex() noexcept = default;
2723

2824
HANDLE native() const noexcept {

src/libipc/platform/semaphore_linux.h

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
5+
#include <fcntl.h> /* For O_* constants */
6+
#include <sys/stat.h> /* For mode constants */
7+
#include <semaphore.h>
8+
#include <errno.h>
9+
10+
#include "libipc/utility/log.h"
11+
#include "libipc/platform/get_wait_time.h"
12+
#include "libipc/shm.h"
13+
14+
namespace ipc {
15+
namespace detail {
16+
namespace sync {
17+
18+
class semaphore {
19+
ipc::shm::handle shm_;
20+
sem_t *h_ = SEM_FAILED;
21+
22+
public:
23+
semaphore() noexcept = default;
24+
~semaphore() noexcept = default;
25+
26+
sem_t *native() const noexcept {
27+
return h_;
28+
}
29+
30+
bool valid() const noexcept {
31+
return h_ != SEM_FAILED;
32+
}
33+
34+
bool open(char const *name, std::uint32_t count) noexcept {
35+
close();
36+
if (!shm_.acquire(name, 0)) {
37+
ipc::error("[open_semaphore] fail shm.acquire: %s\n", name);
38+
return false;
39+
}
40+
h_ = ::sem_open(name, O_CREAT, 0666, static_cast<unsigned>(count));
41+
if (h_ == SEM_FAILED) {
42+
ipc::error("fail sem_open[%d]: %s\n", errno, name);
43+
return false;
44+
}
45+
return true;
46+
}
47+
48+
void close() noexcept {
49+
if (!valid()) return;
50+
if (::sem_close(h_) != 0) {
51+
ipc::error("fail sem_close[%d]: %s\n", errno);
52+
}
53+
if (shm_.ref() == 1) {
54+
if (::sem_unlink(shm_.name()) != 0) {
55+
ipc::error("fail sem_unlink[%d]: %s\n", errno);
56+
}
57+
}
58+
shm_.release();
59+
h_ = SEM_FAILED;
60+
}
61+
62+
bool wait(std::uint64_t tm) noexcept {
63+
if (h == invalid()) return false;
64+
switch (tm) {
65+
case 0:
66+
return true;
67+
case invalid_value:
68+
if (::sem_wait(h_) != 0) {
69+
ipc::error("fail sem_wait[%d]: %s\n", errno);
70+
return false;
71+
}
72+
return true;
73+
default: {
74+
auto ts = detail::make_timespec(tm);
75+
if (::sem_timedwait(h, &ts) != 0) {
76+
if (errno != ETIMEDOUT) {
77+
ipc::error("fail sem_timedwait[%d]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
78+
errno, tm, ts.tv_sec, ts.tv_nsec);
79+
}
80+
return false;
81+
}
82+
}
83+
return true;
84+
}
85+
}
86+
87+
bool post(std::uint32_t count) noexcept {
88+
if (h_ == invalid()) return false;
89+
for (std::uint32_t i = 0; i < count; ++i) {
90+
if (::sem_post(h_) != 0) {
91+
ipc::error("fail sem_post[%d]: %s\n", errno);
92+
return false;
93+
}
94+
}
95+
return true;
96+
}
97+
};
98+
99+
} // namespace sync
100+
} // namespace detail
101+
} // namespace ipc

src/libipc/platform/semaphore_win.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ class semaphore {
1818

1919
public:
2020
semaphore() noexcept = default;
21-
explicit semaphore(char const *name, std::uint32_t count, std::uint32_t limit) noexcept {
22-
open(name, count, limit);
23-
}
24-
2521
~semaphore() noexcept = default;
2622

2723
HANDLE native() const noexcept {
@@ -32,11 +28,10 @@ class semaphore {
3228
return h_ != NULL;
3329
}
3430

35-
bool open(char const *name, std::uint32_t count, std::uint32_t limit) noexcept {
31+
bool open(char const *name, std::uint32_t count) noexcept {
3632
close();
3733
h_ = ::CreateSemaphore(detail::get_sa(),
38-
static_cast<LONG>(count),
39-
(limit == invalid_value) ? LONG_MAX : static_cast<LONG>(limit),
34+
static_cast<LONG>(count), LONG_MAX,
4035
ipc::detail::to_tchar(name).c_str());
4136
if (h_ == NULL) {
4237
ipc::error("fail CreateSemaphore[%lu]: %s\n", ::GetLastError(), name);

src/semaphore.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ semaphore::semaphore()
2424
: p_(p_->make()) {
2525
}
2626

27-
semaphore::semaphore(char const * name, std::uint32_t count, std::uint32_t limit)
27+
semaphore::semaphore(char const * name, std::uint32_t count)
2828
: semaphore() {
29-
open(name, count, limit);
29+
open(name, count);
3030
}
3131

3232
semaphore::~semaphore() {
@@ -46,8 +46,8 @@ bool semaphore::valid() const noexcept {
4646
return impl(p_)->sem_.valid();
4747
}
4848

49-
bool semaphore::open(char const *name, std::uint32_t count, std::uint32_t limit) noexcept {
50-
return impl(p_)->sem_.open(name, count, limit);
49+
bool semaphore::open(char const *name, std::uint32_t count) noexcept {
50+
return impl(p_)->sem_.open(name, count);
5151
}
5252

5353
void semaphore::close() noexcept {

test/test_sync.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,20 @@ TEST(Sync, Mutex) {
8080
EXPECT_TRUE(lock.unlock());
8181
t2.join();
8282
EXPECT_EQ(i, 200);
83+
}
84+
85+
#include "libipc/semaphore.h"
86+
87+
TEST(Sync, Semaphore) {
88+
ipc::sync::semaphore sem;
89+
EXPECT_TRUE(sem.open("test-sem"));
90+
std::thread{[] {
91+
ipc::sync::semaphore sem{"test-sem"};
92+
EXPECT_TRUE(sem.post(10));
93+
}}.join();
94+
95+
for (int i = 0; i < 10; ++i) {
96+
EXPECT_TRUE(sem.wait(0));
97+
}
98+
EXPECT_FALSE(sem.wait(0));
8399
}

0 commit comments

Comments
 (0)