Skip to content

Commit

Permalink
Move setTimeout and friends into timers module
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Oct 26, 2010
1 parent 5cc29b8 commit 7994400
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 73 deletions.
122 changes: 81 additions & 41 deletions lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function debug () {
// IDLE TIMEOUTS
//
// Because often many sockets will have the same idle timeout we will not
// use one timeout watcher per socket. It is too much overhead. Instead
// use one timeout watcher per item. It is too much overhead. Instead
// we'll use a single watcher for all sockets with the same timeout value
// and a linked list. This technique is described in the libev manual:
// http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts
Expand All @@ -24,43 +24,43 @@ function debug () {
// value = list
var lists = {};

// show the most idle socket
// show the most idle item
function peek (list) {
if (list._idlePrev == list) return null;
return list._idlePrev;
}


// remove the most idle socket from the list
// remove the most idle item from the list
function shift (list) {
var first = list._idlePrev;
remove(first);
return first;
}


// remove a socket from its list
function remove (socket) {
socket._idleNext._idlePrev = socket._idlePrev;
socket._idlePrev._idleNext = socket._idleNext;
// remove a item from its list
function remove (item) {
item._idleNext._idlePrev = item._idlePrev;
item._idlePrev._idleNext = item._idleNext;
}


// remove a socket from its list and place at the end.
function append (list, socket) {
remove(socket);
socket._idleNext = list._idleNext;
socket._idleNext._idlePrev = socket;
socket._idlePrev = list;
list._idleNext = socket;
// remove a item from its list and place at the end.
function append (list, item) {
remove(item);
item._idleNext = list._idleNext;
item._idleNext._idlePrev = item;
item._idlePrev = list;
list._idleNext = item;
}


// the main function - creates lists on demand and the watchers associated
// with them.
function insert (socket, msecs) {
socket._idleStart = new Date();
socket._idleTimeout = msecs;
function insert (item, msecs) {
item._idleStart = new Date();
item._idleTimeout = msecs;

if (!msecs) return;

Expand Down Expand Up @@ -105,17 +105,17 @@ function insert (socket, msecs) {
list.again(msecs);
}

append(list, socket);
append(list, item);
assert(list._idleNext != list); // list is not empty
}


var unenroll = exports.unenroll = function (socket) {
if (socket._idleNext) {
socket._idleNext._idlePrev = socket._idlePrev;
socket._idlePrev._idleNext = socket._idleNext;
var unenroll = exports.unenroll = function (item) {
if (item._idleNext) {
item._idleNext._idlePrev = item._idlePrev;
item._idlePrev._idleNext = item._idleNext;

var list = lists[socket._idleTimeout];
var list = lists[item._idleTimeout];
// if empty then stop the watcher
//debug('unenroll');
if (list && list._idlePrev == list) {
Expand All @@ -127,33 +127,73 @@ var unenroll = exports.unenroll = function (socket) {


// Does not start the time, just sets up the members needed.
exports.enroll = function (socket, msecs) {
// if this socket was already in a list somewhere
exports.enroll = function (item, msecs) {
// if this item was already in a list somewhere
// then we should unenroll it from that
if (socket._idleNext) unenroll(socket);
if (item._idleNext) unenroll(item);

socket._idleTimeout = msecs;
socket._idleNext = socket;
socket._idlePrev = socket;
item._idleTimeout = msecs;
item._idleNext = item;
item._idlePrev = item;
};

// call this whenever the socket is active (not idle)
// call this whenever the item is active (not idle)
// it will reset its timeout.
exports.active = function (socket) {
var msecs = socket._idleTimeout;
exports.active = function (item) {
var msecs = item._idleTimeout;
if (msecs) {
var list = lists[msecs];
if (socket._idleNext == socket) {
insert(socket, msecs);
if (item._idleNext == item) {
insert(item, msecs);
} else {
// inline append
socket._idleStart = new Date();
socket._idleNext._idlePrev = socket._idlePrev;
socket._idlePrev._idleNext = socket._idleNext;
socket._idleNext = list._idleNext;
socket._idleNext._idlePrev = socket;
socket._idlePrev = list;
list._idleNext = socket;
item._idleStart = new Date();
item._idleNext._idlePrev = item._idlePrev;
item._idlePrev._idleNext = item._idleNext;
item._idleNext = list._idleNext;
item._idleNext._idlePrev = item;
item._idlePrev = list;
list._idleNext = item;
}
}
};





// Timers
function addTimerListener (callback) {
var timer = this;
// Special case the no param case to avoid the extra object creation.
if (arguments.length > 2) {
var args = Array.prototype.slice.call(arguments, 2);
timer.callback = function () { callback.apply(timer, args); };
} else {
timer.callback = callback;
}
}


exports.setTimeout = function (callback, after) {
var timer = new Timer();
addTimerListener.apply(timer, arguments);
timer.start(after, 0);
return timer;
};

exports.setInterval = function (callback, repeat) {
var timer = new Timer();
addTimerListener.apply(timer, arguments);
timer.start(repeat, repeat ? repeat : 1);
return timer;
};

exports.clearTimeout = function (timer) {
if (timer instanceof Timer) {
timer.callback = null;
timer.stop();
}
};

exports.clearInterval = exports.clearTimeout;
45 changes: 13 additions & 32 deletions src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,45 +425,26 @@ var constants; // lazy loaded.
};
})();

// Timers
function addTimerListener (callback) {
var timer = this;
// Special case the no param case to avoid the extra object creation.
if (arguments.length > 2) {
var args = Array.prototype.slice.call(arguments, 2);
timer.callback = function () { callback.apply(timer, args); };
} else {
timer.callback = callback;
}
}

var Timer; // lazy load

global.setTimeout = function (callback, after) {
if (!Timer) Timer = process.binding("timer").Timer;
var timer = new Timer();
addTimerListener.apply(timer, arguments);
timer.start(after, 0);
return timer;
global.setTimeout = function () {
var t = module.requireNative('timers');
return t.setTimeout.apply(this, arguments);
};

global.setInterval = function (callback, repeat) {
if (!Timer) Timer = process.binding("timer").Timer;
var timer = new Timer();
addTimerListener.apply(timer, arguments);
timer.start(repeat, repeat ? repeat : 1);
return timer;
global.setInterval = function () {
var t = module.requireNative('timers');
return t.setInterval.apply(this, arguments);
};

global.clearTimeout = function (timer) {
if (!Timer) Timer = process.binding("timer").Timer;
if (timer instanceof Timer) {
timer.callback = null;
timer.stop();
}
global.clearTimeout = function () {
var t = module.requireNative('timers');
return t.clearTimeout.apply(this, arguments);
};

global.clearInterval = global.clearTimeout;
global.clearInterval = function () {
var t = module.requireNative('timers');
return t.clearInterval.apply(this, arguments);
};


var stdout;
Expand Down

0 comments on commit 7994400

Please sign in to comment.