From 8cca30f31b2b71812e340692f2892fd5bf9df5db Mon Sep 17 00:00:00 2001 From: isaacs Date: Tue, 10 Jan 2012 12:07:30 -0800 Subject: [PATCH] zlib binding cleanup * Add assert to prevent parallel writes * Embed request object instead of using new/delete * Remove unnecessary WorkReqWrap in favor of uv_work_t * Use container_of instead of req->data Along with 2d8af39accc6e1a863aa60ed80289508f3df50e8 and 0ad2717fd88e5ddd28a1c245c78b37bfe9aa4197, this should Fix #2504. --- src/node_zlib.cc | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/node_zlib.cc b/src/node_zlib.cc index b3b430f..19120af 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -29,15 +29,11 @@ #include #include -#include - namespace node { using namespace v8; -// write() returns one of these, and then calls the cb() when it's done. -typedef ReqWrap WorkReqWrap; static Persistent callback_sym; @@ -83,6 +79,9 @@ template class ZCtx : public ObjectWrap { ZCtx *ctx = ObjectWrap::Unwrap< ZCtx >(args.This()); assert(ctx->init_done_ && "write before init"); + assert(!ctx->write_in_progress_ && "write already in progress"); + ctx->write_in_progress_ = true; + unsigned int flush = args[0]->Uint32Value(); Bytef *in; Bytef *out; @@ -112,9 +111,9 @@ template class ZCtx : public ObjectWrap { assert(out_off + out_len <= Buffer::Length(out_buf)); out = reinterpret_cast(Buffer::Data(out_buf) + out_off); - WorkReqWrap *req_wrap = new WorkReqWrap(); + // build up the work request + uv_work_t* work_req = &(ctx->work_req_); - req_wrap->data_ = ctx; ctx->strm_.avail_in = in_len; ctx->strm_.next_in = &(*in); ctx->strm_.avail_out = out_len; @@ -124,19 +123,14 @@ template class ZCtx : public ObjectWrap { // set this so that later on, I can easily tell how much was written. ctx->chunk_size_ = out_len; - // build up the work request - uv_work_t* work_req = &req_wrap->req_; - work_req->data = req_wrap; - uv_queue_work(uv_default_loop(), work_req, ZCtx::Process, ZCtx::After); - req_wrap->Dispatched(); ctx->Ref(); - return req_wrap->object_; + return ctx->handle_; } @@ -146,8 +140,7 @@ template class ZCtx : public ObjectWrap { // been consumed. static void Process(uv_work_t* work_req) { - WorkReqWrap *req_wrap = reinterpret_cast(work_req->data); - ZCtx *ctx = (ZCtx *)req_wrap->data_; + ZCtx *ctx = container_of(work_req, ZCtx, 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 @@ -179,19 +172,18 @@ template class ZCtx : public ObjectWrap { static void After(uv_work_t* work_req) { HandleScope scope; - WorkReqWrap *req_wrap = reinterpret_cast(work_req->data); - ZCtx *ctx = (ZCtx *)req_wrap->data_; + ZCtx *ctx = container_of(work_req, ZCtx, work_req_); Local avail_out = Integer::New(ctx->strm_.avail_out); Local avail_in = Integer::New(ctx->strm_.avail_in); + ctx->write_in_progress_ = false; + // call the write() cb - assert(req_wrap->object_->Get(callback_sym)->IsFunction() && + assert(ctx->handle_->Get(callback_sym)->IsFunction() && "Invalid callback"); Local args[2] = { avail_in, avail_out }; - MakeCallback(req_wrap->object_, "callback", 2, args); + MakeCallback(ctx->handle_, "callback", 2, args); - // delete the ReqWrap - delete req_wrap; ctx->Unref(); } @@ -284,6 +276,7 @@ template class ZCtx : public ObjectWrap { assert(0 && "wtf?"); } + ctx->write_in_progress_ = false; ctx->init_done_ = true; assert(err == Z_OK); } @@ -301,6 +294,10 @@ template class ZCtx : public ObjectWrap { int flush_; int chunk_size_; + + bool write_in_progress_; + + uv_work_t work_req_; }; -- 2.7.4