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
next prev 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