Speed up dgram.Socket#send()-heavy code a little by omitting the call
into JS land when the user doesn't pass us a completion callback.
var errnoException = util._errnoException;
var errnoException = util._errnoException;
-// no-op callback
-function noop() {
-}
-
-
function isIP(address) {
if (!net)
net = require('net');
function isIP(address) {
if (!net)
net = require('net');
if (port <= 0 || port > 65535)
throw new RangeError('Port should be > 0 and < 65536');
if (port <= 0 || port > 65535)
throw new RangeError('Port should be > 0 and < 65536');
- callback = callback || noop;
+ // Normalize callback so it's either a function or undefined but not anything
+ // else.
+ if (!util.isFunction(callback))
+ callback = undefined;
self.emit('error', ex);
}
else if (self._handle) {
self.emit('error', ex);
}
else if (self._handle) {
- var req = { cb: callback, oncomplete: afterSend };
- var err = self._handle.send(req, buffer, offset, length, port, ip);
- if (err) {
+ var req = {};
+ if (callback) {
+ req.callback = callback;
+ req.oncomplete = afterSend;
+ }
+ var err = self._handle.send(req,
+ buffer,
+ offset,
+ length,
+ port,
+ ip,
+ !!callback);
+ if (err && callback) {
// don't emit as error, dgram_legacy.js compatibility
process.nextTick(function() {
callback(errnoException(err, 'send'));
// don't emit as error, dgram_legacy.js compatibility
process.nextTick(function() {
callback(errnoException(err, 'send'));
function afterSend(err) {
function afterSend(err) {
- if (this.cb)
- this.cb(err ? errnoException(err, 'send') : null);
+ this.callback(err ? errnoException(err, 'send') : null);
using v8::Undefined;
using v8::Value;
using v8::Undefined;
using v8::Value;
-typedef ReqWrap<uv_udp_send_t> SendWrap;
+
+class SendWrap : public ReqWrap<uv_udp_send_t> {
+ public:
+ SendWrap(Local<Object> req_wrap_obj, bool have_callback);
+ inline bool have_callback() const;
+ private:
+ const bool have_callback_;
+};
+
static Persistent<Function> constructor;
static Cached<String> buffer_sym;
static Persistent<Function> constructor;
static Cached<String> buffer_sym;
static Cached<String> onmessage_sym;
static Cached<String> onmessage_sym;
+SendWrap::SendWrap(Local<Object> req_wrap_obj, bool have_callback)
+ : ReqWrap<uv_udp_send_t>(req_wrap_obj)
+ , have_callback_(have_callback) {
+}
+
+
+inline bool SendWrap::have_callback() const {
+ return have_callback_;
+}
+
+
UDPWrap::UDPWrap(Handle<Object> object)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_udp_init(uv_default_loop(), &handle_);
UDPWrap::UDPWrap(Handle<Object> object)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_udp_init(uv_default_loop(), &handle_);
assert(args[3]->IsUint32());
assert(args[4]->IsUint32());
assert(args[5]->IsString());
assert(args[3]->IsUint32());
assert(args[4]->IsUint32());
assert(args[5]->IsString());
+ assert(args[6]->IsBoolean());
Local<Object> req_wrap_obj = args[0].As<Object>();
Local<Object> buffer_obj = args[1].As<Object>();
Local<Object> req_wrap_obj = args[0].As<Object>();
Local<Object> buffer_obj = args[1].As<Object>();
size_t length = args[3]->Uint32Value();
const unsigned short port = args[4]->Uint32Value();
String::Utf8Value address(args[5]);
size_t length = args[3]->Uint32Value();
const unsigned short port = args[4]->Uint32Value();
String::Utf8Value address(args[5]);
+ const bool have_callback = args[6]->IsTrue();
assert(offset < Buffer::Length(buffer_obj));
assert(length <= Buffer::Length(buffer_obj) - offset);
assert(offset < Buffer::Length(buffer_obj));
assert(length <= Buffer::Length(buffer_obj) - offset);
- SendWrap* req_wrap = new SendWrap(req_wrap_obj);
+ SendWrap* req_wrap = new SendWrap(req_wrap_obj, have_callback);
req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj);
uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj);
uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
// TODO(bnoordhuis) share with StreamWrap::AfterWrite() in stream_wrap.cc
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
// TODO(bnoordhuis) share with StreamWrap::AfterWrite() in stream_wrap.cc
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
- HandleScope scope(node_isolate);
-
- assert(req != NULL);
-
SendWrap* req_wrap = static_cast<SendWrap*>(req->data);
SendWrap* req_wrap = static_cast<SendWrap*>(req->data);
- UDPWrap* wrap = static_cast<UDPWrap*>(req->handle->data);
-
- assert(req_wrap->persistent().IsEmpty() == false);
- assert(wrap->persistent().IsEmpty() == false);
-
- Local<Object> req_wrap_obj = req_wrap->object();
- Local<Value> arg = Integer::New(status, node_isolate);
- MakeCallback(req_wrap_obj, oncomplete_sym, 1, &arg);
+ if (req_wrap->have_callback()) {
+ HandleScope scope(node_isolate);
+ Local<Object> req_wrap_obj = req_wrap->object();
+ Local<Value> arg = Integer::New(status, node_isolate);
+ MakeCallback(req_wrap_obj, oncomplete_sym, 1, &arg);
+ }