From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on gnuweeb.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=ALL_TRUSTED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,NO_DNS_FOR_FROM,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.6 Received: from localhost.localdomain (unknown [180.246.144.41]) by gnuweeb.org (Postfix) with ESMTPSA id 99FCF80A34; Sun, 21 Aug 2022 11:26:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gnuweeb.org; s=default; t=1661081162; bh=yz9GNixw0KpkizAEBLH4STVkExeoD7suubYYSVKb7Xo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cAFaeXeAlmOf3zlO5GWaUMrges2ahIbsdaaaKOb57Y3PZNNVniO81Bfc8Vc5Y2foH 8OdyFd6F2Chjes8SHclAtQez4GUXFDQ0UJPWI1cLhh6VgKHQezTA+sBDETVg2YMj72 O9Z1OMxEwcPX7tUQDm41P4GEY40uwDes2ceaBLnhXasZZPZ58oaCCxFxA1IkUKGLCn PNKRsOjcfmQftECPNUh95wqVor6sMeTQI0pojMxOrFPLOjtTfVNrhmt8LiLppTPs+7 o2IkEZTQisv2rH8VLXBMatGNbnU4Lxh/t8jGTMPAhL/vxEyOpXzF1pircZj/MBAchP u8YIsnNoAG6Sg== From: Ammar Faizi To: Alviro Iskandar Setiawan Cc: Ammar Faizi , Muhammad Rizki , Kanna Scarlet , GNU/Weeb Mailing List Subject: [PATCH v1 20/22] chnet: Use busy-waiting for signal waiter Date: Sun, 21 Aug 2022 18:24:51 +0700 Message-Id: <20220821112453.3026255-21-ammarfaizi2@gnuweeb.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220821112453.3026255-1-ammarfaizi2@gnuweeb.org> References: <20220821112453.3026255-1-ammarfaizi2@gnuweeb.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Sometimes the worker stuck on sig.Wait(), it seems the signaling mechanism was implemeted wrongly. Just use a busy-waiting which is easier to implement. There is nothing to worry much about wasting CPU cycle as the waiting period must be very short, if it's not short, then something has gone very wrong! Also, PostTask() may fail, handle this failure. Signed-off-by: Ammar Faizi --- chnet/chnet.cc | 48 ++++++++++++++++++++++++++++++++++++------------ chnet/common.h | 20 +++----------------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/chnet/chnet.cc b/chnet/chnet.cc index a34bb18..bafa0fd 100644 --- a/chnet/chnet.cc +++ b/chnet/chnet.cc @@ -315,6 +315,9 @@ void CHNetDelegate::SetRequestHeader(const std::string &key, int CHNetDelegate::Start(void) { + uint32_t try_count = 0; + bool p; + if (unlikely(!url_is_set_)) { err_ = "URL is not set"; return -EINVAL; @@ -322,11 +325,21 @@ int CHNetDelegate::Start(void) Waiter sig; auto *r = thread_.task_runner().get(); - r->PostTask(FROM_HERE, base::BindOnce(&CHNetDelegate::_Start, - base::Unretained(this), &sig)); - sig.Wait(); - started_ = true; - return 0; + do { + p = r->PostTask(FROM_HERE, + base::BindOnce(&CHNetDelegate::_Start, + base::Unretained(this), &sig)); + try_count++; + } while (unlikely(!p && try_count < 10)); + + if (likely(p)) { + sig.Wait(); + started_ = true; + return 0; + } + + err_ = "Resource temporarily unavailable"; + return -EAGAIN; } void CHNetDelegate::_Read(Waiter *sig, int size) @@ -346,19 +359,31 @@ void CHNetDelegate::_Read(Waiter *sig, int size) int CHNetDelegate::Read(int size) { + uint32_t try_count = 0; + bool p; + if (unlikely(!url_req_)) { err_ = "The request has not been started"; return -EINVAL; } read_ret_.store(-EAGAIN); + Waiter sig; auto *r = thread_.task_runner().get(); - r->PostTask(FROM_HERE, base::BindOnce(&CHNetDelegate::_Read, - base::Unretained(this), &sig, - size)); - sig.Wait(); - return read_ret_.load(); + do { + p = r->PostTask(FROM_HERE, base::BindOnce(&CHNetDelegate::_Read, + base::Unretained(this), &sig, size)); + try_count++; + } while (unlikely(!p && try_count < 10)); + + if (likely(p)) { + sig.Wait(); + return read_ret_.load(); + } + + err_ = "Resource temporarily unavailable"; + return -EAGAIN; } void CHNetDelegate::Write(const char *buf, size_t len) @@ -486,8 +511,7 @@ const char *CHNet::read_buf(void) return ch_->read_buf(); } -Waiter::Waiter(void): - lock_(mutex_) +Waiter::Waiter(void) { is_signaled_.store(false); } diff --git a/chnet/common.h b/chnet/common.h index 5e225ed..5b2a3f2 100644 --- a/chnet/common.h +++ b/chnet/common.h @@ -51,30 +51,16 @@ public: inline void Signal(void) { - is_signaled_.store(true); - cond_.notify_one(); + is_signaled_.store(true, std::memory_order_release); } inline void Wait(void) { - cond_.wait(lock_, [this]{ return is_signaled_.load(); }); - is_signaled_.store(false); - } - - template - inline bool WaitFor(const std::chrono::duration &rel_time) - { - bool ret = cond_.wait_for(lock_, rel_time, [this]{ - return is_signaled_.load(); - }); - is_signaled_.store(false); - return ret; + while (!is_signaled_.load(std::memory_order_acquire)) + __asm__ volatile ("pause" ::: "memory"); } private: - std::mutex mutex_; - std::unique_lock lock_; - std::condition_variable cond_; std::atomic is_signaled_; }; -- Ammar Faizi