mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
Problem: - 'linux' is a predefined macro on Linux platforms - Using 'namespace linux' causes compilation errors - Preprocessor replaces 'linux' with '1' before compilation Solution: - Rename 'namespace linux' to 'namespace linux_' - Rename 'namespace posix' to 'namespace posix_' - Update all 7 call sites accordingly: - linux/condition.h: linux_::detail::make_timespec() - linux/mutex.h: linux_::detail::make_timespec() (2 places) - posix/condition.h: posix_::detail::make_timespec() - posix/mutex.h: posix_::detail::make_timespec() (2 places) - posix/semaphore_impl.h: posix_::detail::make_timespec() This prevents preprocessor macro expansion issues while maintaining the ODR violation fix from the previous commit.
157 lines
4.6 KiB
C++
157 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include "libipc/utility/log.h"
|
|
#include "libipc/utility/scope_guard.h"
|
|
#include "libipc/mutex.h"
|
|
#include "libipc/shm.h"
|
|
|
|
#include "get_wait_time.h"
|
|
|
|
namespace ipc {
|
|
namespace detail {
|
|
namespace sync {
|
|
|
|
class condition {
|
|
ipc::shm::handle shm_;
|
|
pthread_cond_t *cond_ = nullptr;
|
|
|
|
pthread_cond_t *acquire_cond(char const *name) {
|
|
if (!shm_.acquire(name, sizeof(pthread_cond_t))) {
|
|
ipc::error("[acquire_cond] fail shm.acquire: %s\n", name);
|
|
return nullptr;
|
|
}
|
|
return static_cast<pthread_cond_t *>(shm_.get());
|
|
}
|
|
|
|
public:
|
|
condition() = default;
|
|
~condition() = default;
|
|
|
|
pthread_cond_t const *native() const noexcept {
|
|
return cond_;
|
|
}
|
|
|
|
pthread_cond_t *native() noexcept {
|
|
return cond_;
|
|
}
|
|
|
|
bool valid() const noexcept {
|
|
static const char tmp[sizeof(pthread_cond_t)] {};
|
|
return (cond_ != nullptr)
|
|
&& (std::memcmp(tmp, cond_, sizeof(pthread_cond_t)) != 0);
|
|
}
|
|
|
|
bool open(char const *name) noexcept {
|
|
close();
|
|
if ((cond_ = acquire_cond(name)) == nullptr) {
|
|
return false;
|
|
}
|
|
if (shm_.ref() > 1) {
|
|
return valid();
|
|
}
|
|
::pthread_cond_destroy(cond_);
|
|
auto finally = ipc::guard([this] { close(); }); // close when failed
|
|
// init condition
|
|
int eno;
|
|
pthread_condattr_t cond_attr;
|
|
if ((eno = ::pthread_condattr_init(&cond_attr)) != 0) {
|
|
ipc::error("fail pthread_condattr_init[%d]\n", eno);
|
|
return false;
|
|
}
|
|
IPC_UNUSED_ auto guard_cond_attr = guard([&cond_attr] { ::pthread_condattr_destroy(&cond_attr); });
|
|
if ((eno = ::pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED)) != 0) {
|
|
ipc::error("fail pthread_condattr_setpshared[%d]\n", eno);
|
|
return false;
|
|
}
|
|
*cond_ = PTHREAD_COND_INITIALIZER;
|
|
if ((eno = ::pthread_cond_init(cond_, &cond_attr)) != 0) {
|
|
ipc::error("fail pthread_cond_init[%d]\n", eno);
|
|
return false;
|
|
}
|
|
finally.dismiss();
|
|
return valid();
|
|
}
|
|
|
|
void close() noexcept {
|
|
if ((shm_.ref() <= 1) && cond_ != nullptr) {
|
|
int eno;
|
|
if ((eno = ::pthread_cond_destroy(cond_)) != 0) {
|
|
ipc::error("fail pthread_cond_destroy[%d]\n", eno);
|
|
}
|
|
}
|
|
shm_.release();
|
|
cond_ = nullptr;
|
|
}
|
|
|
|
void clear() noexcept {
|
|
if ((shm_.ref() <= 1) && cond_ != nullptr) {
|
|
int eno;
|
|
if ((eno = ::pthread_cond_destroy(cond_)) != 0) {
|
|
ipc::error("fail pthread_cond_destroy[%d]\n", eno);
|
|
}
|
|
}
|
|
shm_.clear(); // Make sure the storage is cleaned up.
|
|
cond_ = nullptr;
|
|
}
|
|
|
|
static void clear_storage(char const *name) noexcept {
|
|
ipc::shm::handle::clear_storage(name);
|
|
}
|
|
|
|
bool wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept {
|
|
if (!valid()) return false;
|
|
switch (tm) {
|
|
case invalid_value: {
|
|
int eno;
|
|
if ((eno = ::pthread_cond_wait(cond_, static_cast<pthread_mutex_t *>(mtx.native()))) != 0) {
|
|
ipc::error("fail pthread_cond_wait[%d]\n", eno);
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
default: {
|
|
auto ts = posix_::detail::make_timespec(tm);
|
|
int eno;
|
|
if ((eno = ::pthread_cond_timedwait(cond_, static_cast<pthread_mutex_t *>(mtx.native()), &ts)) != 0) {
|
|
if (eno != ETIMEDOUT) {
|
|
ipc::error("fail pthread_cond_timedwait[%d]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
|
|
eno, tm, ts.tv_sec, ts.tv_nsec);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool notify(ipc::sync::mutex &) noexcept {
|
|
if (!valid()) return false;
|
|
int eno;
|
|
if ((eno = ::pthread_cond_signal(cond_)) != 0) {
|
|
ipc::error("fail pthread_cond_signal[%d]\n", eno);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool broadcast(ipc::sync::mutex &) noexcept {
|
|
if (!valid()) return false;
|
|
int eno;
|
|
if ((eno = ::pthread_cond_broadcast(cond_)) != 0) {
|
|
ipc::error("fail pthread_cond_broadcast[%d]\n", eno);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace sync
|
|
} // namespace detail
|
|
} // namespace ipc
|