add ut for sync::semaphore

This commit is contained in:
mutouyun 2021-09-12 21:48:22 +08:00
parent d0e2a4d80c
commit d37a6740ea
9 changed files with 125 additions and 29 deletions

View File

@ -14,7 +14,7 @@ class IPC_EXPORT semaphore {
public: public:
semaphore(); semaphore();
explicit semaphore(char const *name, std::uint32_t count = 0, std::uint32_t limit = ipc::invalid_value); explicit semaphore(char const *name, std::uint32_t count = 0);
~semaphore(); ~semaphore();
void const *native() const noexcept; void const *native() const noexcept;
@ -22,7 +22,7 @@ public:
bool valid() const noexcept; bool valid() const noexcept;
bool open(char const *name, std::uint32_t count = 0, std::uint32_t limit = ipc::invalid_value) noexcept; bool open(char const *name, std::uint32_t count = 0) noexcept;
void close() noexcept; void close() noexcept;
bool wait(std::uint64_t tm = ipc::invalid_value) noexcept; bool wait(std::uint64_t tm = ipc::invalid_value) noexcept;

View File

@ -26,10 +26,6 @@ class condition {
public: public:
condition() = default; condition() = default;
explicit condition(char const *name) noexcept {
open(name);
}
~condition() = default; ~condition() = default;
pthread_cond_t const *native() const noexcept { pthread_cond_t const *native() const noexcept {

View File

@ -16,10 +16,6 @@ class condition {
public: public:
condition() noexcept = default; condition() noexcept = default;
explicit condition(char const *name) noexcept {
open(name);
}
~condition() noexcept = default; ~condition() noexcept = default;
HANDLE native() const noexcept { HANDLE native() const noexcept {

View File

@ -50,10 +50,6 @@ class mutex {
public: public:
mutex() = default; mutex() = default;
explicit mutex(char const *name) noexcept {
open(name);
}
~mutex() = default; ~mutex() = default;
pthread_mutex_t const *native() const noexcept { pthread_mutex_t const *native() const noexcept {

View File

@ -19,10 +19,6 @@ class mutex {
public: public:
mutex() noexcept = default; mutex() noexcept = default;
explicit mutex(char const *name) noexcept {
open(name);
}
~mutex() noexcept = default; ~mutex() noexcept = default;
HANDLE native() const noexcept { HANDLE native() const noexcept {

View File

@ -0,0 +1,101 @@
#pragma once
#include <cstdint>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#include <errno.h>
#include "libipc/utility/log.h"
#include "libipc/platform/get_wait_time.h"
#include "libipc/shm.h"
namespace ipc {
namespace detail {
namespace sync {
class semaphore {
ipc::shm::handle shm_;
sem_t *h_ = SEM_FAILED;
public:
semaphore() noexcept = default;
~semaphore() noexcept = default;
sem_t *native() const noexcept {
return h_;
}
bool valid() const noexcept {
return h_ != SEM_FAILED;
}
bool open(char const *name, std::uint32_t count) noexcept {
close();
if (!shm_.acquire(name, 0)) {
ipc::error("[open_semaphore] fail shm.acquire: %s\n", name);
return false;
}
h_ = ::sem_open(name, O_CREAT, 0666, static_cast<unsigned>(count));
if (h_ == SEM_FAILED) {
ipc::error("fail sem_open[%d]: %s\n", errno, name);
return false;
}
return true;
}
void close() noexcept {
if (!valid()) return;
if (::sem_close(h_) != 0) {
ipc::error("fail sem_close[%d]: %s\n", errno);
}
if (shm_.ref() == 1) {
if (::sem_unlink(shm_.name()) != 0) {
ipc::error("fail sem_unlink[%d]: %s\n", errno);
}
}
shm_.release();
h_ = SEM_FAILED;
}
bool wait(std::uint64_t tm) noexcept {
if (h == invalid()) return false;
switch (tm) {
case 0:
return true;
case invalid_value:
if (::sem_wait(h_) != 0) {
ipc::error("fail sem_wait[%d]: %s\n", errno);
return false;
}
return true;
default: {
auto ts = detail::make_timespec(tm);
if (::sem_timedwait(h, &ts) != 0) {
if (errno != ETIMEDOUT) {
ipc::error("fail sem_timedwait[%d]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
errno, tm, ts.tv_sec, ts.tv_nsec);
}
return false;
}
}
return true;
}
}
bool post(std::uint32_t count) noexcept {
if (h_ == invalid()) return false;
for (std::uint32_t i = 0; i < count; ++i) {
if (::sem_post(h_) != 0) {
ipc::error("fail sem_post[%d]: %s\n", errno);
return false;
}
}
return true;
}
};
} // namespace sync
} // namespace detail
} // namespace ipc

View File

@ -18,10 +18,6 @@ class semaphore {
public: public:
semaphore() noexcept = default; semaphore() noexcept = default;
explicit semaphore(char const *name, std::uint32_t count, std::uint32_t limit) noexcept {
open(name, count, limit);
}
~semaphore() noexcept = default; ~semaphore() noexcept = default;
HANDLE native() const noexcept { HANDLE native() const noexcept {
@ -32,11 +28,10 @@ public:
return h_ != NULL; return h_ != NULL;
} }
bool open(char const *name, std::uint32_t count, std::uint32_t limit) noexcept { bool open(char const *name, std::uint32_t count) noexcept {
close(); close();
h_ = ::CreateSemaphore(detail::get_sa(), h_ = ::CreateSemaphore(detail::get_sa(),
static_cast<LONG>(count), static_cast<LONG>(count), LONG_MAX,
(limit == invalid_value) ? LONG_MAX : static_cast<LONG>(limit),
ipc::detail::to_tchar(name).c_str()); ipc::detail::to_tchar(name).c_str());
if (h_ == NULL) { if (h_ == NULL) {
ipc::error("fail CreateSemaphore[%lu]: %s\n", ::GetLastError(), name); ipc::error("fail CreateSemaphore[%lu]: %s\n", ::GetLastError(), name);

View File

@ -24,9 +24,9 @@ semaphore::semaphore()
: p_(p_->make()) { : p_(p_->make()) {
} }
semaphore::semaphore(char const * name, std::uint32_t count, std::uint32_t limit) semaphore::semaphore(char const * name, std::uint32_t count)
: semaphore() { : semaphore() {
open(name, count, limit); open(name, count);
} }
semaphore::~semaphore() { semaphore::~semaphore() {
@ -46,8 +46,8 @@ bool semaphore::valid() const noexcept {
return impl(p_)->sem_.valid(); return impl(p_)->sem_.valid();
} }
bool semaphore::open(char const *name, std::uint32_t count, std::uint32_t limit) noexcept { bool semaphore::open(char const *name, std::uint32_t count) noexcept {
return impl(p_)->sem_.open(name, count, limit); return impl(p_)->sem_.open(name, count);
} }
void semaphore::close() noexcept { void semaphore::close() noexcept {

View File

@ -81,3 +81,19 @@ TEST(Sync, Mutex) {
t2.join(); t2.join();
EXPECT_EQ(i, 200); EXPECT_EQ(i, 200);
} }
#include "libipc/semaphore.h"
TEST(Sync, Semaphore) {
ipc::sync::semaphore sem;
EXPECT_TRUE(sem.open("test-sem"));
std::thread{[] {
ipc::sync::semaphore sem{"test-sem"};
EXPECT_TRUE(sem.post(10));
}}.join();
for (int i = 0; i < 10; ++i) {
EXPECT_TRUE(sem.wait(0));
}
EXPECT_FALSE(sem.wait(0));
}