Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/nodejs/src/req_wrap-inl.h
$ cat -n /usr/include/nodejs/src/req_wrap-inl.h 1 #ifndef SRC_REQ_WRAP_INL_H_ 2 #define SRC_REQ_WRAP_INL_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include "req_wrap.h" 7 #include "async_wrap-inl.h" 8 #include "uv.h" 9 10 namespace node { 11 12 ReqWrapBase::ReqWrapBase(Environment* env) { 13 CHECK(env->has_run_bootstrapping_code()); 14 env->req_wrap_queue()->PushBack(this); 15 } 16 17 template
18 ReqWrap
::ReqWrap(Environment* env, 19 v8::Local
object, 20 AsyncWrap::ProviderType provider) 21 : AsyncWrap(env, object, provider), 22 ReqWrapBase(env) { 23 MakeWeak(); 24 Reset(); 25 } 26 27 template
28 ReqWrap
::~ReqWrap() {} 29 30 template
31 void ReqWrap
::Dispatched() { 32 req_.data = this; 33 } 34 35 template
36 void ReqWrap
::Reset() { 37 original_callback_ = nullptr; 38 req_.data = nullptr; 39 } 40 41 template
42 ReqWrap
* ReqWrap
::from_req(T* req) { 43 return ContainerOf(&ReqWrap
::req_, req); 44 } 45 46 template
47 void ReqWrap
::Cancel() { 48 if (req_.data == this) // Only cancel if already dispatched. 49 uv_cancel(reinterpret_cast
(&req_)); 50 } 51 52 template
53 AsyncWrap* ReqWrap
::GetAsyncWrap() { 54 return this; 55 } 56 57 // Below is dark template magic designed to invoke libuv functions that 58 // initialize uv_req_t instances in a unified fashion, to allow easier 59 // tracking of active/inactive requests. 60 61 // Invoke a generic libuv function that initializes uv_req_t instances. 62 // This is, unfortunately, necessary since they come in three different 63 // variants that can not all be invoked in the same way: 64 // - int uv_foo(uv_loop_t* loop, uv_req_t* request, ...); 65 // - int uv_foo(uv_req_t* request, ...); 66 // - void uv_foo(uv_req_t* request, ...); 67 template
68 struct CallLibuvFunction; 69 70 // Detect `int uv_foo(uv_loop_t* loop, uv_req_t* request, ...);`. 71 template
72 struct CallLibuvFunction
{ 73 using T = int(*)(uv_loop_t*, ReqT*, Args...); 74 template
75 static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) { 76 return fn(loop, req, args...); 77 } 78 }; 79 80 // Detect `int uv_foo(uv_req_t* request, ...);`. 81 template
82 struct CallLibuvFunction
{ 83 using T = int(*)(ReqT*, Args...); 84 template
85 static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) { 86 return fn(req, args...); 87 } 88 }; 89 90 // Detect `void uv_foo(uv_req_t* request, ...);`. 91 template
92 struct CallLibuvFunction
{ 93 using T = void(*)(ReqT*, Args...); 94 template
95 static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) { 96 fn(req, args...); 97 return 0; 98 } 99 }; 100 101 // This is slightly darker magic: This template is 'applied' to each parameter 102 // passed to the libuv function. If the parameter type (aka `T`) is a 103 // function type, it is assumed that this it is the request callback, and a 104 // wrapper that calls the original callback is created. 105 // If not, the parameter is passed through verbatim. 106 template
107 struct MakeLibuvRequestCallback { 108 static T For(ReqWrap
* req_wrap, T v) { 109 static_assert(!is_callable
::value, 110 "MakeLibuvRequestCallback missed a callback"); 111 return v; 112 } 113 }; 114 115 // Match the `void callback(uv_req_t*, ...);` signature that all libuv 116 // callbacks use. 117 template
118 struct MakeLibuvRequestCallback
{ 119 using F = void(*)(ReqT* req, Args... args); 120 121 static void Wrapper(ReqT* req, Args... args) { 122 BaseObjectPtr
> req_wrap{ReqWrap
::from_req(req)}; 123 req_wrap->Detach(); 124 req_wrap->env()->DecreaseWaitingRequestCounter(); 125 F original_callback = reinterpret_cast
(req_wrap->original_callback_); 126 original_callback(req, args...); 127 } 128 129 static F For(ReqWrap
* req_wrap, F v) { 130 CHECK_NULL(req_wrap->original_callback_); 131 req_wrap->original_callback_ = 132 reinterpret_cast
::callback_t>(v); 133 return Wrapper; 134 } 135 }; 136 137 template
138 template
139 int ReqWrap
::Dispatch(LibuvFunction fn, Args... args) { 140 Dispatched(); 141 // This expands as: 142 // 143 // int err = fn(env()->event_loop(), req(), arg1, arg2, Wrapper, arg3, ...) 144 // ^ ^ ^ 145 // | | | 146 // \-- Omitted if `fn` has no | | 147 // first `uv_loop_t*` argument | | 148 // | | 149 // A function callback whose first argument | | 150 // matches the libuv request type is replaced ---/ | 151 // by the `Wrapper` method defined above | 152 // | 153 // Other (non-function) arguments are passed -----/ 154 // through verbatim 155 int err = CallLibuvFunction
::Call( 156 fn, 157 env()->event_loop(), 158 req(), 159 MakeLibuvRequestCallback
::For(this, args)...); 160 if (err >= 0) { 161 ClearWeak(); 162 env()->IncreaseWaitingRequestCounter(); 163 } 164 return err; 165 } 166 167 } // namespace node 168 169 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 170 171 #endif // SRC_REQ_WRAP_INL_H_
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™