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: 52 52 100.0 %
Date: 2020-08-07 22:13:19 Branches: 21 42 50.0 %

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
69094
ReqWrapBase::ReqWrapBase(Environment* env) {
13
69094
  CHECK(env->has_run_bootstrapping_code());
14
69094
  env->req_wrap_queue()->PushBack(this);
15
69094
}
16
17
template <typename T>
18
69094
ReqWrap<T>::ReqWrap(Environment* env,
19
                    v8::Local<v8::Object> object,
20
                    AsyncWrap::ProviderType provider)
21
    : AsyncWrap(env, object, provider),
22
69094
      ReqWrapBase(env) {
23
69094
  Reset();
24
69094
}
25
26
template <typename T>
27
69070
ReqWrap<T>::~ReqWrap() {
28

138140
  CHECK_EQ(false, persistent().IsEmpty());
29
138140
}
30
31
template <typename T>
32
69263
void ReqWrap<T>::Dispatched() {
33
69263
  req_.data = this;
34
69263
}
35
36
template <typename T>
37
69301
void ReqWrap<T>::Reset() {
38
69301
  original_callback_ = nullptr;
39
69301
  req_.data = nullptr;
40
69301
}
41
42
template <typename T>
43
128923
ReqWrap<T>* ReqWrap<T>::from_req(T* req) {
44
128923
  return ContainerOf(&ReqWrap<T>::req_, req);
45
}
46
47
template <typename T>
48
39
void ReqWrap<T>::Cancel() {
49

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

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







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