UNPKG

3.15 kBPlain TextView Raw
1import Fiber = require('../fibers');
2import RunContext = require('./runContext');
3export = FiberManager;
4
5
6/** Helpers for Fiber management. */
7module FiberManager {
8
9 /** Returns true if the current execution context is within a fiber. */
10 export function isExecutingInFiber() {
11 return !!Fiber.current;
12 }
13
14 /** Creates and returns a new fiber in which an arbitrary function may be executed. */
15 export function create(): FiberEx {
16 return Fiber(runInFiber);
17 }
18
19 export interface FiberEx extends Fiber {
20
21 /**
22 * Executes the wrapped function specified in the RunContext instance. The final
23 * return/throw value of the wrapped function is used to notify the promise resolver
24 * and/or callback specified in the RunContext.
25 */
26 run(runCtx: RunContext): void;
27 }
28}
29
30
31/**
32 * The runInFiber() function provides the prolog/epilog wrapper code for running a function inside
33 * a fiber. The runInFiber() function accepts a RunContext instance, and calls the wrapped function
34 * specified there. The final return/throw value of the wrapped function is used to notify the
35 * promise resolver and/or callback specified in the RunContext. This function must take all its
36 * information in a single argument because it is called via Fiber#run(), which accepts one argument.
37 * NB: Since try/catch/finally prevents V8 optimisations, the function is split into several parts.
38 */
39function runInFiber(runCtx: RunContext) {
40 try { tryBlock(runCtx); }
41 catch (err) { catchBlock(runCtx, err); }
42 finally { finallyBlock(runCtx); }
43}
44function tryBlock(runCtx: RunContext) {
45
46 // Maintain an accurate count of currently active fibers, for pool management.
47 adjustFiberCount(+1);
48
49 // Call the wrapped function. It may be suspended several times (at await and/or yield calls).
50 var result = runCtx.wrapped.apply(runCtx.thisArg, runCtx.argsAsArray);
51
52 // The wrapped function returned normally. Notify any waiters.
53 if (runCtx.callback) runCtx.callback(null, result);
54 if (runCtx.resolver) runCtx.resolver.resolve(result);
55}
56function catchBlock(runCtx: RunContext, err) {
57
58 // The wrapped function threw an exception. Notify any waiters.
59 if (runCtx.callback) runCtx.callback(err);
60 if (runCtx.resolver) runCtx.resolver.reject(err);
61}
62function finallyBlock(runCtx: RunContext) {
63
64 // Maintain an accurate count of currently active fibers, for pool management.
65 adjustFiberCount(-1);
66
67 // Execute the done() callback, if provided.
68 if (runCtx.done) runCtx.done();
69}
70
71
72
73
74/**
75 * The following functionality prevents memory leaks in node-fibers by actively managing Fiber.poolSize.
76 * For more information, see https://github.com/laverdet/node-fibers/issues/169.
77 */
78function adjustFiberCount(delta: number) {
79 activeFiberCount += delta;
80 if (activeFiberCount >= fiberPoolSize) {
81 fiberPoolSize += 100;
82 Fiber.poolSize = fiberPoolSize;
83 }
84}
85var fiberPoolSize = Fiber.poolSize;
86var activeFiberCount = 0;