Skip to content

Commit

Permalink
timers: add hasRef method to Timeout & Immediate
Browse files Browse the repository at this point in the history
Provide a way to check whether the current timer or immediate is refed.

PR-URL: #20898
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
  • Loading branch information
apapirovski committed Jun 1, 2018
1 parent de73272 commit 48a2568
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 3 deletions.
18 changes: 18 additions & 0 deletions doc/api/timers.md
Expand Up @@ -23,6 +23,15 @@ running as long as the immediate is active. The `Immediate` object returned by
[`setImmediate()`][] exports both `immediate.ref()` and `immediate.unref()`
functions that can be used to control this default behavior.

### immediate.hasRef()
<!-- YAML
added: REPLACEME
-->

* Returns: {boolean}

If true, the `Immediate` object will keep the Node.js event loop active.

### immediate.ref()
<!-- YAML
added: v9.7.0
Expand Down Expand Up @@ -61,6 +70,15 @@ timer is active. Each of the `Timeout` objects returned by these functions
export both `timeout.ref()` and `timeout.unref()` functions that can be used to
control this default behavior.

### timeout.hasRef()
<!-- YAML
added: REPLACEME
-->

* Returns: {boolean}

If true, the `Timeout` object will keep the Node.js event loop active.

### timeout.ref()
<!-- YAML
added: v0.9.1
Expand Down
12 changes: 10 additions & 2 deletions lib/timers.js
Expand Up @@ -547,6 +547,10 @@ Timeout.prototype.ref = function() {
return this;
};

Timeout.prototype.hasRef = function() {
return !!this[kRefed];
};

Timeout.prototype.close = function() {
clearTimeout(this);
return this;
Expand Down Expand Up @@ -622,7 +626,7 @@ function processImmediate() {
count++;
if (immediate[kRefed])
refCount++;
immediate[kRefed] = undefined;
immediate[kRefed] = null;

tryOnImmediate(immediate, tail, count, refCount);

Expand Down Expand Up @@ -713,6 +717,10 @@ const Immediate = class Immediate {
}
return this;
}

hasRef() {
return !!this[kRefed];
}
};

function setImmediate(callback, arg1, arg2, arg3) {
Expand Down Expand Up @@ -761,7 +769,7 @@ exports.clearImmediate = function clearImmediate(immediate) {

if (immediate[kRefed] && --immediateInfo[kRefCount] === 0)
toggleImmediateRef(false);
immediate[kRefed] = undefined;
immediate[kRefed] = null;

if (destroyHooksExist()) {
emitDestroy(immediate[async_id_symbol]);
Expand Down
8 changes: 8 additions & 0 deletions test/parallel/test-timers-immediate-unref.js
Expand Up @@ -3,6 +3,14 @@
const common = require('../common');
const Countdown = require('../common/countdown');

const assert = require('assert');

const immediate = setImmediate(() => {});
assert.strictEqual(immediate.hasRef(), true);
immediate.unref();
assert.strictEqual(immediate.hasRef(), false);
clearImmediate(immediate);

// This immediate should execute as it was unrefed and refed again.
// It also confirms that unref/ref are chainable.
setImmediate(common.mustCall(firstStep)).ref().unref().unref().ref();
Expand Down
8 changes: 7 additions & 1 deletion test/parallel/test-timers-unref.js
Expand Up @@ -23,15 +23,21 @@

const common = require('../common');

const assert = require('assert');

let unref_interval = false;
let unref_timer = false;
let checks = 0;

const LONG_TIME = 10 * 1000;
const SHORT_TIME = 100;

const timer = setTimeout(() => {}, 10);
assert.strictEqual(timer.hasRef(), true);
// Should not throw.
setTimeout(() => {}, 10).unref().ref().unref();
timer.unref().ref().unref();
assert.strictEqual(timer.hasRef(), false);

setInterval(() => {}, 10).unref().ref().unref();

setInterval(common.mustNotCall('Interval should not fire'), LONG_TIME).unref();
Expand Down

0 comments on commit 48a2568

Please sign in to comment.