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 02/22] chnet: node: Add set_user_data support on SQE
Date: Sun, 21 Aug 2022 18:24:33 +0700	[thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>

Make it possible to track the corresponding SQE when we are iterating
through the CQE.

Signed-off-by: Ammar Faizi <[email protected]>
---
 chnet/chnet_node.cc | 193 ++++++++++++++++++++++++++++++--------------
 chnet/chnet_node.h  |   6 --
 2 files changed, 131 insertions(+), 68 deletions(-)

diff --git a/chnet/chnet_node.cc b/chnet/chnet_node.cc
index 06f624e..7d0c6bc 100644
--- a/chnet/chnet_node.cc
+++ b/chnet/chnet_node.cc
@@ -1,16 +1,38 @@
 
 #include "chnet_node.h"
 
-#ifdef DEBUG_MODE
-#define PR_DEBUG(...)		\
-do {				\
-	printf("Debug: ");	\
-	printf(__VA_ARGS__);	\
-	putchar('\n');		\
-} while (0);
-#else
-#define PR_DEBUG(...) do { } while (0)
-#endif
+class NodeCHNetRing {
+public:
+	inline NodeCHNetRing(uint32_t entry):
+		ring_(entry)
+	{
+	}
+
+	CNRingCtx		ring_;
+	Napi::ObjectReference	ref_;
+};
+
+class NodeCNRingSQE {
+public:
+	inline NodeCNRingSQE(NodeCHNetRing *ring, CNRingSQE *sqe)
+	{
+		sqe_ = sqe;
+		ring_ = ring;
+	}
+
+	CNRingSQE		*sqe_;
+	NodeCHNetRing		*ring_;
+};
+
+struct NodeSQData {
+	uint32_t		id_;
+	NodeCHNetRing		*ring_;
+};
+
+class NodeCHNet {
+public:
+	CHNet			ch_;
+};
 
 static inline void throw_js_exception(Napi::Env &env, const char *err_msg)
 {
@@ -24,18 +46,14 @@ static inline void obj_add_func(Napi::Env &env, Napi::Object &obj,
 	obj[name] = Napi::Function::New(env, func, name, data);
 }
 
-struct sqe_udata {
-	void	*ptr;
-};
-
 static void CHN_SQEPrepNop(const Napi::CallbackInfo &info)
 {
-	CNRingSQE *sqe = (CNRingSQE *)info.Data();
+	NodeCNRingSQE *nsqe = (NodeCNRingSQE *)info.Data();
 
-	sqe->PrepNop();
+	nsqe->sqe_->PrepNop();
 }
 
-static CHNetNode *CHN_PrepGetCHObj(Napi::Env &env, const Napi::Value &arg)
+static NodeCHNet *CHN_PrepGetCHObj(Napi::Env &env, const Napi::Value &arg)
 {
 	Napi::Value ch_in_obj;
 	Napi::Object obj;
@@ -52,15 +70,15 @@ static CHNetNode *CHN_PrepGetCHObj(Napi::Env &env, const Napi::Value &arg)
 		return nullptr;
 	}
 
-	return (CHNetNode *)(uintptr_t)
+	return (NodeCHNet *)(uintptr_t)
 		ch_in_obj.As<Napi::Number>().Int64Value();
 }
 
 static void CHN_SQEPrepStart(const Napi::CallbackInfo &info)
 {
 	Napi::Env env = info.Env();
-	CNRingSQE *sqe;
-	CHNetNode *ch;
+	NodeCNRingSQE *nsqe;
+	NodeCHNet *ch;
 	CHNet *chn;
 
 	if (unlikely(info.Length() != 1 || !info[0].IsObject())) {
@@ -73,16 +91,16 @@ static void CHN_SQEPrepStart(const Napi::CallbackInfo &info)
 		return;
 
 	chn = &ch->ch_;
-	sqe = (CNRingSQE *)info.Data();
-	sqe->PrepStart(chn);
+	nsqe = (NodeCNRingSQE *)info.Data();
+	nsqe->sqe_->PrepStart(chn);
 }
 
 static void CHN_SQEPrepRead(const Napi::CallbackInfo &info)
 {
 	Napi::Env env = info.Env();
 	int32_t read_size;
-	CNRingSQE *sqe;
-	CHNetNode *ch;
+	NodeCNRingSQE *nsqe;
+	NodeCHNet *ch;
 	CHNet *chn;
 
 	if (unlikely(info.Length() != 2 || !info[0].IsObject() ||
@@ -97,69 +115,116 @@ static void CHN_SQEPrepRead(const Napi::CallbackInfo &info)
 
 	read_size = info[1].As<Napi::Number>().Int32Value();
 	chn = &ch->ch_;
-	sqe = (CNRingSQE *)info.Data();
-	sqe->PrepRead(chn, read_size);
+	nsqe = (NodeCNRingSQE *)info.Data();
+	nsqe->sqe_->PrepRead(chn, read_size);
 }
 
-static void CHN_SQESetUserData(const Napi::CallbackInfo &info)
+static Napi::Value CHN_SQESetUserData(const Napi::CallbackInfo &info)
 {
-	(void)info;
+	static std::atomic<uint32_t> count;
+	Napi::Env env = info.Env();
+	struct NodeSQData *data;
+	NodeCNRingSQE *nsqe;
+
+	if (unlikely(info.Length() != 1)) {
+		throw_js_exception(env, "sqe.set_user_data must be given exactly one argument");
+		return env.Null();
+	}
+
+	nsqe = (NodeCNRingSQE *)info.Data();
+	data = new struct NodeSQData;
+	data->ring_ = nsqe->ring_;
+	data->id_   = count++ & nsqe->ring_->ring_.cq_mask_;
+	nsqe->ring_->ref_.Get("__udata")
+		.As<Napi::Object>()[data->id_] = info[0];
+	nsqe->sqe_->SetUserDataPtr(data);
+	return info[0];
 }
 
-static Napi::Object BuildSQEObject(Napi::Env &env, CNRingSQE *sqe)
+static void CHN_SQEDestruct(Napi::Env env, NodeCNRingSQE *sqe)
+{
+	delete sqe;
+	(void)env;
+}
+
+static Napi::Object BuildSQEObject(Napi::Env &env, NodeCHNetRing *ring,
+				   CNRingSQE *sqe)
 {
 	Napi::Object obj = Napi::Object::New(env);
+	NodeCNRingSQE *nsqe;
 
-	obj_add_func(env, obj, sqe, CHN_SQEPrepNop, "prep_nop");
-	obj_add_func(env, obj, sqe, CHN_SQEPrepStart, "prep_start");
-	obj_add_func(env, obj, sqe, CHN_SQEPrepRead, "prep_read");
-	obj_add_func(env, obj, sqe, CHN_SQESetUserData, "set_user_data");
 	sqe->SetUserData(0);
+	nsqe = new NodeCNRingSQE(ring, sqe);
+	obj_add_func(env, obj, nsqe, CHN_SQEPrepNop, "prep_nop");
+	obj_add_func(env, obj, nsqe, CHN_SQEPrepStart, "prep_start");
+	obj_add_func(env, obj, nsqe, CHN_SQEPrepRead, "prep_read");
+	obj_add_func(env, obj, nsqe, CHN_SQESetUserData, "set_user_data");
+	obj.AddFinalizer(CHN_SQEDestruct, nsqe);
 	return obj;
 }
 
 static Napi::Value CHN_RingGetSQE(const Napi::CallbackInfo &info)
 {
 	Napi::Env env = info.Env();
-	CNRingCtx *ring;
+	NodeCHNetRing *ring;
 	CNRingSQE *sqe;
 
-	ring = (CNRingCtx *)info.Data();
-	sqe = ring->GetSQE();
+	ring = (NodeCHNetRing *)info.Data();
+	sqe = ring->ring_.GetSQE();
 	if (unlikely(!sqe))
 		return env.Null();
 
-	return BuildSQEObject(env, sqe);
+	return BuildSQEObject(env, ring, sqe);
 }
 
 static Napi::Value CHN_RingSubmitSQE(const Napi::CallbackInfo &info)
 {
 	Napi::Env env = info.Env();
-	CNRingCtx *ring;
+	NodeCHNetRing *ring;
 
-	ring = (CNRingCtx *)info.Data();
-	return Napi::Number::New(env, ring->SubmitSQE());
+	ring = (NodeCHNetRing *)info.Data();
+	return Napi::Number::New(env, ring->ring_.SubmitSQE());
 }
 
 static void CHN_RingWaitCQE(const Napi::CallbackInfo &info)
 {
 	uint32_t to_wait;
-	CNRingCtx *ring;
+	NodeCHNetRing *ring;
 
 	if (unlikely(info.Length() < 1 || !info[0].IsNumber()))
 		to_wait = 1;
 	else
 		to_wait = info[0].ToNumber().Uint32Value();
 
-	ring = (CNRingCtx *)info.Data();
-	ring->WaitCQE(to_wait);
+	ring = (NodeCHNetRing *)info.Data();
+	ring->ring_.WaitCQE(to_wait);
+}
+
+static void CHN_CQEDestruct(Napi::Env env, NodeSQData *data)
+{
+	/*
+	 * TODO(ammarfaizi2): Clean up user_data from the ring
+	 *                    when it's no longer used.
+	 */
+
+	// data->ring_->ref_.Get("__udata").As<Napi::Object>()
+	// 		.Delete(data->id_);
+	delete data;
+	(void)env;
 }
 
 static Napi::Object BuildCQEObject(Napi::Env &env, CNRingCQE *cqe)
 {
 	Napi::Object obj = Napi::Object::New(env);
+	NodeSQData *data = (NodeSQData *) cqe->GetUserDataPtr();
 
 	obj["res"] = Napi::Number::New(env, cqe->res);
+
+	if (data) {
+		obj["user_data"] = data->ring_->ref_.Get("__udata")
+					.As<Napi::Object>().Get(data->id_);
+		obj.AddFinalizer(CHN_CQEDestruct, data);
+	}
 	return obj;
 }
 
@@ -171,7 +236,7 @@ static Napi::Value CHN_RingForEachCQE(const Napi::CallbackInfo &info)
 	Napi::Env env = info.Env();
 	Napi::Function callback;
 	uint32_t head, i;
-	CNRingCtx *ring;
+	NodeCHNetRing *ring;
 	CNRingCQE *cqe;
 
 	if (unlikely(info.Length() != 1 || !info[0].IsFunction())) {
@@ -182,8 +247,8 @@ static Napi::Value CHN_RingForEachCQE(const Napi::CallbackInfo &info)
 	callback = info[0].As<Napi::Function>();
 
 	i = 0;
-	ring = (CNRingCtx *)info.Data();
-	chnring_for_each_cqe(ring, head, cqe) {
+	ring = (NodeCHNetRing *)info.Data();
+	chnring_for_each_cqe(&ring->ring_, head, cqe) {
 		Napi::Object cqe_obj = BuildCQEObject(env, cqe);
 
 		callback.Call({cqe_obj});
@@ -199,33 +264,35 @@ static void CHN_RingCQAdvance(const Napi::CallbackInfo &info)
 		"ring.cq_advance must be given exactly an integer argument";
 
 	Napi::Env env = info.Env();
-	CNRingCtx *ring;
+	NodeCHNetRing *ring;
 
 	if (unlikely(info.Length() < 1 || !info[0].IsNumber())) {
 		throw_js_exception(env, err_msg);
 		return;
 	}
 
-	ring = (CNRingCtx *)info.Data();
-	ring->CQAdvance(info[0].ToNumber().Uint32Value());
+	ring = (NodeCHNetRing *)info.Data();
+	ring->ring_.CQAdvance(info[0].ToNumber().Uint32Value());
 }
 
-static void CHN_RingDestruct(Napi::Env env, CNRingCtx *ring)
+static void CHN_RingDestruct(Napi::Env env, NodeCHNetRing *ring)
 {
 	delete ring;
 	(void)env;
 }
 
-static inline Napi::Value _CHN_CreateRing(Napi::Env &env, CNRingCtx *ring)
+static inline Napi::Value _CHN_CreateRing(Napi::Env &env, NodeCHNetRing *ring)
 {
 	Napi::Object obj = Napi::Object::New(env);
 
+	obj["__udata"] = Napi::Object::New(env);
 	obj_add_func(env, obj, ring, CHN_RingGetSQE, "get_sqe");
 	obj_add_func(env, obj, ring, CHN_RingSubmitSQE, "submit_sqe");
 	obj_add_func(env, obj, ring, CHN_RingWaitCQE, "wait_cqe");
 	obj_add_func(env, obj, ring, CHN_RingForEachCQE, "for_each_cqe");
 	obj_add_func(env, obj, ring, CHN_RingCQAdvance, "cq_advance");
 	obj.AddFinalizer(CHN_RingDestruct, ring);
+	ring->ref_ = Napi::Persistent(obj);
 	return obj;
 }
 
@@ -235,7 +302,7 @@ static Napi::Value CHN_CreateRing(const Napi::CallbackInfo &info)
 		"chnet.create_ring must be given exactly a positive integer argument";
 
 	Napi::Env env = info.Env();
-	CNRingCtx *ring;
+	NodeCHNetRing *ring;
 	uint32_t entry;
 
 	if (unlikely(info.Length() < 1 || !info[0].IsNumber())) {
@@ -244,7 +311,7 @@ static Napi::Value CHN_CreateRing(const Napi::CallbackInfo &info)
 	}
 
 	entry = info[0].ToNumber().Uint32Value();
-	ring = new CNRingCtx(entry);
+	ring = new NodeCHNetRing(entry);
 	return _CHN_CreateRing(env, ring);
 }
 
@@ -254,14 +321,14 @@ static void CHN_NetSetURL(const Napi::CallbackInfo &info)
 		"chnet.set_url must be given exactly 1 string argument";
 
 	Napi::Env env = info.Env();
-	CHNetNode *ch;
+	NodeCHNet *ch;
 
 	if (unlikely(info.Length() != 1 || !info[0].IsString())) {
 		throw_js_exception(env, err_msg);
 		return;
 	}
 
-	ch = (CHNetNode *)info.Data();
+	ch = (NodeCHNet *)info.Data();
 	const std::string &url = info[0].ToString().Utf8Value();
 	ch->ch_.SetURL(url.c_str());
 }
@@ -269,10 +336,10 @@ static void CHN_NetSetURL(const Napi::CallbackInfo &info)
 static Napi::Value CHN_NetReadBuf(const Napi::CallbackInfo &info)
 {
 	Napi::Env env = info.Env();
-	CHNetNode *ch;
+	NodeCHNet *ch;
 	int ret;
 
-	ch = (CHNetNode *)info.Data();
+	ch = (NodeCHNet *)info.Data();
 	ret = ch->ch_.read_ret();
 	if (ret > 0)
 		return Napi::String::New(env, ch->ch_.read_buf(), (size_t)ret);
@@ -283,13 +350,13 @@ static Napi::Value CHN_NetReadBuf(const Napi::CallbackInfo &info)
 static Napi::Number CHN_NetReadRet(const Napi::CallbackInfo &info)
 {
 	Napi::Env env = info.Env();
-	CHNetNode *ch;
+	NodeCHNet *ch;
 
-	ch = (CHNetNode *)info.Data();
+	ch = (NodeCHNet *)info.Data();
 	return Napi::Number::New(env, ch->ch_.read_ret());
 }
 
-static void CHN_NetDestruct(Napi::Env env, CHNetNode *ch)
+static void CHN_NetDestruct(Napi::Env env, NodeCHNet *ch)
 {
 	delete ch;
 	(void)env;
@@ -299,16 +366,18 @@ static Napi::Object CHN_CreateNet(const Napi::CallbackInfo &info)
 {
 	Napi::Env env = info.Env();
 	Napi::Object obj = Napi::Object::New(env);
-	CHNetNode *ch = new CHNetNode;
+	NodeCHNet *ch = new NodeCHNet;
 	int64_t ch_ptr;
 
 	obj_add_func(env, obj, ch, CHN_NetSetURL, "set_url");
 	obj_add_func(env, obj, ch, CHN_NetReadRet, "read_ret");
 	obj_add_func(env, obj, ch, CHN_NetReadBuf, "read_buf");
 
-	ch_ptr = (int64_t)ch;
+	ch_ptr = (int64_t) (intptr_t) ch;
 	obj["__ch"] = Napi::Number::New(env, ch_ptr);
 	obj.AddFinalizer(CHN_NetDestruct, ch);
+	obj.Seal();
+	obj.Freeze();
 	return obj;
 }
 
diff --git a/chnet/chnet_node.h b/chnet/chnet_node.h
index 336a005..ea0ccb3 100644
--- a/chnet/chnet_node.h
+++ b/chnet/chnet_node.h
@@ -6,10 +6,4 @@
 #include "chnet_ring.h"
 #include "../node-addon-api/napi.h"
 
-class CHNetNode {
-public:
-	CHNetNode(void) = default;
-	CHNet ch_;
-};
-
 #endif /* #ifndef CHNET_NODE_H */
-- 
Ammar Faizi


  parent reply	other threads:[~2022-08-21 11:25 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 ` Ammar Faizi [this message]
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 ` [PATCH v1 20/22] chnet: Use busy-waiting for signal waiter Ammar Faizi
2022-08-21 22:29   ` 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