@@ -20,6 +20,8 @@ ReqWrap<T>::ReqWrap(Environment* env,
2020 // FIXME(bnoordhuis) The fact that a reinterpret_cast is needed is
2121 // arguably a good indicator that there should be more than one queue.
2222 env->req_wrap_queue ()->PushBack (reinterpret_cast <ReqWrap<uv_req_t >*>(this ));
23+
24+ Reset ();
2325}
2426
2527template <typename T>
@@ -33,14 +35,21 @@ void ReqWrap<T>::Dispatched() {
3335 req_.data = this ;
3436}
3537
38+ template <typename T>
39+ void ReqWrap<T>::Reset() {
40+ original_callback_ = nullptr ;
41+ req_.data = nullptr ;
42+ }
43+
3644template <typename T>
3745ReqWrap<T>* ReqWrap<T>::from_req(T* req) {
3846 return ContainerOf (&ReqWrap<T>::req_, req);
3947}
4048
4149template <typename T>
4250void ReqWrap<T>::Cancel() {
43- uv_cancel (reinterpret_cast <uv_req_t *>(&req_));
51+ if (req_.data == this ) // Only cancel if already dispatched.
52+ uv_cancel (reinterpret_cast <uv_req_t *>(&req_));
4453}
4554
4655// Below is dark template magic designed to invoke libuv functions that
@@ -95,7 +104,7 @@ struct CallLibuvFunction<ReqT, void(*)(ReqT*, Args...)> {
95104template <typename ReqT, typename T>
96105struct MakeLibuvRequestCallback {
97106 static T For (ReqWrap<ReqT>* req_wrap, T v) {
98- static_assert (!std::is_function <T>::value,
107+ static_assert (!is_callable <T>::value,
99108 " MakeLibuvRequestCallback missed a callback" );
100109 return v;
101110 }
@@ -109,6 +118,7 @@ struct MakeLibuvRequestCallback<ReqT, void(*)(ReqT*, Args...)> {
109118
110119 static void Wrapper (ReqT* req, Args... args) {
111120 ReqWrap<ReqT>* req_wrap = ContainerOf (&ReqWrap<ReqT>::req_, req);
121+ req_wrap->env ()->DecreaseWaitingRequestCounter ();
112122 F original_callback = reinterpret_cast <F>(req_wrap->original_callback_ );
113123 original_callback (req, args...);
114124 }
@@ -128,23 +138,26 @@ int ReqWrap<T>::Dispatch(LibuvFunction fn, Args... args) {
128138
129139 // This expands as:
130140 //
131- // return fn(env()->event_loop(), req(), arg1, arg2, Wrapper, arg3, ...)
132- // ^ ^ ^
133- // | | |
134- // \-- Omitted if `fn` has no | |
135- // first `uv_loop_t*` argument | |
136- // | |
137- // A function callback whose first argument | |
138- // matches the libuv request type is replaced ---/ |
139- // by the `Wrapper` method defined above |
140- // |
141- // Other (non-function) arguments are passed -----/
142- // through verbatim
143- return CallLibuvFunction<T, LibuvFunction>::Call (
141+ // int err = fn(env()->event_loop(), req(), arg1, arg2, Wrapper, arg3, ...)
142+ // ^ ^ ^
143+ // | | |
144+ // \-- Omitted if `fn` has no | |
145+ // first `uv_loop_t*` argument | |
146+ // | |
147+ // A function callback whose first argument | |
148+ // matches the libuv request type is replaced ---/ |
149+ // by the `Wrapper` method defined above |
150+ // |
151+ // Other (non-function) arguments are passed -----/
152+ // through verbatim
153+ int err = CallLibuvFunction<T, LibuvFunction>::Call (
144154 fn,
145155 env ()->event_loop (),
146156 req (),
147157 MakeLibuvRequestCallback<T, Args>::For (this , args)...);
158+ if (err >= 0 )
159+ env ()->IncreaseWaitingRequestCounter ();
160+ return err;
148161}
149162
150163} // namespace node
0 commit comments