mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2026-02-06 01:39:47 +08:00
impl condition for windows
This commit is contained in:
parent
75f5090d6a
commit
dd80a79c3c
@ -62,7 +62,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class condition {
|
class condition {
|
||||||
pthread_cond_t cond_ = PTHREAD_COND_INITIALIZER;
|
pthread_cond_t cond_ = PTHREAD_COND_INITIALIZER;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool open() {
|
bool open() {
|
||||||
@ -163,8 +163,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close(handle_t h) {
|
void close(handle_t h) {
|
||||||
if (h == invalid()) return;
|
|
||||||
if (opened_.fetch_sub(1, std::memory_order_release) == 1) {
|
if (opened_.fetch_sub(1, std::memory_order_release) == 1) {
|
||||||
|
if (h == invalid()) return;
|
||||||
sem_.close();
|
sem_.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "rw_lock.h"
|
#include "rw_lock.h"
|
||||||
#include "pool_alloc.h"
|
#include "pool_alloc.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#include "platform/to_tchar.h"
|
#include "platform/to_tchar.h"
|
||||||
#include "platform/detail.h"
|
#include "platform/detail.h"
|
||||||
@ -22,10 +23,13 @@ public:
|
|||||||
return s1.h_ == s2.h_;
|
return s1.h_ == s2.h_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Str>
|
bool open(std::string && name, long count = 0, long limit = LONG_MAX) {
|
||||||
semaphore& open(Str const & name, long count = 0, long limit = LONG_MAX) {
|
h_ = ::CreateSemaphore(NULL, count, limit, ipc::detail::to_tchar(std::move(name)).c_str());
|
||||||
h_ = ::CreateSemaphore(NULL, count, limit, name.c_str());
|
if (h_ == NULL) {
|
||||||
return *this;
|
ipc::error("fail CreateSemaphore[%lu]: %s\n", ::GetLastError(), name.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
@ -46,82 +50,132 @@ class mutex : public semaphore {
|
|||||||
using semaphore::post;
|
using semaphore::post;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename Str>
|
bool open(std::string && name) {
|
||||||
mutex& open(Str const & name) {
|
return semaphore::open(std::move(name), 1, 1);
|
||||||
semaphore::open(name, 1, 1);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lock () { return semaphore::wait(); }
|
bool lock () { return semaphore::wait(); }
|
||||||
bool unlock() { return semaphore::post(); }
|
bool unlock() { return semaphore::post(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class condition {
|
||||||
|
mutex lock_;
|
||||||
|
semaphore sema_, handshake_;
|
||||||
|
|
||||||
|
long volatile * counter_ = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend bool operator==(condition const & c1, condition const & c2) {
|
||||||
|
return c1.counter_ == c2.counter_;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(condition const & c1, condition const & c2) {
|
||||||
|
return !(c1 == c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open(std::string const & name, long volatile * counter) {
|
||||||
|
if (lock_ .open(name + "__COND_MTX__") &&
|
||||||
|
sema_ .open(name + "__COND_SEM__") &&
|
||||||
|
handshake_.open(name + "__COND_HAN__")) {
|
||||||
|
counter_ = counter;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
handshake_.close();
|
||||||
|
sema_ .close();
|
||||||
|
lock_ .close();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Mutex, typename F>
|
||||||
|
bool wait_if(Mutex& mtx, F&& pred) {
|
||||||
|
{
|
||||||
|
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lock_);
|
||||||
|
if (!std::forward<F>(pred)()) return true;
|
||||||
|
++ *counter_;
|
||||||
|
}
|
||||||
|
mtx.unlock();
|
||||||
|
bool ret_s = sema_.wait();
|
||||||
|
bool ret_h = handshake_.post();
|
||||||
|
mtx.lock();
|
||||||
|
return ret_s && ret_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool notify() {
|
||||||
|
bool ret_s = true, ret_h = true;
|
||||||
|
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lock_);
|
||||||
|
if (*counter_ > 0) {
|
||||||
|
ret_s = sema_.post();
|
||||||
|
-- *counter_;
|
||||||
|
ret_h = handshake_.wait();
|
||||||
|
}
|
||||||
|
return ret_s && ret_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool broadcast() {
|
||||||
|
bool ret_s = true, ret_h = true;
|
||||||
|
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lock_);
|
||||||
|
if (*counter_ > 0) {
|
||||||
|
ret_s = sema_.post(*counter_);
|
||||||
|
do {
|
||||||
|
-- *counter_;
|
||||||
|
bool rh = handshake_.wait();
|
||||||
|
ret_h = ret_h && rh;
|
||||||
|
} while (*counter_ > 0);
|
||||||
|
}
|
||||||
|
return ret_s && ret_h;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class waiter {
|
class waiter {
|
||||||
long volatile counter_ = 0;
|
long volatile counter_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using handle_t = std::tuple<semaphore, semaphore, mutex>;
|
using handle_t = condition;
|
||||||
|
|
||||||
static handle_t invalid() {
|
static handle_t invalid() {
|
||||||
return handle_t {};
|
return condition {};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
semaphore& sem(handle_t& h) { return std::get<0>(h); }
|
|
||||||
semaphore& han(handle_t& h) { return std::get<1>(h); }
|
|
||||||
mutex & mtx(handle_t& h) { return std::get<2>(h); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
handle_t open(char const * name) {
|
handle_t open(char const * name) {
|
||||||
if (name == nullptr || name[0] == '\0') return invalid();
|
if (name == nullptr || name[0] == '\0') {
|
||||||
std::string n = name;
|
return invalid();
|
||||||
return handle_t {
|
}
|
||||||
semaphore {}.open(ipc::detail::to_tchar(n + "__SEM__")),
|
condition cond;
|
||||||
semaphore {}.open(ipc::detail::to_tchar(n + "__HAN__")),
|
if (cond.open(name, &counter_)) {
|
||||||
mutex {}.open(ipc::detail::to_tchar(n + "__MTX__"))
|
return cond;
|
||||||
};
|
}
|
||||||
|
return invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(handle_t& h) {
|
void close(handle_t& h) {
|
||||||
if (h == invalid()) return;
|
if (h == invalid()) return;
|
||||||
mtx(h).close();
|
h.close();
|
||||||
han(h).close();
|
|
||||||
sem(h).close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
bool wait_if(handle_t& h, F&& pred) {
|
bool wait_if(handle_t& h, F&& pred) {
|
||||||
if (h == invalid()) return false;
|
if (h == invalid()) return false;
|
||||||
{
|
|
||||||
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(mtx(h));
|
class non_mutex {
|
||||||
if (!std::forward<F>(pred)()) return true;
|
public:
|
||||||
++ counter_;
|
void lock () {}
|
||||||
}
|
void unlock() {}
|
||||||
bool ret_s = sem(h).wait();
|
} nm;
|
||||||
bool ret_h = han(h).post();
|
|
||||||
return ret_s && ret_h;
|
return h.wait_if(nm, std::forward<F>(pred));
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify(handle_t& h) {
|
void notify(handle_t& h) {
|
||||||
if (h == invalid()) return;
|
if (h == invalid()) return;
|
||||||
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(mtx(h));
|
h.notify();
|
||||||
if (counter_ > 0) {
|
|
||||||
sem(h).post();
|
|
||||||
-- counter_;
|
|
||||||
han(h).wait();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void broadcast(handle_t& h) {
|
void broadcast(handle_t& h) {
|
||||||
if (h == invalid()) return;
|
if (h == invalid()) return;
|
||||||
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(mtx(h));
|
h.broadcast();
|
||||||
if (counter_ > 0) {
|
|
||||||
sem(h).post(counter_);
|
|
||||||
do {
|
|
||||||
-- counter_;
|
|
||||||
han(h).wait();
|
|
||||||
} while (counter_ > 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user