src: replace CONTAINER_OF with type-safe function
Replace the CONTAINER_OF macro with a template function that is as type-safe as a reinterpret_cast<> of an arbitrary pointer can be made. Signed-off-by: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
parent
c7b02034ef
commit
820aaf5b3d
@ -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) {
|
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;
|
Environment* env = task->env;
|
||||||
|
|
||||||
/* Reset the idle timer */
|
/* 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) {
|
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);
|
free(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ inline bool Environment::in_domain() const {
|
|||||||
|
|
||||||
inline Environment* Environment::from_immediate_check_handle(
|
inline Environment* Environment::from_immediate_check_handle(
|
||||||
uv_check_t* 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() {
|
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(
|
inline Environment* Environment::from_idle_prepare_handle(
|
||||||
uv_prepare_t* 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() {
|
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) {
|
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() {
|
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) {
|
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() {
|
inline uv_timer_t* Environment::cares_timer_handle() {
|
||||||
|
@ -1523,7 +1523,7 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
QUEUE_FOREACH(q, &req_wrap_queue) {
|
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())
|
if (w->persistent().IsEmpty())
|
||||||
continue;
|
continue;
|
||||||
ary->Set(i++, w->object());
|
ary->Set(i++, w->object());
|
||||||
@ -1546,7 +1546,7 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
|
|||||||
Local<String> owner_sym = env->owner_string();
|
Local<String> owner_sym = env->owner_string();
|
||||||
|
|
||||||
QUEUE_FOREACH(q, &handle_wrap_queue) {
|
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))
|
if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
|
||||||
continue;
|
continue;
|
||||||
Local<Object> object = w->object();
|
Local<Object> object = w->object();
|
||||||
|
@ -4027,7 +4027,6 @@ class PBKDF2Request : public AsyncWrap {
|
|||||||
error_ = err;
|
error_ = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(trevnorris): Make private and make work with CONTAINER_OF macro.
|
|
||||||
uv_work_t work_req_;
|
uv_work_t work_req_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -4059,7 +4058,7 @@ void EIO_PBKDF2(PBKDF2Request* req) {
|
|||||||
|
|
||||||
|
|
||||||
void EIO_PBKDF2(uv_work_t* work_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);
|
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) {
|
void EIO_PBKDF2After(uv_work_t* work_req, int status) {
|
||||||
assert(status == 0);
|
assert(status == 0);
|
||||||
PBKDF2Request* req = CONTAINER_OF(work_req, PBKDF2Request, work_req_);
|
PBKDF2Request* req = ContainerOf(&PBKDF2Request::work_req_, work_req);
|
||||||
Environment* env = req->env();
|
Environment* env = req->env();
|
||||||
HandleScope handle_scope(env->isolate());
|
HandleScope handle_scope(env->isolate());
|
||||||
Context::Scope context_scope(env->context());
|
Context::Scope context_scope(env->context());
|
||||||
@ -4257,7 +4256,6 @@ class RandomBytesRequest : public AsyncWrap {
|
|||||||
error_ = err;
|
error_ = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(trevnorris): Make private and make work with CONTAINER_OF macro.
|
|
||||||
uv_work_t work_req_;
|
uv_work_t work_req_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -4269,9 +4267,8 @@ class RandomBytesRequest : public AsyncWrap {
|
|||||||
|
|
||||||
template <bool pseudoRandom>
|
template <bool pseudoRandom>
|
||||||
void RandomBytesWork(uv_work_t* work_req) {
|
void RandomBytesWork(uv_work_t* work_req) {
|
||||||
RandomBytesRequest* req = CONTAINER_OF(work_req,
|
RandomBytesRequest* req =
|
||||||
RandomBytesRequest,
|
ContainerOf(&RandomBytesRequest::work_req_, work_req);
|
||||||
work_req_);
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
// Ensure that OpenSSL's PRNG is properly seeded.
|
// 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) {
|
void RandomBytesAfter(uv_work_t* work_req, int status) {
|
||||||
assert(status == 0);
|
assert(status == 0);
|
||||||
RandomBytesRequest* req = CONTAINER_OF(work_req,
|
RandomBytesRequest* req =
|
||||||
RandomBytesRequest,
|
ContainerOf(&RandomBytesRequest::work_req_, work_req);
|
||||||
work_req_);
|
|
||||||
Environment* env = req->env();
|
Environment* env = req->env();
|
||||||
HandleScope handle_scope(env->isolate());
|
HandleScope handle_scope(env->isolate());
|
||||||
Context::Scope context_scope(env->context());
|
Context::Scope context_scope(env->context());
|
||||||
|
@ -77,7 +77,7 @@ const uint32_t kOnMessageComplete = 3;
|
|||||||
|
|
||||||
#define HTTP_CB(name) \
|
#define HTTP_CB(name) \
|
||||||
static int name(http_parser* p_) { \
|
static int name(http_parser* p_) { \
|
||||||
Parser* self = CONTAINER_OF(p_, Parser, parser_); \
|
Parser* self = ContainerOf(&Parser::parser_, p_); \
|
||||||
return self->name##_(); \
|
return self->name##_(); \
|
||||||
} \
|
} \
|
||||||
int name##_()
|
int name##_()
|
||||||
@ -85,7 +85,7 @@ const uint32_t kOnMessageComplete = 3;
|
|||||||
|
|
||||||
#define HTTP_DATA_CB(name) \
|
#define HTTP_DATA_CB(name) \
|
||||||
static int name(http_parser* p_, const char* at, size_t length) { \
|
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); \
|
return self->name##_(at, length); \
|
||||||
} \
|
} \
|
||||||
int name##_(const char* at, size_t length)
|
int name##_(const char* at, size_t length)
|
||||||
|
@ -83,7 +83,7 @@ void Environment::IsolateData::AfterGarbageCollection(GCType type,
|
|||||||
q = QUEUE_HEAD(&queue);
|
q = QUEUE_HEAD(&queue);
|
||||||
QUEUE_REMOVE(q);
|
QUEUE_REMOVE(q);
|
||||||
QUEUE_INSERT_TAIL(&gc_tracker_queue_, 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_);
|
env->AfterGarbageCollectionCallback(&gc_info_before_, &gc_info_after_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ class ZCtx : public AsyncWrap {
|
|||||||
// for a single write() call, until all of the input bytes have
|
// for a single write() call, until all of the input bytes have
|
||||||
// been consumed.
|
// been consumed.
|
||||||
static void Process(uv_work_t* work_req) {
|
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
|
// 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
|
// 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) {
|
static void After(uv_work_t* work_req, int status) {
|
||||||
assert(status == 0);
|
assert(status == 0);
|
||||||
|
|
||||||
ZCtx* ctx = CONTAINER_OF(work_req, ZCtx, work_req_);
|
ZCtx* ctx = ContainerOf(&ZCtx::work_req_, work_req);
|
||||||
Environment* env = ctx->env();
|
Environment* env = ctx->env();
|
||||||
|
|
||||||
HandleScope handle_scope(env->isolate());
|
HandleScope handle_scope(env->isolate());
|
||||||
|
@ -105,7 +105,7 @@ class SignalWrap : public HandleWrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void OnSignal(uv_signal_t* handle, int signum) {
|
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();
|
Environment* env = wrap->env();
|
||||||
HandleScope handle_scope(env->isolate());
|
HandleScope handle_scope(env->isolate());
|
||||||
Context::Scope context_scope(env->context());
|
Context::Scope context_scope(env->context());
|
||||||
|
@ -510,7 +510,7 @@ void StreamWrap::SetBlocking(const FunctionCallbackInfo<Value>& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void StreamWrap::AfterWrite(uv_write_t* req, int status) {
|
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();
|
StreamWrap* wrap = req_wrap->wrap();
|
||||||
Environment* env = wrap->env();
|
Environment* env = wrap->env();
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ TLSCallbacks::~TLSCallbacks() {
|
|||||||
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
|
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
|
||||||
QUEUE_REMOVE(q);
|
QUEUE_REMOVE(q);
|
||||||
|
|
||||||
WriteItem* wi = QUEUE_DATA(q, WriteItem, member_);
|
WriteItem* wi = ContainerOf(&WriteItem::member_, q);
|
||||||
delete wi;
|
delete wi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ bool TLSCallbacks::InvokeQueued(int status) {
|
|||||||
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
|
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
|
||||||
QUEUE_REMOVE(q);
|
QUEUE_REMOVE(q);
|
||||||
|
|
||||||
WriteItem* wi = QUEUE_DATA(q, WriteItem, member_);
|
WriteItem* wi = ContainerOf(&WriteItem::member_, q);
|
||||||
wi->cb_(&wi->w_->req_, status);
|
wi->cb_(&wi->w_->req_, status);
|
||||||
delete wi;
|
delete wi;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,26 @@
|
|||||||
|
|
||||||
namespace node {
|
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>
|
template <class TypeName>
|
||||||
inline v8::Local<TypeName> PersistentToLocal(
|
inline v8::Local<TypeName> PersistentToLocal(
|
||||||
v8::Isolate* isolate,
|
v8::Isolate* isolate,
|
||||||
|
24
src/util.h
24
src/util.h
@ -29,13 +29,6 @@
|
|||||||
|
|
||||||
namespace node {
|
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) \
|
#define FIXED_ONE_BYTE_STRING(isolate, string) \
|
||||||
(node::OneByteString((isolate), (string), sizeof(string) - 1))
|
(node::OneByteString((isolate), (string), sizeof(string) - 1))
|
||||||
|
|
||||||
@ -63,6 +56,23 @@ namespace node {
|
|||||||
|
|
||||||
#define UNREACHABLE() abort()
|
#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()
|
// If persistent.IsWeak() == false, then do not call persistent.Reset()
|
||||||
// while the returned Local<T> is still in scope, it will destroy the
|
// while the returned Local<T> is still in scope, it will destroy the
|
||||||
// reference to the object.
|
// reference to the object.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user