From 0a1725738846f78a566df56a80191e448eae9076 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Tue, 11 Dec 2018 18:46:04 +0800 Subject: [PATCH] rw_lock (TBD) --- include/ipc.h | 6 +++++ src/ipc.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index 1be111f..2383d7c 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -27,7 +27,13 @@ public: void swap(channel& rhs); channel& operator=(channel rhs); + bool valid(void) const; + char const * name (void) const; + + channel clone(void) const; + bool connect(char const * name); + void disconnect(void); private: class channel_; diff --git a/src/ipc.cpp b/src/ipc.cpp index 9f771a2..6a19374 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -1,7 +1,10 @@ #include +#include +#include #include #include #include +#include #include #include @@ -25,6 +28,42 @@ using guard_t = std::unique_ptr, void(*)(handle_ std::unordered_map h2q__; +class rw_lock { + std::atomic_size_t lc_ { 0 }; + + enum : std::size_t { + w_flag = std::numeric_limits::max() + }; + +public: + void r_lock(void) { + do { + std::size_t old = lc_.load(std::memory_order_acquire); + std::size_t unlocked = old + 1; + if (unlocked && + lc_.compare_exchange_weak(old, unlocked, std::memory_order_acq_rel)) { + break; + } + std::this_thread::yield(); + } while(1); + } + + void r_unlock(void) { + lc_.fetch_sub(1, std::memory_order_release); + } + + void w_lock(void) { + std::size_t expected = 0; + while (!lc_.compare_exchange_weak(expected, w_flag, std::memory_order_acq_rel)) { + std::this_thread::yield(); + } + } + + void w_unlock(void) { + lc_.store(0, std::memory_order_release); + } +} h2q_lc__; + queue_t* queue_of(handle_t h) { if (h == nullptr) { return nullptr; @@ -138,7 +177,8 @@ std::vector recv(handle_t h) { class channel::channel_ { public: - handle_t h_; + handle_t h_ = nullptr; + std::string n_; }; channel::channel(void) @@ -147,7 +187,7 @@ channel::channel(void) channel::channel(char const * name) : channel() { - connect(name); + this->connect(name); } channel::channel(channel&& rhs) @@ -168,8 +208,28 @@ channel& channel::operator=(channel rhs) { return *this; } +bool channel::valid(void) const { + return (p_ != nullptr) && (p_->h_ != nullptr); +} + +char const * channel::name(void) const { + return (p_ == nullptr) ? "" : p_->n_.c_str(); +} + +channel channel::clone(void) const { + return { name() }; +} + bool channel::connect(char const * name) { - return false; + if (p_ == nullptr) return false; + this->disconnect(); + p_->h_ = ipc::connect((p_->n_ = name).c_str()); + return valid(); +} + +void channel::disconnect(void) { + if (!valid()) return; + ipc::disconnect(p_->h_); } } // namespace ipc