Browse Source

async_hooks: reduce duplication with factory

PR-URL: https://github.com/nodejs/node/pull/13755
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
v6
Ruben Bridgewater 8 years ago
committed by Andreas Madsen
parent
commit
5c6c02996b
No known key found for this signature in database GPG Key ID: 2FEE61B3C9E40F20
  1. 100
      lib/async_hooks.js

100
lib/async_hooks.js

@ -49,15 +49,18 @@ const init_symbol = Symbol('init');
const before_symbol = Symbol('before'); const before_symbol = Symbol('before');
const after_symbol = Symbol('after'); const after_symbol = Symbol('after');
const destroy_symbol = Symbol('destroy'); const destroy_symbol = Symbol('destroy');
const emitBeforeNative = emitHookFactory(before_symbol, 'emitBeforeNative');
const emitAfterNative = emitHookFactory(after_symbol, 'emitAfterNative');
const emitDestroyNative = emitHookFactory(destroy_symbol, 'emitDestroyNative');
// Setup the callbacks that node::AsyncWrap will call when there are hooks to // Setup the callbacks that node::AsyncWrap will call when there are hooks to
// process. They use the same functions as the JS embedder API. These callbacks // process. They use the same functions as the JS embedder API. These callbacks
// are setup immediately to prevent async_wrap.setupHooks() from being hijacked // are setup immediately to prevent async_wrap.setupHooks() from being hijacked
// and the cost of doing so is negligible. // and the cost of doing so is negligible.
async_wrap.setupHooks({ init, async_wrap.setupHooks({ init,
before: emitBeforeN, before: emitBeforeNative,
after: emitAfterN, after: emitAfterNative,
destroy: emitDestroyN }); destroy: emitDestroyNative });
// Used to fatally abort the process if a callback throws. // Used to fatally abort the process if a callback throws.
function fatalError(e) { function fatalError(e) {
@ -325,8 +328,8 @@ function emitInitS(asyncId, type, triggerAsyncId, resource) {
triggerAsyncId = initTriggerId(); triggerAsyncId = initTriggerId();
} }
// I'd prefer allowing these checks to not exist, or only throw in a debug // TODO(trevnorris): I'd prefer allowing these checks to not exist, or only
// build, in order to improve performance. // throw in a debug build, in order to improve performance.
if (!Number.isSafeInteger(asyncId) || asyncId < 0) if (!Number.isSafeInteger(asyncId) || asyncId < 0)
throw new RangeError('asyncId must be an unsigned integer'); throw new RangeError('asyncId must be an unsigned integer');
if (typeof type !== 'string' || type.length <= 0) if (typeof type !== 'string' || type.length <= 0)
@ -342,24 +345,35 @@ function emitInitS(asyncId, type, triggerAsyncId, resource) {
} }
} }
function emitHookFactory(symbol, name) {
function emitBeforeN(asyncId) { // Called from native. The asyncId stack handling is taken care of there
processing_hook = true; // before this is called.
// Use a single try/catch for all hook to avoid setting up one per iteration. // eslint-disable-next-line func-style
try { const fn = function(asyncId) {
for (var i = 0; i < active_hooks_array.length; i++) { processing_hook = true;
if (typeof active_hooks_array[i][before_symbol] === 'function') { // Use a single try/catch for all hook to avoid setting up one per
active_hooks_array[i][before_symbol](asyncId); // iteration.
try {
for (var i = 0; i < active_hooks_array.length; i++) {
if (typeof active_hooks_array[i][symbol] === 'function') {
active_hooks_array[i][symbol](asyncId);
}
} }
} catch (e) {
fatalError(e);
} }
} catch (e) { processing_hook = false;
fatalError(e);
}
processing_hook = false;
if (tmp_active_hooks_array !== null) { if (tmp_active_hooks_array !== null) {
restoreTmpHooks(); restoreTmpHooks();
} }
};
// Set the name property of the anonymous function as it looks good in the
// stack trace.
Object.defineProperty(fn, 'name', {
value: name
});
return fn;
} }
@ -379,29 +393,7 @@ function emitBeforeS(asyncId, triggerAsyncId = asyncId) {
if (async_hook_fields[kBefore] === 0) if (async_hook_fields[kBefore] === 0)
return; return;
emitBeforeN(asyncId); emitBeforeNative(asyncId);
}
// Called from native. The asyncId stack handling is taken care of there before
// this is called.
function emitAfterN(asyncId) {
processing_hook = true;
// Use a single try/catch for all hook to avoid setting up one per iteration.
try {
for (var i = 0; i < active_hooks_array.length; i++) {
if (typeof active_hooks_array[i][after_symbol] === 'function') {
active_hooks_array[i][after_symbol](asyncId);
}
}
} catch (e) {
fatalError(e);
}
processing_hook = false;
if (tmp_active_hooks_array !== null) {
restoreTmpHooks();
}
} }
@ -410,7 +402,7 @@ function emitAfterN(asyncId) {
// after callbacks. // after callbacks.
function emitAfterS(asyncId) { function emitAfterS(asyncId) {
if (async_hook_fields[kAfter] > 0) if (async_hook_fields[kAfter] > 0)
emitAfterN(asyncId); emitAfterNative(asyncId);
popAsyncIds(asyncId); popAsyncIds(asyncId);
} }
@ -425,26 +417,6 @@ function emitDestroyS(asyncId) {
} }
function emitDestroyN(asyncId) {
processing_hook = true;
// Use a single try/catch for all hook to avoid setting up one per iteration.
try {
for (var i = 0; i < active_hooks_array.length; i++) {
if (typeof active_hooks_array[i][destroy_symbol] === 'function') {
active_hooks_array[i][destroy_symbol](asyncId);
}
}
} catch (e) {
fatalError(e);
}
processing_hook = false;
if (tmp_active_hooks_array !== null) {
restoreTmpHooks();
}
}
// Emit callbacks for native calls. Since some state can be setup directly from // Emit callbacks for native calls. Since some state can be setup directly from
// C++ there's no need to perform all the work here. // C++ there's no need to perform all the work here.

Loading…
Cancel
Save