effect
Version:
The missing standard library for TypeScript, for writing production-grade software.
126 lines (125 loc) • 4.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.make = exports.get = exports.TypeId = void 0;
var Context = _interopRequireWildcard(require("../Context.js"));
var Duration = _interopRequireWildcard(require("../Duration.js"));
var Effectable = _interopRequireWildcard(require("../Effectable.js"));
var _Function = require("../Function.js");
var Readable = _interopRequireWildcard(require("../Readable.js"));
var coreEffect = _interopRequireWildcard(require("./core-effect.js"));
var core = _interopRequireWildcard(require("./core.js"));
var circular = _interopRequireWildcard(require("./effect/circular.js"));
var fiberRuntime = _interopRequireWildcard(require("./fiberRuntime.js"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/** @internal */
const TypeId = exports.TypeId = /*#__PURE__*/Symbol.for("effect/RcRef");
const stateEmpty = {
_tag: "Empty"
};
const stateClosed = {
_tag: "Closed"
};
const variance = {
_A: _Function.identity,
_E: _Function.identity
};
class RcRefImpl extends Effectable.Class {
acquire;
context;
scope;
idleTimeToLive;
[TypeId] = variance;
[Readable.TypeId] = Readable.TypeId;
state = stateEmpty;
semaphore = /*#__PURE__*/circular.unsafeMakeSemaphore(1);
constructor(acquire, context, scope, idleTimeToLive) {
super();
this.acquire = acquire;
this.context = context;
this.scope = scope;
this.idleTimeToLive = idleTimeToLive;
this.get = get(this);
}
get;
commit() {
return this.get;
}
}
/** @internal */
const make = options => core.withFiberRuntime(fiber => {
const context = fiber.getFiberRef(core.currentContext);
const scope = Context.get(context, fiberRuntime.scopeTag);
const ref = new RcRefImpl(options.acquire, context, scope, options.idleTimeToLive ? Duration.decode(options.idleTimeToLive) : undefined);
return core.as(scope.addFinalizer(() => ref.semaphore.withPermits(1)(core.suspend(() => {
const close = ref.state._tag === "Acquired" ? core.scopeClose(ref.state.scope, core.exitVoid) : core.void;
ref.state = stateClosed;
return close;
}))), ref);
});
/** @internal */
exports.make = make;
const get = self_ => {
const self = self_;
return core.uninterruptibleMask(restore => core.suspend(() => {
switch (self.state._tag) {
case "Closed":
{
return core.interrupt;
}
case "Acquired":
{
self.state.refCount++;
return self.state.fiber ? core.as(core.interruptFiber(self.state.fiber), self.state) : core.succeed(self.state);
}
case "Empty":
{
return fiberRuntime.scopeMake().pipe(coreEffect.bindTo("scope"), coreEffect.bind("value", ({
scope
}) => restore(core.fiberRefLocally(self.acquire, core.currentContext, Context.add(self.context, fiberRuntime.scopeTag, scope)))), core.map(({
scope,
value
}) => {
const state = {
_tag: "Acquired",
value,
scope,
fiber: undefined,
refCount: 1
};
self.state = state;
return state;
}));
}
}
})).pipe(self.semaphore.withPermits(1), coreEffect.bindTo("state"), coreEffect.bind("scope", () => fiberRuntime.scopeTag), core.tap(({
scope,
state
}) => scope.addFinalizer(() => core.suspend(() => {
state.refCount--;
if (state.refCount > 0) {
return core.void;
}
if (self.idleTimeToLive === undefined) {
self.state = stateEmpty;
return core.scopeClose(state.scope, core.exitVoid);
}
return coreEffect.sleep(self.idleTimeToLive).pipe(core.interruptible, core.zipRight(core.suspend(() => {
if (self.state._tag === "Acquired" && self.state.refCount === 0) {
self.state = stateEmpty;
return core.scopeClose(state.scope, core.exitVoid);
}
return core.void;
})), fiberRuntime.ensuring(core.sync(() => {
state.fiber = undefined;
})), circular.forkIn(self.scope), core.tap(fiber => {
state.fiber = fiber;
}), self.semaphore.withPermits(1));
}))), core.map(({
state
}) => state.value));
};
exports.get = get;
//# sourceMappingURL=rcRef.js.map