GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/req_wrap-inl.h Lines: 50 50 100.0 %
Date: 2019-05-05 22:32:45 Branches: 23 44 52.3 %

Line Branch Exec Source
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 "env-inl.h"
9
#include "util-inl.h"
10
#include "uv.h"
11
12
namespace node {
13
14
98055
ReqWrapBase::ReqWrapBase(Environment* env) {
15
98055
  env->req_wrap_queue()->PushBack(this);
16
98055
}
17
18
template <typename T>
19
98055
ReqWrap<T>::ReqWrap(Environment* env,
20
                    v8::Local<v8::Object> object,
21
                    AsyncWrap::ProviderType provider)
22
    : AsyncWrap(env, object, provider),
23
98055
      ReqWrapBase(env) {
24
98055
  Reset();
25
98055
}
26
27
template <typename T>
28
98028
ReqWrap<T>::~ReqWrap() {
29

196056
  CHECK_EQ(false, persistent().IsEmpty());
30

196056
}
31
32
template <typename T>
33
98243
void ReqWrap<T>::Dispatched() {
34
98243
  req_.data = this;
35
98243
}
36
37
template <typename T>
38
98276
void ReqWrap<T>::Reset() {
39
98276
  original_callback_ = nullptr;
40
98276
  req_.data = nullptr;
41
98276
}
42
43
template <typename T>
44
80107
ReqWrap<T>* ReqWrap<T>::from_req(T* req) {
45
80107
  return ContainerOf(&ReqWrap<T>::req_, req);
46
}
47
48
template <typename T>
49
34
void ReqWrap<T>::Cancel() {
50

34
  if (req_.data == this)  // Only cancel if already dispatched.
51
1
    uv_cancel(reinterpret_cast<uv_req_t*>(&req_));
52
34
}
53
54
template <typename T>
55
12
AsyncWrap* ReqWrap<T>::GetAsyncWrap() {
56
12
  return this;
57
}
58
59
// Below is dark template magic designed to invoke libuv functions that
60
// initialize uv_req_t instances in a unified fashion, to allow easier
61
// tracking of active/inactive requests.
62
63
// Invoke a generic libuv function that initializes uv_req_t instances.
64
// This is, unfortunately, necessary since they come in three different
65
// variants that can not all be invoked in the same way:
66
// - int uv_foo(uv_loop_t* loop, uv_req_t* request, ...);
67
// - int uv_foo(uv_req_t* request, ...);
68
// - void uv_foo(uv_req_t* request, ...);
69
template <typename ReqT, typename T>
70
struct CallLibuvFunction;
71
72
// Detect `int uv_foo(uv_loop_t* loop, uv_req_t* request, ...);`.
73
template <typename ReqT, typename... Args>
74
struct CallLibuvFunction<ReqT, int(*)(uv_loop_t*, ReqT*, Args...)> {
75
  using T = int(*)(uv_loop_t*, ReqT*, Args...);
76
  template <typename... PassedArgs>
77
64312
  static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
78
64312
    return fn(loop, req, args...);
79
  }
80
};
81
82
// Detect `int uv_foo(uv_req_t* request, ...);`.
83
template <typename ReqT, typename... Args>
84
struct CallLibuvFunction<ReqT, int(*)(ReqT*, Args...)> {
85
  using T = int(*)(ReqT*, Args...);
86
  template <typename... PassedArgs>
87
33877
  static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
88
33877
    return fn(req, args...);
89
  }
90
};
91
92
// Detect `void uv_foo(uv_req_t* request, ...);`.
93
template <typename ReqT, typename... Args>
94
struct CallLibuvFunction<ReqT, void(*)(ReqT*, Args...)> {
95
  using T = void(*)(ReqT*, Args...);
96
  template <typename... PassedArgs>
97
54
  static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
98
54
    fn(req, args...);
99
54
    return 0;
100
  }
101
};
102
103
// This is slightly darker magic: This template is 'applied' to each parameter
104
// passed to the libuv function. If the parameter type (aka `T`) is a
105
// function type, it is assumed that this it is the request callback, and a
106
// wrapper that calls the original callback is created.
107
// If not, the parameter is passed through verbatim.
108
template <typename ReqT, typename T>
109
struct MakeLibuvRequestCallback {
110
246034
  static T For(ReqWrap<ReqT>* req_wrap, T v) {
111
    static_assert(!is_callable<T>::value,
112
                  "MakeLibuvRequestCallback missed a callback");
113
246034
    return v;
114
  }
115
};
116
117
// Match the `void callback(uv_req_t*, ...);` signature that all libuv
118
// callbacks use.
119
template <typename ReqT, typename... Args>
120
struct MakeLibuvRequestCallback<ReqT, void(*)(ReqT*, Args...)> {
121
  using F = void(*)(ReqT* req, Args... args);
122
123
98224
  static void Wrapper(ReqT* req, Args... args) {
124
98224
    ReqWrap<ReqT>* req_wrap = ContainerOf(&ReqWrap<ReqT>::req_, req);
125
98224
    req_wrap->env()->DecreaseWaitingRequestCounter();
126
98224
    F original_callback = reinterpret_cast<F>(req_wrap->original_callback_);
127
98224
    original_callback(req, args...);
128
98215
  }
129
130
98243
  static F For(ReqWrap<ReqT>* req_wrap, F v) {
131

98243
    CHECK_NULL(req_wrap->original_callback_);
132
98243
    req_wrap->original_callback_ =
133
        reinterpret_cast<typename ReqWrap<ReqT>::callback_t>(v);
134
98243
    return Wrapper;
135
  }
136
};
137
138
template <typename T>
139
template <typename LibuvFunction, typename... Args>
140
98243
int ReqWrap<T>::Dispatch(LibuvFunction fn, Args... args) {
141
98243
  Dispatched();
142
143
  // This expands as:
144
  //
145
  // int err = fn(env()->event_loop(), req(), arg1, arg2, Wrapper, arg3, ...)
146
  //              ^                                       ^        ^
147
  //              |                                       |        |
148
  //              \-- Omitted if `fn` has no              |        |
149
  //                  first `uv_loop_t*` argument         |        |
150
  //                                                      |        |
151
  //        A function callback whose first argument      |        |
152
  //        matches the libuv request type is replaced ---/        |
153
  //        by the `Wrapper` method defined above                  |
154
  //                                                               |
155
  //               Other (non-function) arguments are passed  -----/
156
  //               through verbatim
157
  int err = CallLibuvFunction<T, LibuvFunction>::Call(
158
      fn,
159
      env()->event_loop(),
160
      req(),
161
98243
      MakeLibuvRequestCallback<T, Args>::For(this, args)...);
162







98243
  if (err >= 0)
163
98242
    env()->IncreaseWaitingRequestCounter();
164
98243
  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_