mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
实现condition_win
This commit is contained in:
parent
0cccdac868
commit
c1ceaa657a
@ -1,52 +1,116 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
#include "libipc/utility/log.h"
|
#include "libipc/utility/log.h"
|
||||||
|
#include "libipc/utility/scope_guard.h"
|
||||||
|
#include "libipc/platform/detail.h"
|
||||||
#include "libipc/mutex.h"
|
#include "libipc/mutex.h"
|
||||||
|
#include "libipc/semaphore.h"
|
||||||
|
#include "libipc/shm.h"
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
namespace sync {
|
namespace sync {
|
||||||
|
|
||||||
class condition {
|
class condition {
|
||||||
HANDLE h_ = NULL;
|
ipc::sync::semaphore sem_;
|
||||||
|
ipc::sync::mutex lock_;
|
||||||
|
ipc::shm::handle shm_;
|
||||||
|
|
||||||
|
std::int32_t &counter() {
|
||||||
|
return *static_cast<std::int32_t *>(shm_.get());
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
condition() noexcept = default;
|
condition() = default;
|
||||||
~condition() noexcept = default;
|
~condition() noexcept = default;
|
||||||
|
|
||||||
HANDLE native() const noexcept {
|
auto native() noexcept {
|
||||||
return h_;
|
return sem_.native();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto native() const noexcept {
|
||||||
|
return sem_.native();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid() const noexcept {
|
bool valid() const noexcept {
|
||||||
return h_ != NULL;
|
return sem_.valid() && lock_.valid() && shm_.valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open(char const *name) noexcept {
|
bool open(char const *name) noexcept {
|
||||||
close();
|
close();
|
||||||
|
if (!sem_.open((std::string{"_cond_sem_"} + name).c_str())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto finally_sem = ipc::guard([this] { sem_.close(); }); // close when failed
|
||||||
|
if (!lock_.open((std::string{"_cond_lock_"} + name).c_str())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto finally_lock = ipc::guard([this] { lock_.close(); }); // close when failed
|
||||||
|
if (!shm_.acquire((std::string{"_cond_shm_"} + name).c_str(), sizeof(std::int32_t))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally_lock.dismiss();
|
||||||
|
finally_sem.dismiss();
|
||||||
return valid();
|
return valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() noexcept {
|
void close() noexcept {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
::CloseHandle(h_);
|
sem_.close();
|
||||||
h_ = NULL;
|
lock_.close();
|
||||||
|
shm_.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept {
|
bool wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept {
|
||||||
return true;
|
if (!valid()) return false;
|
||||||
|
auto &cnt = counter();
|
||||||
|
{
|
||||||
|
IPC_UNUSED_ std::lock_guard<ipc::sync::mutex> guard {lock_};
|
||||||
|
cnt = (cnt < 0) ? 1 : cnt + 1;
|
||||||
|
}
|
||||||
|
DWORD ms = (tm == invalid_value) ? INFINITE : static_cast<DWORD>(tm);
|
||||||
|
/**
|
||||||
|
* @see
|
||||||
|
* - https://www.microsoft.com/en-us/research/wp-content/uploads/2004/12/ImplementingCVs.pdf
|
||||||
|
* - https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-signalobjectandwait
|
||||||
|
*/
|
||||||
|
bool rs = ::SignalObjectAndWait(mtx.native(), sem_.native(), ms, FALSE) == WAIT_OBJECT_0;
|
||||||
|
bool rl = mtx.lock(); // INFINITE
|
||||||
|
if (!rs) {
|
||||||
|
IPC_UNUSED_ std::lock_guard<ipc::sync::mutex> guard {lock_};
|
||||||
|
cnt -= 1;
|
||||||
|
}
|
||||||
|
return rs && rl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool notify() noexcept {
|
bool notify() noexcept {
|
||||||
return true;
|
if (!valid()) return false;
|
||||||
|
auto &cnt = counter();
|
||||||
|
if (!lock_.lock()) return false;
|
||||||
|
bool ret = false;
|
||||||
|
if (cnt > 0) {
|
||||||
|
ret = sem_.post(1);
|
||||||
|
cnt -= 1;
|
||||||
|
}
|
||||||
|
return lock_.unlock() && ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool broadcast() noexcept {
|
bool broadcast() noexcept {
|
||||||
return true;
|
if (!valid()) return false;
|
||||||
|
auto &cnt = counter();
|
||||||
|
if (!lock_.lock()) return false;
|
||||||
|
bool ret = false;
|
||||||
|
if (cnt > 0) {
|
||||||
|
ret = sem_.post(cnt);
|
||||||
|
cnt = 0;
|
||||||
|
}
|
||||||
|
return lock_.unlock() && ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ constexpr auto to_tchar(ipc::string &&str) -> IsSameChar<T, ipc::string, ipc::st
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* codecvt_utf8_utf16/std::wstring_convert is deprecated
|
* @remarks codecvt_utf8_utf16/std::wstring_convert is deprecated
|
||||||
* @see https://codingtidbit.com/2020/02/09/c17-codecvt_utf8-is-deprecated/
|
* @see https://codingtidbit.com/2020/02/09/c17-codecvt_utf8-is-deprecated/
|
||||||
* https://stackoverflow.com/questions/42946335/deprecated-header-codecvt-replacement
|
* https://stackoverflow.com/questions/42946335/deprecated-header-codecvt-replacement
|
||||||
* https://en.cppreference.com/w/cpp/locale/codecvt/in
|
* https://en.cppreference.com/w/cpp/locale/codecvt/in
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <array>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
@ -129,8 +130,10 @@ TEST(Sync, Condition) {
|
|||||||
std::printf("test-cond-%d: %d\n", num, val);
|
std::printf("test-cond-%d: %d\n", num, val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::thread test_cond1 {job, 1};
|
std::array<std::thread, 10> test_conds;
|
||||||
std::thread test_cond2 {job, 2};
|
for (int i = 0; i < (int)test_conds.size(); ++i) {
|
||||||
|
test_conds[i] = std::thread{job, i};
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 1; i < 100; ++i) {
|
for (int i = 1; i < 100; ++i) {
|
||||||
{
|
{
|
||||||
@ -150,11 +153,11 @@ TEST(Sync, Condition) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<ipc::sync::mutex> guard {lock};
|
std::lock_guard<ipc::sync::mutex> guard {lock};
|
||||||
|
for (int i = 0; i < (int)test_conds.size(); ++i) {
|
||||||
que.push_back(0);
|
que.push_back(0);
|
||||||
que.push_back(0);
|
}
|
||||||
}
|
}
|
||||||
cond.broadcast();
|
cond.broadcast();
|
||||||
|
|
||||||
test_cond1.join();
|
for (auto &t : test_conds) t.join();
|
||||||
test_cond2.join();
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user