mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
101 lines
2.6 KiB
C++
101 lines
2.6 KiB
C++
#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/shm.h"
|
|
|
|
#include "get_wait_time.h"
|
|
#include "get_error.h"
|
|
|
|
namespace ipc {
|
|
namespace detail {
|
|
namespace sync {
|
|
|
|
class semaphore {
|
|
ipc::shm::handle shm_;
|
|
sem_t *h_ = SEM_FAILED;
|
|
|
|
public:
|
|
semaphore() = 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, 1)) {
|
|
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[%s]: name = %s\n", curr_error(), name);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void close() noexcept {
|
|
if (!valid()) return;
|
|
if (::sem_close(h_) != 0) {
|
|
ipc::error("fail sem_close[%s]\n", curr_error());
|
|
}
|
|
h_ = SEM_FAILED;
|
|
if (shm_.name() != nullptr) {
|
|
std::string name = shm_.name();
|
|
if (shm_.release() <= 1) {
|
|
if (::sem_unlink(name.c_str()) != 0) {
|
|
ipc::error("fail sem_unlink[%s]: name = %s\n", curr_error(), name.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool wait(std::uint64_t tm) noexcept {
|
|
if (!valid()) return false;
|
|
if (tm == invalid_value) {
|
|
if (::sem_wait(h_) != 0) {
|
|
ipc::error("fail sem_wait[%s]\n", curr_error());
|
|
return false;
|
|
}
|
|
} else {
|
|
auto ts = detail::make_timespec(tm);
|
|
if (::sem_timedwait(h_, &ts) != 0) {
|
|
if (errno != ETIMEDOUT) {
|
|
ipc::error("fail sem_timedwait[%s]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
|
|
curr_error(), tm, ts.tv_sec, ts.tv_nsec);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool post(std::uint32_t count) noexcept {
|
|
if (!valid()) return false;
|
|
for (std::uint32_t i = 0; i < count; ++i) {
|
|
if (::sem_post(h_) != 0) {
|
|
ipc::error("fail sem_post[%s]\n", curr_error());
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace sync
|
|
} // namespace detail
|
|
} // namespace ipc
|