void EIO_AfterClose(uv_work_t* req) { Nan::HandleScope scope; VoidBaton* data = static_cast<VoidBaton*>(req->data); v8::Local<v8::Value> argv[1]; if (data->errorString[0]) { argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked()); } else { argv[0] = Nan::Null(); // We don't have an error, so clean up the write queue for that fd _WriteQueue *q = qForFD(data->fd); if (q) { q->lock(); QueuedWrite &write_queue = q->get(); while (!write_queue.empty()) { QueuedWrite *del_q = write_queue.next; del_q->baton->buffer.Reset(); del_q->remove(); } q->unlock(); deleteQForFD(data->fd); } } data->callback.Call(1, argv); delete data; delete req; }
void EIO_AfterClose(uv_work_t* req) { NanScope(); CloseBaton* data = static_cast<CloseBaton*>(req->data); v8::Handle<v8::Value> argv[1]; if(data->errorString[0]) { argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString)); } else { argv[0] = NanUndefined(); // We don't have an error, so clean up the write queue for that fd _WriteQueue *q = qForFD(data->fd); if (q) { q->lock(); QueuedWrite &write_queue = q->get(); while (!write_queue.empty()) { QueuedWrite *del_q = write_queue.next; NanDisposePersistent(del_q->baton->buffer); del_q->remove(); } q->unlock(); deleteQForFD(data->fd); } } data->callback->Call(1, argv); delete data->callback; delete data; delete req; }
void EIO_AfterWrite(uv_work_t* req) { NanScope(); QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data); WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton); v8::Handle<v8::Value> argv[2]; if(data->errorString[0]) { argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString)); argv[1] = NanUndefined(); } else { argv[0] = NanUndefined(); argv[1] = NanNew<v8::Int32>(data->result); } data->callback->Call(2, argv); if (data->offset < data->bufferLength && !data->errorString[0]) { // We're not done with this baton, so throw it right back onto the queue. // Don't re-push the write in the event loop if there was an error; because same error could occur again! // TODO: Add a uv_poll here for unix... //fprintf(stderr, "Write again...\n"); uv_queue_work(uv_default_loop(), req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); return; } int fd = data->fd; _WriteQueue *q = qForFD(fd); if(!q) { NanThrowTypeError("There's no write queue for that file descriptor (after write)!"); return; } q->lock(); QueuedWrite &write_queue = q->get(); // remove this one from the list queuedWrite->remove(); // If there are any left, start a new thread to write the next one. if (!write_queue.empty()) { // Always pull the next work item from the head of the queue QueuedWrite* nextQueuedWrite = write_queue.next; uv_queue_work(uv_default_loop(), &nextQueuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); } q->unlock(); NanDisposePersistent(data->buffer); delete data->callback; delete data; delete queuedWrite; }
void EIO_AfterWrite(uv_work_t* req) { Nan::HandleScope scope; QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data); WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton); v8::Local<v8::Value> argv[1]; if (data->errorString[0]) { argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked()); } else { argv[0] = Nan::Null(); } if (data->offset < data->bufferLength && !data->errorString[0]) { // We're not done with this baton, so throw it right back onto the queue. // Don't re-push the write in the event loop if there was an error; because same error could occur again! // TODO: Add a uv_poll here for unix... uv_queue_work(uv_default_loop(), req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); return; } // throwing errors instead of returning them at this point is rude int fd = data->fd; _WriteQueue *q = qForFD(fd); if (!q) { Nan::ThrowTypeError("There's no write queue for that file descriptor (after write)"); return; } q->lock(); QueuedWrite &write_queue = q->get(); // remove this one from the list queuedWrite->remove(); data->callback.Call(1, argv); // If there are any left, start a new thread to write the next one. if (!write_queue.empty()) { // Always pull the next work item from the head of the queue QueuedWrite* nextQueuedWrite = write_queue.next; uv_queue_work(uv_default_loop(), &nextQueuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); } q->unlock(); data->buffer.Reset(); delete data; delete queuedWrite; }
static _WriteQueue *newQForFD(const int fd) { _WriteQueue *q = qForFD(fd); if (q == NULL) { if (write_queues == NULL) { write_queues = new _WriteQueue(fd); return write_queues; } else { q = write_queues; while (q->_next != NULL) { q = q->_next; } q->_next = new _WriteQueue(fd); return q->_next; } } return q; }