summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cares_wrap.cc5
-rw-r--r--src/env-inl.h8
-rw-r--r--src/node.cc4
-rw-r--r--src/node_crypto.cc16
-rw-r--r--src/node_http_parser.cc4
-rw-r--r--src/node_v8.cc2
-rw-r--r--src/node_zlib.cc4
-rw-r--r--src/signal_wrap.cc2
-rw-r--r--src/stream_wrap.cc2
-rw-r--r--src/tls_wrap.cc4
-rw-r--r--src/util-inl.h20
-rw-r--r--src/util.h24
12 files changed, 61 insertions, 34 deletions
diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc
index 0f5987b01a..f762f2a403 100644
--- a/src/cares_wrap.cc
+++ b/src/cares_wrap.cc
@@ -88,7 +88,7 @@ static void ares_timeout(uv_timer_t* handle) {
static void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
- ares_task_t* task = CONTAINER_OF(watcher, ares_task_t, poll_watcher);
+ ares_task_t* task = ContainerOf(&ares_task_t::poll_watcher, watcher);
Environment* env = task->env;
/* Reset the idle timer */
@@ -109,7 +109,8 @@ static void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
static void ares_poll_close_cb(uv_handle_t* watcher) {
- ares_task_t* task = CONTAINER_OF(watcher, ares_task_t, poll_watcher);
+ ares_task_t* task = ContainerOf(&ares_task_t::poll_watcher,
+ reinterpret_cast<uv_poll_t*>(watcher));
free(task);
}
diff --git a/src/env-inl.h b/src/env-inl.h
index 890ddd2305..90fc77c624 100644
--- a/src/env-inl.h
+++ b/src/env-inl.h
@@ -276,7 +276,7 @@ inline bool Environment::in_domain() const {
inline Environment* Environment::from_immediate_check_handle(
uv_check_t* handle) {
- return CONTAINER_OF(handle, Environment, immediate_check_handle_);
+ return ContainerOf(&Environment::immediate_check_handle_, handle);
}
inline uv_check_t* Environment::immediate_check_handle() {
@@ -289,7 +289,7 @@ inline uv_idle_t* Environment::immediate_idle_handle() {
inline Environment* Environment::from_idle_prepare_handle(
uv_prepare_t* handle) {
- return CONTAINER_OF(handle, Environment, idle_prepare_handle_);
+ return ContainerOf(&Environment::idle_prepare_handle_, handle);
}
inline uv_prepare_t* Environment::idle_prepare_handle() {
@@ -297,7 +297,7 @@ inline uv_prepare_t* Environment::idle_prepare_handle() {
}
inline Environment* Environment::from_idle_check_handle(uv_check_t* handle) {
- return CONTAINER_OF(handle, Environment, idle_check_handle_);
+ return ContainerOf(&Environment::idle_check_handle_, handle);
}
inline uv_check_t* Environment::idle_check_handle() {
@@ -345,7 +345,7 @@ inline void Environment::set_printed_error(bool value) {
}
inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) {
- return CONTAINER_OF(handle, Environment, cares_timer_handle_);
+ return ContainerOf(&Environment::cares_timer_handle_, handle);
}
inline uv_timer_t* Environment::cares_timer_handle() {
diff --git a/src/node.cc b/src/node.cc
index 7a4a090724..5d13e8bd58 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1523,7 +1523,7 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
int i = 0;
QUEUE_FOREACH(q, &req_wrap_queue) {
- ReqWrap<uv_req_t>* w = CONTAINER_OF(q, ReqWrap<uv_req_t>, req_wrap_queue_);
+ ReqWrap<uv_req_t>* w = ContainerOf(&ReqWrap<uv_req_t>::req_wrap_queue_, q);
if (w->persistent().IsEmpty())
continue;
ary->Set(i++, w->object());
@@ -1546,7 +1546,7 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
Local<String> owner_sym = env->owner_string();
QUEUE_FOREACH(q, &handle_wrap_queue) {
- HandleWrap* w = CONTAINER_OF(q, HandleWrap, handle_wrap_queue_);
+ HandleWrap* w = ContainerOf(&HandleWrap::handle_wrap_queue_, q);
if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
continue;
Local<Object> object = w->object();
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index af928708b8..4201040491 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -4027,7 +4027,6 @@ class PBKDF2Request : public AsyncWrap {
error_ = err;
}
- // TODO(trevnorris): Make private and make work with CONTAINER_OF macro.
uv_work_t work_req_;
private:
@@ -4059,7 +4058,7 @@ void EIO_PBKDF2(PBKDF2Request* req) {
void EIO_PBKDF2(uv_work_t* work_req) {
- PBKDF2Request* req = CONTAINER_OF(work_req, PBKDF2Request, work_req_);
+ PBKDF2Request* req = ContainerOf(&PBKDF2Request::work_req_, work_req);
EIO_PBKDF2(req);
}
@@ -4078,7 +4077,7 @@ void EIO_PBKDF2After(PBKDF2Request* req, Local<Value> argv[2]) {
void EIO_PBKDF2After(uv_work_t* work_req, int status) {
assert(status == 0);
- PBKDF2Request* req = CONTAINER_OF(work_req, PBKDF2Request, work_req_);
+ PBKDF2Request* req = ContainerOf(&PBKDF2Request::work_req_, work_req);
Environment* env = req->env();
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
@@ -4257,7 +4256,6 @@ class RandomBytesRequest : public AsyncWrap {
error_ = err;
}
- // TODO(trevnorris): Make private and make work with CONTAINER_OF macro.
uv_work_t work_req_;
private:
@@ -4269,9 +4267,8 @@ class RandomBytesRequest : public AsyncWrap {
template <bool pseudoRandom>
void RandomBytesWork(uv_work_t* work_req) {
- RandomBytesRequest* req = CONTAINER_OF(work_req,
- RandomBytesRequest,
- work_req_);
+ RandomBytesRequest* req =
+ ContainerOf(&RandomBytesRequest::work_req_, work_req);
int r;
// Ensure that OpenSSL's PRNG is properly seeded.
@@ -4317,9 +4314,8 @@ void RandomBytesCheck(RandomBytesRequest* req, Local<Value> argv[2]) {
void RandomBytesAfter(uv_work_t* work_req, int status) {
assert(status == 0);
- RandomBytesRequest* req = CONTAINER_OF(work_req,
- RandomBytesRequest,
- work_req_);
+ RandomBytesRequest* req =
+ ContainerOf(&RandomBytesRequest::work_req_, work_req);
Environment* env = req->env();
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc
index 3739437a0d..911fec398d 100644
--- a/src/node_http_parser.cc
+++ b/src/node_http_parser.cc
@@ -77,7 +77,7 @@ const uint32_t kOnMessageComplete = 3;
#define HTTP_CB(name) \
static int name(http_parser* p_) { \
- Parser* self = CONTAINER_OF(p_, Parser, parser_); \
+ Parser* self = ContainerOf(&Parser::parser_, p_); \
return self->name##_(); \
} \
int name##_()
@@ -85,7 +85,7 @@ const uint32_t kOnMessageComplete = 3;
#define HTTP_DATA_CB(name) \
static int name(http_parser* p_, const char* at, size_t length) { \
- Parser* self = CONTAINER_OF(p_, Parser, parser_); \
+ Parser* self = ContainerOf(&Parser::parser_, p_); \
return self->name##_(at, length); \
} \
int name##_(const char* at, size_t length)
diff --git a/src/node_v8.cc b/src/node_v8.cc
index 6652f6176a..b71b2a384d 100644
--- a/src/node_v8.cc
+++ b/src/node_v8.cc
@@ -83,7 +83,7 @@ void Environment::IsolateData::AfterGarbageCollection(GCType type,
q = QUEUE_HEAD(&queue);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&gc_tracker_queue_, q);
- Environment* env = CONTAINER_OF(q, Environment, gc_tracker_queue_);
+ Environment* env = ContainerOf(&Environment::gc_tracker_queue_, q);
env->AfterGarbageCollectionCallback(&gc_info_before_, &gc_info_after_);
}
}
diff --git a/src/node_zlib.cc b/src/node_zlib.cc
index 4453d82b44..4f0c938998 100644
--- a/src/node_zlib.cc
+++ b/src/node_zlib.cc
@@ -246,7 +246,7 @@ class ZCtx : public AsyncWrap {
// for a single write() call, until all of the input bytes have
// been consumed.
static void Process(uv_work_t* work_req) {
- ZCtx *ctx = CONTAINER_OF(work_req, ZCtx, work_req_);
+ ZCtx *ctx = ContainerOf(&ZCtx::work_req_, work_req);
// If the avail_out is left at 0, then it means that it ran out
// of room. If there was avail_out left over, then it means
@@ -320,7 +320,7 @@ class ZCtx : public AsyncWrap {
static void After(uv_work_t* work_req, int status) {
assert(status == 0);
- ZCtx* ctx = CONTAINER_OF(work_req, ZCtx, work_req_);
+ ZCtx* ctx = ContainerOf(&ZCtx::work_req_, work_req);
Environment* env = ctx->env();
HandleScope handle_scope(env->isolate());
diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc
index e1ec2fd21a..a50340d511 100644
--- a/src/signal_wrap.cc
+++ b/src/signal_wrap.cc
@@ -105,7 +105,7 @@ class SignalWrap : public HandleWrap {
}
static void OnSignal(uv_signal_t* handle, int signum) {
- SignalWrap* wrap = CONTAINER_OF(handle, SignalWrap, handle_);
+ SignalWrap* wrap = ContainerOf(&SignalWrap::handle_, handle);
Environment* env = wrap->env();
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc
index 069d17bcc5..026e204929 100644
--- a/src/stream_wrap.cc
+++ b/src/stream_wrap.cc
@@ -510,7 +510,7 @@ void StreamWrap::SetBlocking(const FunctionCallbackInfo<Value>& args) {
}
void StreamWrap::AfterWrite(uv_write_t* req, int status) {
- WriteWrap* req_wrap = CONTAINER_OF(req, WriteWrap, req_);
+ WriteWrap* req_wrap = ContainerOf(&WriteWrap::req_, req);
StreamWrap* wrap = req_wrap->wrap();
Environment* env = wrap->env();
diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc
index 2f63dfc9c4..b0200a8956 100644
--- a/src/tls_wrap.cc
+++ b/src/tls_wrap.cc
@@ -114,7 +114,7 @@ TLSCallbacks::~TLSCallbacks() {
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
QUEUE_REMOVE(q);
- WriteItem* wi = QUEUE_DATA(q, WriteItem, member_);
+ WriteItem* wi = ContainerOf(&WriteItem::member_, q);
delete wi;
}
}
@@ -145,7 +145,7 @@ bool TLSCallbacks::InvokeQueued(int status) {
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
QUEUE_REMOVE(q);
- WriteItem* wi = QUEUE_DATA(q, WriteItem, member_);
+ WriteItem* wi = ContainerOf(&WriteItem::member_, q);
wi->cb_(&wi->w_->req_, status);
delete wi;
}
diff --git a/src/util-inl.h b/src/util-inl.h
index 76015ccb3b..3709208f16 100644
--- a/src/util-inl.h
+++ b/src/util-inl.h
@@ -28,6 +28,26 @@
namespace node {
+template <typename Inner, typename Outer>
+ContainerOfHelper<Inner, Outer>::ContainerOfHelper(Inner Outer::*field,
+ Inner* pointer)
+ : pointer_(reinterpret_cast<Outer*>(
+ reinterpret_cast<uintptr_t>(pointer) -
+ reinterpret_cast<uintptr_t>(&(static_cast<Outer*>(0)->*field)))) {
+}
+
+template <typename Inner, typename Outer>
+template <typename TypeName>
+ContainerOfHelper<Inner, Outer>::operator TypeName*() const {
+ return static_cast<TypeName*>(pointer_);
+}
+
+template <typename Inner, typename Outer>
+inline ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
+ Inner* pointer) {
+ return ContainerOfHelper<Inner, Outer>(field, pointer);
+}
+
template <class TypeName>
inline v8::Local<TypeName> PersistentToLocal(
v8::Isolate* isolate,
diff --git a/src/util.h b/src/util.h
index 05a7dae25c..3dcfa5560f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -29,13 +29,6 @@
namespace node {
-#define OFFSET_OF(TypeName, Field) \
- (reinterpret_cast<uintptr_t>(&(reinterpret_cast<TypeName*>(8)->Field)) - 8)
-
-#define CONTAINER_OF(Pointer, TypeName, Field) \
- reinterpret_cast<TypeName*>( \
- reinterpret_cast<uintptr_t>(Pointer) - OFFSET_OF(TypeName, Field))
-
#define FIXED_ONE_BYTE_STRING(isolate, string) \
(node::OneByteString((isolate), (string), sizeof(string) - 1))
@@ -63,6 +56,23 @@ namespace node {
#define UNREACHABLE() abort()
+// The helper is for doing safe downcasts from base types to derived types.
+template <typename Inner, typename Outer>
+class ContainerOfHelper {
+ public:
+ inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
+ template <typename TypeName>
+ inline operator TypeName*() const;
+ private:
+ Outer* const pointer_;
+};
+
+// Calculate the address of the outer (i.e. embedding) struct from
+// the interior pointer to a data member.
+template <typename Inner, typename Outer>
+inline ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
+ Inner* pointer);
+
// If persistent.IsWeak() == false, then do not call persistent.Reset()
// while the returned Local<T> is still in scope, it will destroy the
// reference to the object.