mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 08:46:45 +08:00
add ut for sync::semaphore
This commit is contained in:
parent
d0e2a4d80c
commit
d37a6740ea
@ -14,7 +14,7 @@ class IPC_EXPORT semaphore {
|
||||
|
||||
public:
|
||||
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();
|
||||
|
||||
void const *native() const noexcept;
|
||||
@ -22,7 +22,7 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
bool wait(std::uint64_t tm = ipc::invalid_value) noexcept;
|
||||
|
||||
@ -26,10 +26,6 @@ class condition {
|
||||
|
||||
public:
|
||||
condition() = default;
|
||||
explicit condition(char const *name) noexcept {
|
||||
open(name);
|
||||
}
|
||||
|
||||
~condition() = default;
|
||||
|
||||
pthread_cond_t const *native() const noexcept {
|
||||
|
||||
@ -16,10 +16,6 @@ class condition {
|
||||
|
||||
public:
|
||||
condition() noexcept = default;
|
||||
explicit condition(char const *name) noexcept {
|
||||
open(name);
|
||||
}
|
||||
|
||||
~condition() noexcept = default;
|
||||
|
||||
HANDLE native() const noexcept {
|
||||
|
||||
@ -50,10 +50,6 @@ class mutex {
|
||||
|
||||
public:
|
||||
mutex() = default;
|
||||
explicit mutex(char const *name) noexcept {
|
||||
open(name);
|
||||
}
|
||||
|
||||
~mutex() = default;
|
||||
|
||||
pthread_mutex_t const *native() const noexcept {
|
||||
|
||||
@ -19,10 +19,6 @@ class mutex {
|
||||
|
||||
public:
|
||||
mutex() noexcept = default;
|
||||
explicit mutex(char const *name) noexcept {
|
||||
open(name);
|
||||
}
|
||||
|
||||
~mutex() noexcept = default;
|
||||
|
||||
HANDLE native() const noexcept {
|
||||
|
||||
@ -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
|
||||
@ -18,10 +18,6 @@ class semaphore {
|
||||
|
||||
public:
|
||||
semaphore() noexcept = default;
|
||||
explicit semaphore(char const *name, std::uint32_t count, std::uint32_t limit) noexcept {
|
||||
open(name, count, limit);
|
||||
}
|
||||
|
||||
~semaphore() noexcept = default;
|
||||
|
||||
HANDLE native() const noexcept {
|
||||
@ -32,11 +28,10 @@ public:
|
||||
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();
|
||||
h_ = ::CreateSemaphore(detail::get_sa(),
|
||||
static_cast<LONG>(count),
|
||||
(limit == invalid_value) ? LONG_MAX : static_cast<LONG>(limit),
|
||||
static_cast<LONG>(count), LONG_MAX,
|
||||
ipc::detail::to_tchar(name).c_str());
|
||||
if (h_ == NULL) {
|
||||
ipc::error("fail CreateSemaphore[%lu]: %s\n", ::GetLastError(), name);
|
||||
|
||||
@ -24,9 +24,9 @@ semaphore::semaphore()
|
||||
: 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() {
|
||||
open(name, count, limit);
|
||||
open(name, count);
|
||||
}
|
||||
|
||||
semaphore::~semaphore() {
|
||||
@ -46,8 +46,8 @@ bool semaphore::valid() const noexcept {
|
||||
return impl(p_)->sem_.valid();
|
||||
}
|
||||
|
||||
bool semaphore::open(char const *name, std::uint32_t count, std::uint32_t limit) noexcept {
|
||||
return impl(p_)->sem_.open(name, count, limit);
|
||||
bool semaphore::open(char const *name, std::uint32_t count) noexcept {
|
||||
return impl(p_)->sem_.open(name, count);
|
||||
}
|
||||
|
||||
void semaphore::close() noexcept {
|
||||
|
||||
@ -80,4 +80,20 @@ TEST(Sync, Mutex) {
|
||||
EXPECT_TRUE(lock.unlock());
|
||||
t2.join();
|
||||
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));
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user