mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
implement waiter_linux.h
This commit is contained in:
parent
d1822e9fc9
commit
e09ea90949
@ -1,32 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace std {
|
||||
|
||||
// deduction guides for std::unique_ptr
|
||||
template <typename T, typename D>
|
||||
unique_ptr(T* p, D&& d) -> unique_ptr<T, std::decay_t<D>>;
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace ipc {
|
||||
namespace detail {
|
||||
|
||||
class waiter {
|
||||
pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t cond_ = PTHREAD_COND_INITIALIZER;
|
||||
std::atomic<unsigned> counter_ { 0 };
|
||||
|
||||
public:
|
||||
using handle_t = void*;
|
||||
|
||||
private:
|
||||
constexpr static waiter* waiter_cast(handle_t h) {
|
||||
return static_cast<waiter*>(h);
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr static handle_t invalid() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
handle_t open(char const * name) {
|
||||
if (name == nullptr || name[0] == '\0') return invalid();
|
||||
return invalid();
|
||||
if (counter_.fetch_add(1, std::memory_order_acq_rel) == 0) {
|
||||
// init mutex
|
||||
pthread_mutexattr_t mutex_attr;
|
||||
if (::pthread_mutexattr_init(&mutex_attr) != 0) {
|
||||
return invalid();
|
||||
}
|
||||
[[maybe_unused]] auto guard_mutex_attr = std::unique_ptr { &mutex_attr, ::pthread_mutexattr_destroy };
|
||||
if (::pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED) != 0) {
|
||||
return invalid();
|
||||
}
|
||||
if (::pthread_mutex_init(&mutex_, &mutex_attr) != 0) {
|
||||
return invalid();
|
||||
}
|
||||
auto guard_mutex = std::unique_ptr { &mutex_, ::pthread_mutex_destroy };
|
||||
// init condition
|
||||
pthread_condattr_t cond_attr;
|
||||
if (::pthread_condattr_init(&cond_attr) != 0) {
|
||||
return invalid();
|
||||
}
|
||||
[[maybe_unused]] auto guard_cond_attr = std::unique_ptr { &cond_attr, ::pthread_condattr_destroy };
|
||||
if (::pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED) != 0) {
|
||||
return invalid();
|
||||
}
|
||||
if (::pthread_cond_init(&cond_, &cond_attr) != 0) {
|
||||
return invalid();
|
||||
}
|
||||
// no need to guard condition
|
||||
// release guards
|
||||
guard_mutex.release();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
static void close(handle_t /*h*/) {
|
||||
void close(handle_t h) {
|
||||
if (h == invalid()) return;
|
||||
auto w = waiter_cast(h);
|
||||
if (w->counter_.fetch_sub(1, std::memory_order_acq_rel) == 1) {
|
||||
::pthread_cond_destroy (&(w->cond_ ));
|
||||
::pthread_mutex_destroy(&(w->mutex_));
|
||||
}
|
||||
}
|
||||
|
||||
bool wait(handle_t /*h*/) {
|
||||
return false;
|
||||
bool wait(handle_t h) {
|
||||
if (h == invalid()) return false;
|
||||
auto w = waiter_cast(h);
|
||||
if (::pthread_mutex_lock(&(w->mutex_)) != 0) {
|
||||
return false;
|
||||
}
|
||||
[[maybe_unused]] auto guard = std::unique_ptr { &(w->mutex_), ::pthread_mutex_unlock };
|
||||
if (::pthread_cond_wait(&(w->cond_), &(w->mutex_)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void notify(handle_t /*h*/) {
|
||||
void notify(handle_t h) {
|
||||
if (h == invalid()) return;
|
||||
::pthread_cond_signal(&(waiter_cast(h)->cond_));
|
||||
}
|
||||
|
||||
void broadcast(handle_t /*h*/) {
|
||||
void broadcast(handle_t h) {
|
||||
if (h == invalid()) return;
|
||||
::pthread_cond_broadcast(&(waiter_cast(h)->cond_));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ public:
|
||||
return ::CreateSemaphore(NULL, 0, LONG_MAX, ipc::detail::to_tchar(name).c_str());
|
||||
}
|
||||
|
||||
static void close(handle_t h) {
|
||||
void close(handle_t h) {
|
||||
::CloseHandle(h);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user