mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56: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:
|
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;
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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:
|
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);
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -80,4 +80,20 @@ TEST(Sync, Mutex) {
|
|||||||
EXPECT_TRUE(lock.unlock());
|
EXPECT_TRUE(lock.unlock());
|
||||||
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));
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user