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-09-15 22:29:17 Branches: 24 44 54.5 %

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

221882
  CHECK_EQ(false, persistent().IsEmpty());
28

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

35
  if (req_.data == this)  // Only cancel if already dispatched.
49
1
    uv_cancel(reinterpret_cast<uv_req_t*>(&req_));
50
35
}
51
52
template <typename T>
53
12
AsyncWrap* ReqWrap<T>::GetAsyncWrap() {
54
12
  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 <typename ReqT, typename T>
68
struct CallLibuvFunction;
69
70
// Detect `int uv_foo(uv_loop_t* loop, uv_req_t* request, ...);`.
71
template <typename ReqT, typename... Args>
72
struct CallLibuvFunction<ReqT, int(*)(uv_loop_t*, ReqT*, Args...)> {
73
  using T = int(*)(uv_loop_t*, ReqT*, Args...);
74
  template <typename... PassedArgs>
75
64495
  static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
76
64495
    return fn(loop, req, args...);
77
  }
78
};
79
80
// Detect `int uv_foo(uv_req_t* request, ...);`.
81
template <typename ReqT, typename... Args>
82
struct CallLibuvFunction<ReqT, int(*)(ReqT*, Args...)> {
83
  using T = int(*)(ReqT*, Args...);
84
  template <typename... PassedArgs>
85
46656
  static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
86
46656
    return fn(req, args...);
87
  }
88
};
89
90
// Detect `void uv_foo(uv_req_t* request, ...);`.
91
template <typename ReqT, typename... Args>
92
struct CallLibuvFunction<ReqT, void(*)(ReqT*, Args...)> {
93
  using T = void(*)(ReqT*, Args...);
94
  template <typename... PassedArgs>
95
54
  static int Call(T fn, uv_loop_t* loop, ReqT* req, PassedArgs... args) {
96
54
    fn(req, args...);
97
54
    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 <typename ReqT, typename T>
107
struct MakeLibuvRequestCallback {
108
265635
  static T For(ReqWrap<ReqT>* req_wrap, T v) {
109
    static_assert(!is_callable<T>::value,
110
                  "MakeLibuvRequestCallback missed a callback");
111
265635
    return v;
112
  }
113
};
114
115
// Match the `void callback(uv_req_t*, ...);` signature that all libuv
116
// callbacks use.
117
template <typename ReqT, typename... Args>
118
struct MakeLibuvRequestCallback<ReqT, void(*)(ReqT*, Args...)> {
119
  using F = void(*)(ReqT* req, Args... args);
120
121
111137
  static void Wrapper(ReqT* req, Args... args) {
122
111137
    ReqWrap<ReqT>* req_wrap = ContainerOf(&ReqWrap<ReqT>::req_, req);
123
111137
    req_wrap->env()->DecreaseWaitingRequestCounter();
124
111137
    F original_callback = reinterpret_cast<F>(req_wrap->original_callback_);
125
111137
    original_callback(req, args...);
126
111126
  }
127
128
111205
  static F For(ReqWrap<ReqT>* req_wrap, F v) {
129

111205
    CHECK_NULL(req_wrap->original_callback_);
130
111205
    req_wrap->original_callback_ =
131
        reinterpret_cast<typename ReqWrap<ReqT>::callback_t>(v);
132
111205
    return Wrapper;
133
  }
134
};
135
136
template <typename T>
137
template <typename LibuvFunction, typename... Args>
138
111205
int ReqWrap<T>::Dispatch(LibuvFunction fn, Args... args) {
139
111205
  Dispatched();
140
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<T, LibuvFunction>::Call(
156
      fn,
157
      env()->event_loop(),
158
      req(),
159
111205
      MakeLibuvRequestCallback<T, Args>::For(this, args)...);
160







111205
  if (err >= 0)
161
111203
    env()->IncreaseWaitingRequestCounter();
162
111205
  return err;
163
}
164
165
}  // namespace node
166
167
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
168
169
#endif  // SRC_REQ_WRAP_INL_H_