rockbed 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -0
- package/dist/assert/index.d.ts +6 -0
- package/dist/assert/index.js +27 -0
- package/dist/assert/index.js.map +1 -0
- package/dist/async/index.d.ts +105 -0
- package/dist/async/index.js +380 -0
- package/dist/async/index.js.map +1 -0
- package/dist/dispose/index.d.ts +47 -0
- package/dist/dispose/index.js +166 -0
- package/dist/dispose/index.js.map +1 -0
- package/dist/dispose-base-CAeXDpjg.d.ts +6 -0
- package/dist/error/index.d.ts +46 -0
- package/dist/error/index.js +150 -0
- package/dist/error/index.js.map +1 -0
- package/dist/error-base-BWuBlS2k.d.ts +28 -0
- package/dist/event/index.d.ts +57 -0
- package/dist/event/index.js +167 -0
- package/dist/event/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +989 -0
- package/dist/index.js.map +1 -0
- package/dist/json/index.d.ts +4 -0
- package/dist/json/index.js +20 -0
- package/dist/json/index.js.map +1 -0
- package/dist/lock/index.d.ts +106 -0
- package/dist/lock/index.js +404 -0
- package/dist/lock/index.js.map +1 -0
- package/dist/response/index.d.ts +17 -0
- package/dist/response/index.js +19 -0
- package/dist/response/index.js.map +1 -0
- package/package.json +80 -0
- package/src/assert/assert.ts +24 -0
- package/src/assert/index.ts +2 -0
- package/src/async/barrier.ts +47 -0
- package/src/async/index.ts +8 -0
- package/src/async/promise.ts +316 -0
- package/src/async/wait.ts +7 -0
- package/src/dispose/disposable-store.ts +68 -0
- package/src/dispose/disposable-t.ts +85 -0
- package/src/dispose/disposable-utils.ts +13 -0
- package/src/dispose/dispose-base.ts +9 -0
- package/src/dispose/index.ts +8 -0
- package/src/dispose/logger.ts +41 -0
- package/src/error/error-base.ts +39 -0
- package/src/error/error-code.ts +48 -0
- package/src/error/error-const.ts +16 -0
- package/src/error/error-or.ts +2 -0
- package/src/error/error-t.ts +93 -0
- package/src/error/index.ts +5 -0
- package/src/event/emitter.ts +193 -0
- package/src/event/index.ts +10 -0
- package/src/index.ts +8 -0
- package/src/json/index.ts +1 -0
- package/src/json/json.ts +15 -0
- package/src/lock/README.md +11 -0
- package/src/lock/capability.ts +89 -0
- package/src/lock/index.ts +2 -0
- package/src/lock/semaphore.ts +21 -0
- package/src/lock/shared-mutex.ts +256 -0
- package/src/response/index.ts +1 -0
- package/src/response/response.ts +27 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/assert/assert.ts","../src/error/error-base.ts","../src/error/error-t.ts","../src/error/error-const.ts","../src/error/error-code.ts","../src/dispose/dispose-base.ts","../src/dispose/logger.ts","../src/dispose/disposable-store.ts","../src/dispose/disposable-t.ts","../src/dispose/disposable-utils.ts","../src/async/promise.ts","../src/async/wait.ts","../src/async/barrier.ts","../src/event/emitter.ts","../src/json/json.ts","../src/lock/capability.ts","../src/lock/semaphore.ts","../src/lock/shared-mutex.ts","../src/response/response.ts"],"sourcesContent":["function abort(reason: string): never {\n throw new Error(`lvAssert(${reason})`);\n}\n\nexport function lvAssert(expr: unknown, reason?: string): asserts expr {\n if (!expr) {\n abort(reason ?? '#expr is false');\n }\n}\n\nexport function lvAssertNotHere(reason?: string): never {\n abort(reason ?? 'unreachable code flow');\n}\n\nexport function lvAssertNever(member: never, message = 'Illegal value:'): never {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n abort(`${message}: ${member}`);\n}\n\nexport function lvAssertNotNil<T>(val: T, reason?: string): asserts val is NonNullable<T> {\n if (val === null || val === undefined) {\n abort(reason ?? '#val is nil');\n }\n}\n","//\n// lv项目中使用的错误类型\n//\n\nexport const ILvErrorRef = Symbol.for('rockbed.ILvErrorRef');\nexport type ILvErrorRef = ILvErrorOr<never>;\n\nexport const ILvRealErrorRef = Symbol.for('rockbed.ILvRealErrorRef');\nexport interface ILvRealErrorRef {\n readonly ok: false;\n readonly code: number;\n readonly msg: string;\n readonly cause?: ILvErrorRef | Error;\n readonly toString: () => string;\n readonly pair: () => [ILvRealErrorRef, null];\n readonly errorInfo?: unknown;\n}\n\n//\n// 没有错误时,可以直接使用 value 字段\n//\nexport const ILvValueRef = Symbol.for('rockbed.ILvValueRef');\nexport interface ILvValueRef<T> {\n readonly ok: true;\n readonly code: 0;\n readonly msg: '';\n readonly cause?: undefined;\n readonly value: T;\n readonly toString: () => string;\n readonly pair: () => [null, T];\n}\n\n//\n// lv项目中使用的携带值可能错误类型\n//\nexport const ILvErrorOr = Symbol.for('rockbed.ILvErrorOr');\nexport type ILvErrorOr<T> = (ILvRealErrorRef | ILvValueRef<T>) & {\n readonly pair: () => [null, T] | [ILvRealErrorRef, null];\n};\n","import type { ILvErrorRef, ILvErrorOr, ILvRealErrorRef } from './error-base';\n\n//\n// Error类\n//\n// 用户给函数签名明确错误\n// function foo(): ILvErrorRef\n// return makeOk(); // 如果没有错误\n// return makeError(code, msg); // 指定错误码和携带消息\n//\n// const SomeError = LvErrorConst(code, msg); // 更推荐用LvErrorConst生成\n// return SomeError();\n//\n\nconst lvErrorRefSymbol = Symbol('lvErrorRef');\n\nexport function makeOk(): ILvErrorOr<never> {\n return {\n ok: true,\n value: null!,\n pair() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return [null, null!] as any;\n },\n code: 0,\n msg: '',\n ...{ [lvErrorRefSymbol]: true }, // 跳过类型检测\n };\n}\n\nexport function makeOkWith<T>(value: T): ILvErrorOr<T> {\n return {\n ok: true,\n value,\n pair() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return [null, value] as any;\n },\n code: 0,\n msg: '',\n ...{ [lvErrorRefSymbol]: true }, // 跳过类型检测\n };\n}\n\nfunction printCause(cause: ILvErrorRef | Error | undefined): string {\n if (cause === undefined) {\n return '';\n } else if (cause instanceof Error) {\n return `\\ncaused by [jsError]${cause.name}-${cause.message}`;\n } else {\n return `\\ncaused by [${cause.code}]${cause.msg}${cause.ok ? '' : printCause(cause.cause)}`;\n }\n}\n\nfunction internalMakeError(\n code: number,\n msg: string,\n cause?: ILvErrorRef | Error,\n errorInfo?: unknown,\n) {\n const errorRef: ILvRealErrorRef = {\n ok: false,\n code,\n msg,\n cause,\n errorInfo,\n toString() {\n return `[${code}]${msg}.${cause ? printCause(cause) : ''}`;\n },\n pair() {\n return [errorRef, null];\n },\n ...{ [lvErrorRefSymbol]: true }, // 跳过类型检测\n };\n return errorRef;\n}\n\nexport function makeError(code: number, msg: string, errorInfo?: unknown): ILvRealErrorRef {\n return internalMakeError(code, msg, undefined, errorInfo);\n}\n\nexport function makeErrorBy(\n code: number,\n msg: string,\n cause: ILvErrorRef | Error,\n errorInfo?: unknown,\n): ILvRealErrorRef {\n return internalMakeError(code, msg, cause, errorInfo);\n}\n\nexport function isLvErrorRef(val: unknown): val is ILvErrorRef {\n return typeof val === 'object' && val !== null && lvErrorRefSymbol in val;\n}\n","import { makeError, makeErrorBy } from './error-t';\n\n//\n// Error编译时错误对象\n//\nexport function lvErrorConst(code: number, msg: string) {\n return (rewrite?: string | Error) => {\n if (!rewrite) {\n return makeError(code, msg);\n }\n if (typeof rewrite === 'string') {\n return makeError(code, rewrite);\n }\n return makeErrorBy(code, rewrite.message, rewrite);\n };\n}\n","import { lvErrorConst } from './error-const';\n\n/**\n * 提供了通用的错误码(+1至+256)\n *\n * 注意:这里只是提供了通用的错误码,方便服务使用,但并不是要求服务一定使用如下的错误码来表明某种错误\n */\nexport enum GenericError {\n Ok = 0,\n Cancelled = 1, // 操作被取消\n TimedOut = 2, // 操作超时\n PermissionDenied = 3, // 无权限\n AlreadyExists = 4, // 已经存在(文件/记录等)\n NotSupported = 5, // 操作不支持\n ResourceUnavailable = 6, // 资源不可用\n OutOfRange = 7, // (参数/结果等)发生越界\n InvalidArgument = 8, // 无效参数\n NetworkFailed = 9, // 网络失败\n Interrupted = 10, // 操作被中断(捕获异常转为错误)\n ResultNil = 11, // 结果不存在(null or undefined转为错误)\n}\n\n/**\n * 通用错误码所对应的编译时常量对象(ErrorConst)\n */\nexport const cancelledError = lvErrorConst(GenericError.Cancelled, 'operation(s) cancelled.');\nexport const timeoutError = lvErrorConst(GenericError.TimedOut, 'operation(s) timed out.');\nexport const permissionDeniedError = lvErrorConst(\n GenericError.PermissionDenied,\n 'permission denied.',\n);\nexport const alreadyExistsError = lvErrorConst(GenericError.AlreadyExists, 'already exists.');\nexport const notSupportedError = lvErrorConst(\n GenericError.NotSupported,\n 'operation(s) not supported.',\n);\nexport const resourceUnavailableError = lvErrorConst(\n GenericError.ResourceUnavailable,\n 'resource is unavailable.',\n);\nexport const outOfRangeError = lvErrorConst(GenericError.OutOfRange, 'out of range.');\nexport const invalidArgumentError = lvErrorConst(\n GenericError.InvalidArgument,\n 'invalid arguments.',\n);\nexport const networkFailedError = lvErrorConst(GenericError.NetworkFailed, 'network failed.');\nexport const interruptedError = lvErrorConst(GenericError.Interrupted, 'interrupted.');\nexport const resultNilError = lvErrorConst(GenericError.ResultNil, 'result is nil.');\n","//\n// Disposable特征约束\n//\nexport interface IDisposable {\n dispose: () => void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nexport const EmptyDispose = Object.freeze<IDisposable>({ dispose() {} });\n","import type { IDisposable } from './dispose-base';\n\nlet disposableLogger: IDisposableLogger | null = null;\n\nexport interface IDisposableLogger {\n branch: (from: string, to: string) => void;\n end: () => void;\n}\n\nfunction setDisposableLogger(logger: IDisposableLogger | null): void {\n disposableLogger = logger;\n}\n\nfunction makeDefaultLogger() {\n return new (class implements IDisposableLogger {\n private readonly _dep: [string, string][] = [];\n\n branch(from: string, to: string): void {\n this._dep.push([from, to]);\n }\n\n end(): void {\n // console.log(this._dep);\n }\n })();\n}\n\n// 辅助能力 dispose触发时记录\nexport function BRANCH_DISPOSE(from: string, to: string) {\n disposableLogger?.branch(from, to);\n}\n\nexport function disposeWithLog<T extends IDisposable>(\n x: T,\n logger: IDisposableLogger = makeDefaultLogger(),\n) {\n setDisposableLogger(logger);\n x.dispose();\n logger.end();\n setDisposableLogger(null);\n}\n","import type { IDisposable } from './dispose-base';\nimport { BRANCH_DISPOSE } from './logger';\n\nexport class DisposableStore implements IDisposable {\n static DISABLE_DISPOSED_WARNING = false;\n\n private readonly _toDispose = new Set<IDisposable>();\n private _isDisposed = false;\n\n get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n dispose(): void {\n if (this._isDisposed) {\n // 不应该出现重复dispose\n /* eslint-disable no-console */\n console.warn(new Error('DisposableStore has disposed.').stack);\n return;\n }\n\n this._isDisposed = true;\n this.clear();\n }\n\n clear(): void {\n if (this._toDispose.size === 0) {\n return;\n }\n\n for (const disposable of this._toDispose) {\n BRANCH_DISPOSE(this.constructor.name, disposable.constructor.name);\n }\n\n try {\n // TODO(vorshen): 考虑异常情况\n for (const disposable of this._toDispose) {\n disposable.dispose();\n }\n } finally {\n this._toDispose.clear();\n }\n }\n\n add<T extends IDisposable>(o: T): T {\n if (!o) {\n return o;\n }\n if ((o as unknown as DisposableStore) === this) {\n throw new Error('Cannot register a disposable on itself.');\n }\n\n if (this._isDisposed) {\n if (!DisposableStore.DISABLE_DISPOSED_WARNING) {\n /* eslint-disable no-console */\n console.warn(\n new Error(\n 'Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!',\n ).stack,\n );\n }\n } else {\n this._toDispose.add(o);\n }\n\n return o;\n }\n}\n","import { DisposableStore } from './disposable-store';\nimport type { IDisposable } from './dispose-base';\nimport { BRANCH_DISPOSE } from './logger';\n\n//\n// Disposable基类\n//\n// 自动添加DisposableStore,提供默认的dispose和register方法\n//\nexport abstract class Disposable implements IDisposable {\n protected readonly _store = new DisposableStore();\n\n // 销毁该节点和所有的子节点\n dispose(): void {\n BRANCH_DISPOSE(this.constructor.name, this._store.constructor.name);\n\n this._store.dispose();\n }\n\n // 挂载子节点\n protected _register<T extends IDisposable>(o: T): T {\n if ((o as unknown as Disposable) === this) {\n throw new Error('Cannot register a disposable on itself!');\n }\n return this._store.add(o);\n }\n}\n\nexport class MutableDisposable<T extends IDisposable> implements IDisposable {\n private _value?: T;\n private _isDisposed = false;\n\n constructor(value?: T) {\n this.value = value;\n }\n\n get value(): T | undefined {\n return this._isDisposed ? undefined : this._value;\n }\n\n set value(value: T | undefined) {\n if (this._isDisposed || value === this._value) {\n return;\n }\n\n this._value?.dispose();\n this._value = value;\n }\n\n clear(): void {\n this.value = undefined;\n }\n\n dispose(): void {\n this._isDisposed = true;\n this._value?.dispose();\n this._value = undefined;\n }\n\n release(): T | undefined {\n const oldValue = this._value;\n this._value = undefined;\n return oldValue;\n }\n}\n\nexport class SafeDisposable<T extends IDisposable> implements IDisposable {\n private _value: T | null = null;\n\n constructor(value: T) {\n this._value = value;\n }\n\n isEmpty() {\n return this._value === null;\n }\n\n dispose() {\n if (!this._value) {\n return;\n }\n this._value.dispose();\n this._value = null;\n }\n}\n","import { SafeDisposable } from './disposable-t';\nimport { EmptyDispose } from './dispose-base';\n\nexport function makeSafeDisposable(fn: (...args: any) => any) {\n const disposable = new SafeDisposable({\n dispose: fn,\n });\n return disposable;\n}\n\nexport function makeEmptyDisposable() {\n return EmptyDispose;\n}\n","/* eslint-disable @typescript-eslint/prefer-promise-reject-errors */\nimport {\n makeOkWith,\n type ILvErrorOr,\n cancelledError,\n GenericError,\n timeoutError,\n type ILvErrorRef,\n makeOk,\n isLvErrorRef,\n} from '../error';\nimport { EmptyDispose, makeSafeDisposable, type IDisposable } from '../dispose';\n\nexport interface ICancellationToken {\n readonly isCancellationRequested: boolean;\n readonly reason?: string;\n readonly onCancellationRequested: (\n listener: () => any,\n thisArgs?: any,\n ) => IDisposable;\n}\n\nconst shortcutCancellationEvent = (callback: () => any, context?: any): IDisposable => {\n const handle = setTimeout(callback.bind(context), 0);\n return makeSafeDisposable(() => clearTimeout(handle));\n};\n\nclass MutableToken implements ICancellationToken, IDisposable {\n private _isCancelled = false;\n private _reason?: string;\n private readonly _listeners = new Set<() => void>();\n\n get isCancellationRequested(): boolean {\n return this._isCancelled;\n }\n\n get reason(): string | undefined {\n return this._reason;\n }\n\n onCancellationRequested(listener: () => any, thisArgs?: any): IDisposable {\n if (this._isCancelled) {\n return shortcutCancellationEvent(listener, thisArgs);\n }\n\n const wrappedListener = listener.bind(thisArgs);\n this._listeners.add(wrappedListener);\n return makeSafeDisposable(() => {\n this._listeners.delete(wrappedListener);\n });\n }\n\n cancel(reason?: string): void {\n if (this._isCancelled) {\n return;\n }\n\n this._reason = reason;\n this._isCancelled = true;\n for (const listener of this._listeners) {\n listener();\n }\n this._listeners.clear();\n }\n\n dispose(): void {\n this._listeners.clear();\n }\n}\n\nexport class CancellationToken {\n static None = Object.freeze<ICancellationToken>({\n isCancellationRequested: false,\n onCancellationRequested: () => EmptyDispose,\n });\n\n static Cancelled = Object.freeze<ICancellationToken>({\n isCancellationRequested: true,\n onCancellationRequested: shortcutCancellationEvent,\n });\n\n static Make(reason: string): ICancellationToken {\n return Object.freeze<ICancellationToken>({\n isCancellationRequested: true,\n onCancellationRequested: shortcutCancellationEvent,\n reason,\n });\n }\n}\n\nexport class CancellationTokenSource implements IDisposable {\n private _token?: ICancellationToken;\n private _abortController?: AbortController;\n\n get token(): ICancellationToken {\n if (!this._token) {\n this._token = new MutableToken();\n }\n return this._token;\n }\n\n get signal(): AbortSignal {\n if (!this._abortController) {\n this._abortController = new AbortController();\n }\n if (this._token?.isCancellationRequested) {\n this._abortController.abort(this._token.reason);\n }\n return this._abortController.signal;\n }\n\n cancel(reason?: string): void {\n if (!this._token) {\n this._token =\n reason === undefined ? CancellationToken.Cancelled : CancellationToken.Make(reason);\n } else if (this._token instanceof MutableToken) {\n this._token.cancel(reason);\n }\n this._abortController?.abort(reason);\n }\n\n dispose(cancel = false): void {\n if (cancel) {\n this.cancel();\n }\n if (!this._token) {\n this._token = CancellationToken.None;\n } else if (this._token instanceof MutableToken) {\n this._token.dispose();\n }\n }\n}\n\n/**\n * 一般来说Promise常用的场景有:\n * 1. 单次异步调用(new Promise)\n * 2. 批量promise调用(Promise.all)\n * 3. promise竞速调用(Promise.race)\n *\n * 但是原生能力有如下的缺陷\n * 1. 不支持取消某一次promise调用\n * 2. 不支持错误语义,promise.catch的重视程度比try catch还低\n * 3. 超时行为需要基于race封装\n *\n * 针对这三点,基建侧提供了高阶的promise能力\n * 1. makeCancelablePromise 返回一个可取消的promise\n * const promise = makeCancelablePromise(() => { ... });\n * promise.then((res) => {\n * // res是一个ILvErrorRef对象\n * });\n * // 可以直接取消promise\n * promise.cancel();\n *\n * 2. parallelPromise 并发执行promise,会自动观测ILvErrorRef语义\n * 当单个promise出现错误返回时,promise执行失败,尽可能调用所有cancelablePromise\n * 当单个promise出现reject时,promise执行失败,尽可能调用所有cancelablePromise,并且将reject继续上抛\n *\n * 3. makePromiseWithTimeout 让promise支持超时,可以提供默认值\n *\n * ——————————————————\n * Promise.allSettled和Promise.any在实际使用中场景较少,暂不提供错误语义包装\n */\n\n//\n// 可以cancel的promise对象\n//\nexport interface CancelablePromise<T> extends Promise<T> {\n cancel: () => void;\n}\n\n/**\n * 快速生成一个CancelablePromise对象\n */\nexport function makeCancelablePromise<T>(\n callback: (token: ICancellationToken) => Promise<T | ILvErrorOr<T>>,\n): CancelablePromise<ILvErrorOr<T>> {\n const source = new CancellationTokenSource();\n const thenable = callback(source.token);\n const promise = new Promise<ILvErrorOr<T>>((resolve, reject) => {\n const subscription = source.token.onCancellationRequested(() => {\n subscription.dispose();\n source.dispose();\n resolve(cancelledError());\n });\n Promise.resolve(thenable).then(\n (value) => {\n subscription.dispose();\n source.dispose();\n if (isLvErrorRef(value)) {\n resolve(value);\n } else {\n resolve(makeOkWith(value as T));\n }\n },\n (err) => {\n subscription.dispose();\n source.dispose();\n reject(err);\n },\n );\n });\n return new (class {\n cancel() {\n source.cancel();\n }\n then<TResult1 = T, TResult2 = never>(\n resolve?: ((value: ILvErrorOr<T>) => TResult1 | Promise<TResult1>) | null,\n reject?: ((reason: any) => TResult2 | Promise<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return promise.then(resolve, reject);\n }\n catch<TResult = never>(\n reject?: ((reason: any) => TResult | Promise<TResult>) | null,\n ): Promise<T | TResult> {\n return this.then(undefined, reject);\n }\n finally(onfinally?: (() => void) | null): Promise<ILvErrorOr<T>> {\n return promise.finally(onfinally);\n }\n })() as CancelablePromise<ILvErrorOr<T>>;\n}\n\n/**\n * 并行执行promise,当某一个失败,本次调用失败\n * 本质上和Promise.all差不多,相比较之下\n * 1. 包装了错误语义判断\n * 2. 当失败时,会尽可能尝试cancel其他promise\n *\n * 注意:某一个promise失败时,会尽可能尝试调用其他promise的cancel,但不保证一定有效\n * (有可能promiseA已经成功,但是primiseB在之后失败了)\n */\nexport function parallelPromise(promiseList: Promise<any>[]): Promise<ILvErrorRef> {\n if (promiseList.length === 0) {\n return Promise.resolve(makeOk());\n }\n\n let todo = promiseList.length;\n const finish = () => {\n todo = -1;\n for (const promise of promiseList) {\n (promise as Partial<CancelablePromise<any>>).cancel?.();\n }\n };\n\n return new Promise<ILvErrorRef>((resolve, reject) => {\n for (const promise of promiseList) {\n promise\n\n .then((res) => {\n if (isLvErrorRef(res) && !res.ok) {\n finish();\n resolve(res as ILvErrorRef);\n return;\n }\n todo--;\n if (todo === 0) {\n resolve(makeOk());\n }\n })\n .catch((err) => {\n finish();\n reject(err);\n });\n }\n });\n}\n\n/**\n * 包装一个promise,提供超时能力\n */\nexport function makePromiseWithTimeout<T>(\n callback: (token: ICancellationToken) => Promise<T | ILvErrorOr<T>>,\n timeout: number,\n defaultValue?: T, // 当发生超时时,提供的默认值\n): Promise<ILvErrorOr<T>> {\n const cancellable = makeCancelablePromise<T>(callback);\n const timer = setTimeout(() => {\n cancellable.cancel();\n }, timeout);\n return cancellable.then((res: ILvErrorOr<T>) => {\n clearTimeout(timer);\n if (res.ok) {\n return res;\n }\n // 如果是被取消,触发了超时\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n if (res.code === GenericError.Cancelled) {\n if (defaultValue !== undefined) {\n // 希望返回默认值\n return makeOkWith(defaultValue);\n }\n return timeoutError();\n } else {\n // 遇到其他错误时透传错误\n return res;\n }\n });\n}\n\n// 如果 proposal-promise-with-resolvers 通过了,那么这个函数就可以去掉了\n// https://github.com/microsoft/TypeScript/blob/1d96eb489e559f4f61522edb3c8b5987bbe948af/src/harness/util.ts#L115\nexport interface Deferred<T> {\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason: unknown) => void;\n promise: Promise<T>;\n}\n\nexport function defer<T = void>(): Deferred<T> {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<T>((_resolve, _reject) => {\n resolve = _resolve;\n reject = _reject;\n });\n return { resolve, reject, promise };\n}\n","/**\n * 等待一段时间\n * @param ms 单位毫秒\n */\nexport function wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","export interface IBarrier {\n isOpen: () => boolean;\n open: () => void;\n wait: () => Promise<boolean>;\n}\n\n/**\n * A barrier that is initially closed and then becomes opened permanently after a certain period of\n * time or when open is called explicitly\n */\nexport class Barrier {\n private _isOpen: boolean;\n private readonly _promise: Promise<boolean>;\n private _completePromise!: (v: boolean) => void;\n\n constructor() {\n this._isOpen = false;\n this._promise = new Promise<boolean>((c, e) => {\n this._completePromise = c;\n });\n }\n\n isOpen(): boolean {\n return this._isOpen;\n }\n\n open(): void {\n this._isOpen = true;\n this._completePromise(true);\n }\n\n wait(): Promise<boolean> {\n return this._promise;\n }\n}\n\nexport function makeBarrierByPromise(promise: Promise<any>, openWhenReject: boolean = false) {\n const barrier = new Barrier();\n promise.then(() => barrier.open());\n if (openWhenReject) {\n promise.catch((err) => {\n barrier.open();\n throw err;\n });\n }\n return barrier;\n}\n","/* eslint-disable @typescript-eslint/no-redundant-type-constituents */\nimport { makeSafeDisposable } from '../dispose';\nimport type { IDisposable } from '../dispose';\n\nexport interface EmitterOptions {\n onAddListener?: (...args: any) => any;\n onRemoveListener?: (...args: any) => any;\n onListenerError?: (e: any) => void;\n}\n\n/**\n * 默认错误处理:异步抛出监听器错误,避免阻塞当前事件分发。\n */\nexport function asyncUnexpectedErrorHandler(e: unknown): undefined {\n setTimeout(() => {\n throw e;\n }, 0);\n}\n\n/**\n * 同步抛出监听器错误,适合测试或需要立即失败的场景。\n */\nexport function syncUnexpectedError(e: unknown): undefined {\n throw e;\n}\n\n/**\n * 忽略监听器错误,适合明确允许 best-effort 通知的场景。\n */\nexport function ignoreUnexpectedError(_e: unknown): undefined {}\n\n//\n// 事件监听中的回调实体\n//\nclass Listener<TArgs extends any[]> {\n private readonly _callback: (...args: TArgs) => void;\n private readonly _callbackThis: any | undefined;\n\n constructor(callback: (...args: TArgs) => void, callbackThis: any | undefined) {\n this._callback = callback;\n this._callbackThis = callbackThis;\n }\n\n invoke(...args: TArgs): void {\n this._callback.call(this._callbackThis, ...args);\n }\n}\n\n//\n// 存放在EventDeliveryQueue中的元素\n//\nclass EventDeliveryQueueElement<TArgs extends any[]> {\n readonly emitter: Emitter<TArgs>;\n readonly listener: Listener<TArgs>;\n readonly event: TArgs;\n constructor(emitter: Emitter<TArgs>, listener: Listener<TArgs>, event: TArgs) {\n this.emitter = emitter;\n this.listener = listener;\n this.event = event;\n }\n}\n\nexport class EventDeliveryQueue {\n protected _queue: EventDeliveryQueueElement<any>[] = [];\n\n constructor(\n private readonly _onListenerError: (e: unknown) => void = asyncUnexpectedErrorHandler,\n ) {}\n\n get size(): number {\n return this._queue.length;\n }\n\n push<TArgs extends any[]>(\n emitter: Emitter<TArgs>,\n listener: Listener<TArgs>,\n event: TArgs,\n ): void {\n this._queue.push(new EventDeliveryQueueElement(emitter, listener, event));\n }\n\n clear<TArgs extends any[]>(emitter: Emitter<TArgs>): void {\n this._queue = this._queue.filter((element) => element.emitter !== emitter);\n }\n\n deliver(): void {\n while (this._queue.length > 0) {\n const element = this._queue.shift()!;\n try {\n element.listener.invoke(...element.event);\n } catch (e) {\n this._onListenerError(e);\n }\n }\n }\n}\n\nexport interface Event<T extends any[]> {\n (listener: (...args: T) => any, thisArgs?: any): IDisposable;\n}\n\nexport class Emitter<TArgs extends any[]> {\n protected _listeners?: Set<Listener<TArgs>>;\n private readonly _options?: EmitterOptions;\n private _disposed = false;\n private _event?: Event<TArgs>;\n private _deliveryQueue?: EventDeliveryQueue;\n\n constructor(options?: EmitterOptions) {\n this._options = options;\n }\n\n get event(): Event<TArgs> {\n if (this._event) {\n return this._event;\n }\n\n this._event = (callback: (...args: TArgs) => any, thisArgs?: any): IDisposable => {\n if (!this._listeners) {\n this._listeners = new Set();\n }\n\n const listener = new Listener(callback, thisArgs);\n this._listeners.add(listener);\n\n if (this._options?.onAddListener) {\n this._options.onAddListener(this, callback, thisArgs);\n }\n\n // 生成可销毁函数返回\n const result = () => {\n if (!this._disposed) {\n this._listeners?.delete(listener);\n if (this._options?.onRemoveListener) {\n this._options.onRemoveListener(this, callback, thisArgs);\n }\n }\n };\n\n return makeSafeDisposable(result);\n };\n\n return this._event;\n }\n\n dispose(): void {\n if (this._disposed) {\n return;\n }\n this._disposed = true;\n this._listeners?.clear();\n this._deliveryQueue?.clear(this);\n }\n\n fire(...event: TArgs): void {\n if (!this._listeners) {\n return;\n }\n this._deliveryQueue ??= new EventDeliveryQueue(this._options?.onListenerError);\n\n for (const listener of this._listeners) {\n this._deliveryQueue.push(this, listener, event);\n }\n this._deliveryQueue.deliver();\n }\n}\n\n// 辅助能力:只监听某个事件一次\nexport function listenOnce<TArgs extends any[]>(event: Event<TArgs>): Event<TArgs> {\n return (listener, thisArgs = null) => {\n let didFire = false;\n let result: IDisposable | undefined = undefined;\n\n result = event((...args) => {\n if (didFire) {\n return;\n }\n if (result) {\n result.dispose();\n } else {\n didFire = true;\n }\n\n return listener.call(thisArgs, ...args);\n }, null);\n\n if (didFire) {\n result.dispose();\n }\n\n return result;\n };\n}\n","export function safeJsonParse<T>(value: string): T {\n try {\n return JSON.parse(value);\n } catch (error) {\n return {} as T;\n }\n}\n\nexport function safeJsonStringify<T>(value: T): string {\n try {\n return JSON.stringify(value);\n } catch (error) {\n return '{}';\n }\n}","import { lvAssert } from '../assert';\nimport { Emitter, type Event } from '../event';\n\n//\n// 资源对应的是标准库中的 unsigned state 以及相关的位运算\n// 我们用两个具体的Capability结构实现(Capability命名来源于标准库)\n//\n\n/**\n * 资源状态\n */\nexport enum CapabilityStatus {\n Unlocked,\n Locked,\n}\n\n/**\n * 独享的资源\n *\n * acquire 获取控制权\n * release 释放控制权\n */\nexport class Capability {\n public onUnlocked: Event<[]>;\n\n private readonly _onUnlocked = new Emitter<[]>();\n private _status = CapabilityStatus.Unlocked;\n\n constructor() {\n this.onUnlocked = this._onUnlocked.event;\n }\n\n get status(): CapabilityStatus {\n return this._status;\n }\n\n public acquire(): void {\n lvAssert(this._status === CapabilityStatus.Unlocked);\n this._status = CapabilityStatus.Locked;\n }\n\n public release(): void {\n lvAssert(this._status === CapabilityStatus.Locked);\n this._status = CapabilityStatus.Unlocked;\n this._onUnlocked.fire();\n }\n}\n\n/**\n * 共享的资源\n *\n * acquire 获取控制权\n * release 释放控制权\n */\nexport class SharedCapability {\n public onUnlocked: Event<[]>;\n\n private readonly _onUnlocked = new Emitter<[]>();\n private _status = CapabilityStatus.Unlocked;\n private _counter = 0;\n\n constructor() {\n this.onUnlocked = this._onUnlocked.event;\n }\n\n get status(): CapabilityStatus {\n return this._status;\n }\n\n get counter(): number {\n return this._counter;\n }\n\n public acquire() {\n if (this._status === CapabilityStatus.Unlocked) {\n this._status = CapabilityStatus.Locked;\n }\n this._counter++;\n }\n\n public release() {\n lvAssert(this._counter > 0);\n this._counter--;\n if (this._counter === 0) {\n this._status = CapabilityStatus.Unlocked;\n this._onUnlocked.fire();\n }\n }\n}\n","import type { Event } from '../event';\nimport { Emitter } from '../event';\n\n/**\n * 信号\n *\n * 用来模拟标准库的condition_variable\n * 提供监听某个信号被激活的能力\n */\nexport class Semaphore {\n public onActive: Event<[]>;\n private readonly _onActive = new Emitter<[]>();\n\n constructor() {\n this.onActive = this._onActive.event;\n }\n\n public notify(): void {\n this._onActive.fire();\n }\n}\n","import { lvAssert, lvAssertNotNil } from '../assert';\nimport { listenOnce } from '../event';\nimport { SharedCapability, Capability, CapabilityStatus } from './capability';\nimport { Semaphore } from './semaphore';\n\n/**\n * 提供读写能力的共享互斥量\n *\n * 参考C++17标准库双门思想实现\n * 接口也与标准库保持一致\n * 方法内部禁止promise,只可以对外暴露promise\n *\n * 核心\n * - 写写互斥,读写互斥,读读可重入\n *\n * 使用举例:\n * class Foo {\n * private _mutex = new SharedMutex();\n *\n * async add() {\n * // 上写锁\n * await this._mutex.lock();\n * // ...write something\n * this._mutex.unlock();\n * }\n *\n * async getSomething1() {\n * // 上读锁\n * await this._mutex.lockShared();\n * try {\n * return xxx;\n * } finally {\n * this._mutex.unlockShared();\n * }\n * }\n *\n * async getSomething2() {\n * // 上读锁\n * await this._mutex.lockShared();\n * try {\n * return xxx;\n * } finally {\n * this._mutex.unlockShared();\n * }\n * }\n * }\n */\nexport class SharedMutex {\n // 在第一道门外等待的写者\n private readonly _waitingWriters: Semaphore[] = [];\n\n // 已经通过了第一道门的写者\n // 如果在第二道门外等待,状态为sharedLocked\n // 如果已经进入到第二道门内拿到了锁,状态为locked\n private _writer?: Capability;\n\n // 在第一道门外等待的读者\n private _waitingReader?: Semaphore;\n\n // 拿到锁的读者\n private _reader?: SharedCapability;\n\n /**\n * 是否被锁住\n */\n public isLocked(): boolean {\n return Boolean(this._writer) || this._readerCount !== 0;\n }\n\n /**\n * 等待并获取写锁\n */\n public lock(): Promise<void> {\n return new Promise<void>((resolve) => {\n // 第一道门\n if (this._writer) {\n // 如果已经有写者进入了,其他写者等待\n const token = new Semaphore();\n this._waitingWriters.push(token);\n token.onActive(() => {\n this._writerEnterGate1(resolve);\n });\n } else {\n this._writerEnterGate1(resolve);\n }\n });\n }\n\n /**\n * 尝试获取写锁,立刻返回结果\n */\n public tryLock(): boolean {\n if (this._writer || this._readerCount > 0) {\n return false;\n }\n // 这里不需要await,一定可以上锁\n this.lock();\n return true;\n }\n\n /**\n * 解除写锁\n */\n public unLock(): void {\n lvAssertNotNil(this._writer);\n\n // 打开第一道门\n this._writer.release();\n }\n\n /**\n * 解除写锁。`unLock` 的常规拼写别名。\n */\n public unlock(): void {\n this.unLock();\n }\n\n /**\n * 等待并获取读锁\n */\n public lockShared(): Promise<void> {\n return new Promise<void>((resolve) => {\n // 读者只需要进第一道门\n if (this._writer) {\n // 如果有写者已经进入了第一道门,读者等待\n if (!this._waitingReader) {\n this._waitingReader = new Semaphore();\n }\n this._waitingReader.onActive(() => {\n this._readerEnterGate1(resolve);\n });\n } else {\n this._readerEnterGate1(resolve);\n }\n });\n }\n\n /**\n * 尝试获取读锁,立刻返回结果\n */\n public tryLockShared(): boolean {\n if (this._writer) {\n return false;\n }\n // 不需要await,一定可以上锁\n this.lockShared();\n return true;\n }\n\n /**\n * 解除读锁\n */\n public unLockShared(): void {\n lvAssertNotNil(this._reader);\n if (this._writer) {\n // TODO(niurouwan): 暂时保留,方便验证,稳定后可以去掉\n lvAssert(this._writer.status === CapabilityStatus.Unlocked);\n }\n\n this._reader.release();\n }\n\n /**\n * 解除读锁。`unLockShared` 的常规拼写别名。\n */\n public unlockShared(): void {\n this.unLockShared();\n }\n\n /**\n * 获取当前读者数量\n */\n private get _readerCount(): number {\n return this._reader ? this._reader.counter : 0;\n }\n\n /**\n * 写者进入第一道门\n */\n private _writerEnterGate1(resolve: () => void): void {\n lvAssert(!this._writer);\n // 确定写者,关第一道门\n this._writer = new Capability();\n\n // 第二道门\n // 等待所有读者出去\n if (this._readerCount > 0) {\n listenOnce(this._reader!.onUnlocked)(() => {\n this._writerEnterGate2(resolve);\n });\n } else {\n this._writerEnterGate2(resolve);\n }\n }\n\n /**\n * 写者进入第二道门\n */\n private _writerEnterGate2(resolve: () => void): void {\n lvAssertNotNil(this._writer);\n lvAssert(this._readerCount === 0);\n\n // 成功加锁\n this._writer.acquire();\n listenOnce(this._writer.onUnlocked)(() => {\n lvAssertNotNil(this._writer);\n // 不再持有\n this._writer = undefined;\n this._moveForward();\n });\n resolve();\n }\n\n /**\n * 读者进入第一道门\n */\n private _readerEnterGate1(resolve: () => void): void {\n lvAssert(!this._writer);\n\n // 门外等待的读者清除\n this._waitingReader = undefined;\n\n if (!this._reader) {\n this._reader = new SharedCapability();\n this._reader.acquire();\n listenOnce(this._reader.onUnlocked)(() => {\n this._moveForward();\n });\n } else {\n this._reader.acquire();\n }\n resolve();\n }\n\n /**\n * 锁释放时推进流程\n */\n private _moveForward(): void {\n // 如果有写者在等待在第二道门前面,那么此时推进的一定是读锁释放,直接return即可\n if (this._writer) {\n return;\n }\n\n // 写者优先,优先通知在第一道门前面的写者\n if (this._waitingWriters.length > 0) {\n const semaphore = this._waitingWriters.shift()!;\n semaphore.notify();\n return;\n }\n\n // 最后通知第一道门前面的读者\n if (this._waitingReader) {\n this._waitingReader.notify();\n }\n }\n}\n","export interface ISuccessResponse<T = any> {\n code: 0;\n data: T;\n msg: string;\n}\n\nexport interface IErrorResponse {\n code: Exclude<number, 0>;\n msg: string;\n}\n\nexport type IResponse<T = any> = ISuccessResponse<T> | IErrorResponse;\n\nexport function makeSuccessResponse<T = any>(data: T): ISuccessResponse<T> {\n return {\n code: 0,\n data,\n msg: 'success',\n };\n}\n\nexport function makeErrorResponse(code: number, msg: string) {\n return {\n code,\n msg,\n };\n}\n"],"mappings":"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","names":["GenericError"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/json/json.ts
|
|
2
|
+
function safeJsonParse(value) {
|
|
3
|
+
try {
|
|
4
|
+
return JSON.parse(value);
|
|
5
|
+
} catch (error) {
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function safeJsonStringify(value) {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.stringify(value);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
return "{}";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
safeJsonParse,
|
|
18
|
+
safeJsonStringify
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/json/json.ts"],"sourcesContent":["export function safeJsonParse<T>(value: string): T {\n try {\n return JSON.parse(value);\n } catch (error) {\n return {} as T;\n }\n}\n\nexport function safeJsonStringify<T>(value: T): string {\n try {\n return JSON.stringify(value);\n } catch (error) {\n return '{}';\n }\n}"],"mappings":";AAAO,SAAS,cAAiB,OAAkB;AACjD,MAAI;AACF,WAAO,KAAK,MAAM,KAAK;AAAA,EACzB,SAAS,OAAO;AACd,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,kBAAqB,OAAkB;AACrD,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,SAAS,OAAO;AACd,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 提供读写能力的共享互斥量
|
|
3
|
+
*
|
|
4
|
+
* 参考C++17标准库双门思想实现
|
|
5
|
+
* 接口也与标准库保持一致
|
|
6
|
+
* 方法内部禁止promise,只可以对外暴露promise
|
|
7
|
+
*
|
|
8
|
+
* 核心
|
|
9
|
+
* - 写写互斥,读写互斥,读读可重入
|
|
10
|
+
*
|
|
11
|
+
* 使用举例:
|
|
12
|
+
* class Foo {
|
|
13
|
+
* private _mutex = new SharedMutex();
|
|
14
|
+
*
|
|
15
|
+
* async add() {
|
|
16
|
+
* // 上写锁
|
|
17
|
+
* await this._mutex.lock();
|
|
18
|
+
* // ...write something
|
|
19
|
+
* this._mutex.unlock();
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* async getSomething1() {
|
|
23
|
+
* // 上读锁
|
|
24
|
+
* await this._mutex.lockShared();
|
|
25
|
+
* try {
|
|
26
|
+
* return xxx;
|
|
27
|
+
* } finally {
|
|
28
|
+
* this._mutex.unlockShared();
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* async getSomething2() {
|
|
33
|
+
* // 上读锁
|
|
34
|
+
* await this._mutex.lockShared();
|
|
35
|
+
* try {
|
|
36
|
+
* return xxx;
|
|
37
|
+
* } finally {
|
|
38
|
+
* this._mutex.unlockShared();
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
*/
|
|
43
|
+
declare class SharedMutex {
|
|
44
|
+
private readonly _waitingWriters;
|
|
45
|
+
private _writer?;
|
|
46
|
+
private _waitingReader?;
|
|
47
|
+
private _reader?;
|
|
48
|
+
/**
|
|
49
|
+
* 是否被锁住
|
|
50
|
+
*/
|
|
51
|
+
isLocked(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* 等待并获取写锁
|
|
54
|
+
*/
|
|
55
|
+
lock(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* 尝试获取写锁,立刻返回结果
|
|
58
|
+
*/
|
|
59
|
+
tryLock(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* 解除写锁
|
|
62
|
+
*/
|
|
63
|
+
unLock(): void;
|
|
64
|
+
/**
|
|
65
|
+
* 解除写锁。`unLock` 的常规拼写别名。
|
|
66
|
+
*/
|
|
67
|
+
unlock(): void;
|
|
68
|
+
/**
|
|
69
|
+
* 等待并获取读锁
|
|
70
|
+
*/
|
|
71
|
+
lockShared(): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* 尝试获取读锁,立刻返回结果
|
|
74
|
+
*/
|
|
75
|
+
tryLockShared(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* 解除读锁
|
|
78
|
+
*/
|
|
79
|
+
unLockShared(): void;
|
|
80
|
+
/**
|
|
81
|
+
* 解除读锁。`unLockShared` 的常规拼写别名。
|
|
82
|
+
*/
|
|
83
|
+
unlockShared(): void;
|
|
84
|
+
/**
|
|
85
|
+
* 获取当前读者数量
|
|
86
|
+
*/
|
|
87
|
+
private get _readerCount();
|
|
88
|
+
/**
|
|
89
|
+
* 写者进入第一道门
|
|
90
|
+
*/
|
|
91
|
+
private _writerEnterGate1;
|
|
92
|
+
/**
|
|
93
|
+
* 写者进入第二道门
|
|
94
|
+
*/
|
|
95
|
+
private _writerEnterGate2;
|
|
96
|
+
/**
|
|
97
|
+
* 读者进入第一道门
|
|
98
|
+
*/
|
|
99
|
+
private _readerEnterGate1;
|
|
100
|
+
/**
|
|
101
|
+
* 锁释放时推进流程
|
|
102
|
+
*/
|
|
103
|
+
private _moveForward;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { SharedMutex };
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
// src/assert/assert.ts
|
|
2
|
+
function abort(reason) {
|
|
3
|
+
throw new Error(`lvAssert(${reason})`);
|
|
4
|
+
}
|
|
5
|
+
function lvAssert(expr, reason) {
|
|
6
|
+
if (!expr) {
|
|
7
|
+
abort(reason ?? "#expr is false");
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function lvAssertNotNil(val, reason) {
|
|
11
|
+
if (val === null || val === void 0) {
|
|
12
|
+
abort(reason ?? "#val is nil");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/dispose/disposable-t.ts
|
|
17
|
+
var SafeDisposable = class {
|
|
18
|
+
_value = null;
|
|
19
|
+
constructor(value) {
|
|
20
|
+
this._value = value;
|
|
21
|
+
}
|
|
22
|
+
isEmpty() {
|
|
23
|
+
return this._value === null;
|
|
24
|
+
}
|
|
25
|
+
dispose() {
|
|
26
|
+
if (!this._value) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this._value.dispose();
|
|
30
|
+
this._value = null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// src/dispose/disposable-utils.ts
|
|
35
|
+
function makeSafeDisposable(fn) {
|
|
36
|
+
const disposable = new SafeDisposable({
|
|
37
|
+
dispose: fn
|
|
38
|
+
});
|
|
39
|
+
return disposable;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/event/emitter.ts
|
|
43
|
+
function asyncUnexpectedErrorHandler(e) {
|
|
44
|
+
setTimeout(() => {
|
|
45
|
+
throw e;
|
|
46
|
+
}, 0);
|
|
47
|
+
}
|
|
48
|
+
var Listener = class {
|
|
49
|
+
_callback;
|
|
50
|
+
_callbackThis;
|
|
51
|
+
constructor(callback, callbackThis) {
|
|
52
|
+
this._callback = callback;
|
|
53
|
+
this._callbackThis = callbackThis;
|
|
54
|
+
}
|
|
55
|
+
invoke(...args) {
|
|
56
|
+
this._callback.call(this._callbackThis, ...args);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var EventDeliveryQueueElement = class {
|
|
60
|
+
emitter;
|
|
61
|
+
listener;
|
|
62
|
+
event;
|
|
63
|
+
constructor(emitter, listener, event) {
|
|
64
|
+
this.emitter = emitter;
|
|
65
|
+
this.listener = listener;
|
|
66
|
+
this.event = event;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var EventDeliveryQueue = class {
|
|
70
|
+
constructor(_onListenerError = asyncUnexpectedErrorHandler) {
|
|
71
|
+
this._onListenerError = _onListenerError;
|
|
72
|
+
}
|
|
73
|
+
_onListenerError;
|
|
74
|
+
_queue = [];
|
|
75
|
+
get size() {
|
|
76
|
+
return this._queue.length;
|
|
77
|
+
}
|
|
78
|
+
push(emitter, listener, event) {
|
|
79
|
+
this._queue.push(new EventDeliveryQueueElement(emitter, listener, event));
|
|
80
|
+
}
|
|
81
|
+
clear(emitter) {
|
|
82
|
+
this._queue = this._queue.filter((element) => element.emitter !== emitter);
|
|
83
|
+
}
|
|
84
|
+
deliver() {
|
|
85
|
+
while (this._queue.length > 0) {
|
|
86
|
+
const element = this._queue.shift();
|
|
87
|
+
try {
|
|
88
|
+
element.listener.invoke(...element.event);
|
|
89
|
+
} catch (e) {
|
|
90
|
+
this._onListenerError(e);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var Emitter = class {
|
|
96
|
+
_listeners;
|
|
97
|
+
_options;
|
|
98
|
+
_disposed = false;
|
|
99
|
+
_event;
|
|
100
|
+
_deliveryQueue;
|
|
101
|
+
constructor(options) {
|
|
102
|
+
this._options = options;
|
|
103
|
+
}
|
|
104
|
+
get event() {
|
|
105
|
+
if (this._event) {
|
|
106
|
+
return this._event;
|
|
107
|
+
}
|
|
108
|
+
this._event = (callback, thisArgs) => {
|
|
109
|
+
if (!this._listeners) {
|
|
110
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
111
|
+
}
|
|
112
|
+
const listener = new Listener(callback, thisArgs);
|
|
113
|
+
this._listeners.add(listener);
|
|
114
|
+
if (this._options?.onAddListener) {
|
|
115
|
+
this._options.onAddListener(this, callback, thisArgs);
|
|
116
|
+
}
|
|
117
|
+
const result = () => {
|
|
118
|
+
if (!this._disposed) {
|
|
119
|
+
this._listeners?.delete(listener);
|
|
120
|
+
if (this._options?.onRemoveListener) {
|
|
121
|
+
this._options.onRemoveListener(this, callback, thisArgs);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
return makeSafeDisposable(result);
|
|
126
|
+
};
|
|
127
|
+
return this._event;
|
|
128
|
+
}
|
|
129
|
+
dispose() {
|
|
130
|
+
if (this._disposed) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
this._disposed = true;
|
|
134
|
+
this._listeners?.clear();
|
|
135
|
+
this._deliveryQueue?.clear(this);
|
|
136
|
+
}
|
|
137
|
+
fire(...event) {
|
|
138
|
+
if (!this._listeners) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
this._deliveryQueue ??= new EventDeliveryQueue(this._options?.onListenerError);
|
|
142
|
+
for (const listener of this._listeners) {
|
|
143
|
+
this._deliveryQueue.push(this, listener, event);
|
|
144
|
+
}
|
|
145
|
+
this._deliveryQueue.deliver();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
function listenOnce(event) {
|
|
149
|
+
return (listener, thisArgs = null) => {
|
|
150
|
+
let didFire = false;
|
|
151
|
+
let result = void 0;
|
|
152
|
+
result = event((...args) => {
|
|
153
|
+
if (didFire) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (result) {
|
|
157
|
+
result.dispose();
|
|
158
|
+
} else {
|
|
159
|
+
didFire = true;
|
|
160
|
+
}
|
|
161
|
+
return listener.call(thisArgs, ...args);
|
|
162
|
+
}, null);
|
|
163
|
+
if (didFire) {
|
|
164
|
+
result.dispose();
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/lock/capability.ts
|
|
171
|
+
var Capability = class {
|
|
172
|
+
onUnlocked;
|
|
173
|
+
_onUnlocked = new Emitter();
|
|
174
|
+
_status = 0 /* Unlocked */;
|
|
175
|
+
constructor() {
|
|
176
|
+
this.onUnlocked = this._onUnlocked.event;
|
|
177
|
+
}
|
|
178
|
+
get status() {
|
|
179
|
+
return this._status;
|
|
180
|
+
}
|
|
181
|
+
acquire() {
|
|
182
|
+
lvAssert(this._status === 0 /* Unlocked */);
|
|
183
|
+
this._status = 1 /* Locked */;
|
|
184
|
+
}
|
|
185
|
+
release() {
|
|
186
|
+
lvAssert(this._status === 1 /* Locked */);
|
|
187
|
+
this._status = 0 /* Unlocked */;
|
|
188
|
+
this._onUnlocked.fire();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
var SharedCapability = class {
|
|
192
|
+
onUnlocked;
|
|
193
|
+
_onUnlocked = new Emitter();
|
|
194
|
+
_status = 0 /* Unlocked */;
|
|
195
|
+
_counter = 0;
|
|
196
|
+
constructor() {
|
|
197
|
+
this.onUnlocked = this._onUnlocked.event;
|
|
198
|
+
}
|
|
199
|
+
get status() {
|
|
200
|
+
return this._status;
|
|
201
|
+
}
|
|
202
|
+
get counter() {
|
|
203
|
+
return this._counter;
|
|
204
|
+
}
|
|
205
|
+
acquire() {
|
|
206
|
+
if (this._status === 0 /* Unlocked */) {
|
|
207
|
+
this._status = 1 /* Locked */;
|
|
208
|
+
}
|
|
209
|
+
this._counter++;
|
|
210
|
+
}
|
|
211
|
+
release() {
|
|
212
|
+
lvAssert(this._counter > 0);
|
|
213
|
+
this._counter--;
|
|
214
|
+
if (this._counter === 0) {
|
|
215
|
+
this._status = 0 /* Unlocked */;
|
|
216
|
+
this._onUnlocked.fire();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// src/lock/semaphore.ts
|
|
222
|
+
var Semaphore = class {
|
|
223
|
+
onActive;
|
|
224
|
+
_onActive = new Emitter();
|
|
225
|
+
constructor() {
|
|
226
|
+
this.onActive = this._onActive.event;
|
|
227
|
+
}
|
|
228
|
+
notify() {
|
|
229
|
+
this._onActive.fire();
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// src/lock/shared-mutex.ts
|
|
234
|
+
var SharedMutex = class {
|
|
235
|
+
// 在第一道门外等待的写者
|
|
236
|
+
_waitingWriters = [];
|
|
237
|
+
// 已经通过了第一道门的写者
|
|
238
|
+
// 如果在第二道门外等待,状态为sharedLocked
|
|
239
|
+
// 如果已经进入到第二道门内拿到了锁,状态为locked
|
|
240
|
+
_writer;
|
|
241
|
+
// 在第一道门外等待的读者
|
|
242
|
+
_waitingReader;
|
|
243
|
+
// 拿到锁的读者
|
|
244
|
+
_reader;
|
|
245
|
+
/**
|
|
246
|
+
* 是否被锁住
|
|
247
|
+
*/
|
|
248
|
+
isLocked() {
|
|
249
|
+
return Boolean(this._writer) || this._readerCount !== 0;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* 等待并获取写锁
|
|
253
|
+
*/
|
|
254
|
+
lock() {
|
|
255
|
+
return new Promise((resolve) => {
|
|
256
|
+
if (this._writer) {
|
|
257
|
+
const token = new Semaphore();
|
|
258
|
+
this._waitingWriters.push(token);
|
|
259
|
+
token.onActive(() => {
|
|
260
|
+
this._writerEnterGate1(resolve);
|
|
261
|
+
});
|
|
262
|
+
} else {
|
|
263
|
+
this._writerEnterGate1(resolve);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* 尝试获取写锁,立刻返回结果
|
|
269
|
+
*/
|
|
270
|
+
tryLock() {
|
|
271
|
+
if (this._writer || this._readerCount > 0) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
this.lock();
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* 解除写锁
|
|
279
|
+
*/
|
|
280
|
+
unLock() {
|
|
281
|
+
lvAssertNotNil(this._writer);
|
|
282
|
+
this._writer.release();
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* 解除写锁。`unLock` 的常规拼写别名。
|
|
286
|
+
*/
|
|
287
|
+
unlock() {
|
|
288
|
+
this.unLock();
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* 等待并获取读锁
|
|
292
|
+
*/
|
|
293
|
+
lockShared() {
|
|
294
|
+
return new Promise((resolve) => {
|
|
295
|
+
if (this._writer) {
|
|
296
|
+
if (!this._waitingReader) {
|
|
297
|
+
this._waitingReader = new Semaphore();
|
|
298
|
+
}
|
|
299
|
+
this._waitingReader.onActive(() => {
|
|
300
|
+
this._readerEnterGate1(resolve);
|
|
301
|
+
});
|
|
302
|
+
} else {
|
|
303
|
+
this._readerEnterGate1(resolve);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* 尝试获取读锁,立刻返回结果
|
|
309
|
+
*/
|
|
310
|
+
tryLockShared() {
|
|
311
|
+
if (this._writer) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
this.lockShared();
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* 解除读锁
|
|
319
|
+
*/
|
|
320
|
+
unLockShared() {
|
|
321
|
+
lvAssertNotNil(this._reader);
|
|
322
|
+
if (this._writer) {
|
|
323
|
+
lvAssert(this._writer.status === 0 /* Unlocked */);
|
|
324
|
+
}
|
|
325
|
+
this._reader.release();
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* 解除读锁。`unLockShared` 的常规拼写别名。
|
|
329
|
+
*/
|
|
330
|
+
unlockShared() {
|
|
331
|
+
this.unLockShared();
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* 获取当前读者数量
|
|
335
|
+
*/
|
|
336
|
+
get _readerCount() {
|
|
337
|
+
return this._reader ? this._reader.counter : 0;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* 写者进入第一道门
|
|
341
|
+
*/
|
|
342
|
+
_writerEnterGate1(resolve) {
|
|
343
|
+
lvAssert(!this._writer);
|
|
344
|
+
this._writer = new Capability();
|
|
345
|
+
if (this._readerCount > 0) {
|
|
346
|
+
listenOnce(this._reader.onUnlocked)(() => {
|
|
347
|
+
this._writerEnterGate2(resolve);
|
|
348
|
+
});
|
|
349
|
+
} else {
|
|
350
|
+
this._writerEnterGate2(resolve);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* 写者进入第二道门
|
|
355
|
+
*/
|
|
356
|
+
_writerEnterGate2(resolve) {
|
|
357
|
+
lvAssertNotNil(this._writer);
|
|
358
|
+
lvAssert(this._readerCount === 0);
|
|
359
|
+
this._writer.acquire();
|
|
360
|
+
listenOnce(this._writer.onUnlocked)(() => {
|
|
361
|
+
lvAssertNotNil(this._writer);
|
|
362
|
+
this._writer = void 0;
|
|
363
|
+
this._moveForward();
|
|
364
|
+
});
|
|
365
|
+
resolve();
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* 读者进入第一道门
|
|
369
|
+
*/
|
|
370
|
+
_readerEnterGate1(resolve) {
|
|
371
|
+
lvAssert(!this._writer);
|
|
372
|
+
this._waitingReader = void 0;
|
|
373
|
+
if (!this._reader) {
|
|
374
|
+
this._reader = new SharedCapability();
|
|
375
|
+
this._reader.acquire();
|
|
376
|
+
listenOnce(this._reader.onUnlocked)(() => {
|
|
377
|
+
this._moveForward();
|
|
378
|
+
});
|
|
379
|
+
} else {
|
|
380
|
+
this._reader.acquire();
|
|
381
|
+
}
|
|
382
|
+
resolve();
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* 锁释放时推进流程
|
|
386
|
+
*/
|
|
387
|
+
_moveForward() {
|
|
388
|
+
if (this._writer) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (this._waitingWriters.length > 0) {
|
|
392
|
+
const semaphore = this._waitingWriters.shift();
|
|
393
|
+
semaphore.notify();
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (this._waitingReader) {
|
|
397
|
+
this._waitingReader.notify();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
export {
|
|
402
|
+
SharedMutex
|
|
403
|
+
};
|
|
404
|
+
//# sourceMappingURL=index.js.map
|