public inbox for [email protected]
 help / color / mirror / Atom feed
From: Ammar Faizi <[email protected]>
To: Alviro Iskandar Setiawan <[email protected]>
Cc: Ammar Faizi <[email protected]>,
	Muhammad Rizki <[email protected]>,
	Kanna Scarlet <[email protected]>,
	GNU/Weeb Mailing List <[email protected]>
Subject: [PATCH v1 20/22] chnet: Use busy-waiting for signal waiter
Date: Sun, 21 Aug 2022 18:24:51 +0700	[thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>

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 <[email protected]>
---
 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<typename Rep, typename Period>
-	inline bool WaitFor(const std::chrono::duration<Rep, Period> &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<std::mutex> lock_;
-	std::condition_variable cond_;
 	std::atomic<bool> is_signaled_;
 };
 
-- 
Ammar Faizi


  parent reply	other threads:[~2022-08-21 11:26 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-21 11:24 [PATCH v1 00/22] ncns updates Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 01/22] chnet: Add initial request body support Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 02/22] chnet: node: Add set_user_data support on SQE Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 03/22] tests/js/ring: Update the unit test to utilize set_user_data Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 04/22] binding.gyp: Add `-ggdb3` flag for better debugging experience Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 05/22] binding.gyp: Add `-Wno-enum-constexpr-conversion` flag Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 06/22] chnet: node: Add set_method function to set HTTP method Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 07/22] chnet: node: Add get_error function to return the error string Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 08/22] chnet: node: Add set_payload function to set HTTP req body Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 09/22] tests/js/ring: Add simple HTTP POST request example in NodeJS Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 10/22] chnet: Split construct URL req creation into a new function Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 11/22] chnet: Add set request header support Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 12/22] chnet: node: Fix unused variable warning Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 13/22] chnet: node: Add set request header function in NodeJS Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 14/22] tests/js/ring: Add more set header function test Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 15/22] chnet: node: Don't use static counter for data ID Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 16/22] tests/js/ring: Add JavaScript class wrapper example Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 17/22] chnet: Initial chunked request body support Ammar Faizi
2022-08-21 22:13   ` Alviro Iskandar Setiawan
2022-08-22  3:08     ` Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 18/22] chnet: Rework the chunked request body interface Ammar Faizi
2022-08-21 22:20   ` Alviro Iskandar Setiawan
2022-08-21 11:24 ` [PATCH v1 19/22] chnet: ring: Refactor the ring completely Ammar Faizi
2022-08-21 11:24 ` Ammar Faizi [this message]
2022-08-21 22:29   ` [PATCH v1 20/22] chnet: Use busy-waiting for signal waiter Alviro Iskandar Setiawan
2022-08-21 11:24 ` [PATCH v1 21/22] chnet: ring: Bump max_entry to 2G Ammar Faizi
2022-08-21 11:24 ` [PATCH v1 22/22] tests/cpp: Delete basic.cpp as it's no longer relevant Ammar Faizi
2022-08-21 22:21   ` Alviro Iskandar Setiawan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox