@zk-tech/bedrock 0.0.1 → 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/dist/async/index.cjs.map +1 -1
- package/dist/async/index.d.cts +2 -2
- package/dist/async/index.d.ts +2 -2
- package/dist/async/index.js.map +1 -1
- package/dist/error/index.cjs.map +1 -1
- package/dist/error/index.d.cts +19 -19
- package/dist/error/index.d.ts +19 -19
- package/dist/error/index.js.map +1 -1
- package/dist/{error-base-B4zaiJ5m.d.cts → error-base-DOFtBFla.d.cts} +8 -8
- package/dist/{error-base-B4zaiJ5m.d.ts → error-base-DOFtBFla.d.ts} +8 -8
- package/dist/promise/index.cjs.map +1 -1
- package/dist/promise/index.d.cts +4 -4
- package/dist/promise/index.d.ts +4 -4
- package/dist/promise/index.js.map +1 -1
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +2 -2
- package/dist/worker/index.d.ts +2 -2
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -2
- package/src/_internal/logger.ts +0 -59
- package/src/array/array.test.ts +0 -35
- package/src/array/array.ts +0 -25
- package/src/array/index.ts +0 -1
- package/src/assert/assert.test.ts +0 -86
- package/src/assert/assert.ts +0 -42
- package/src/assert/index.ts +0 -2
- package/src/async/barrier.test.ts +0 -90
- package/src/async/barrier.ts +0 -58
- package/src/async/cancellation.test.ts +0 -85
- package/src/async/cancellation.ts +0 -193
- package/src/async/index.ts +0 -18
- package/src/async/queue/queue.test.ts +0 -70
- package/src/async/queue/queue.ts +0 -56
- package/src/async/queue/task.test.ts +0 -155
- package/src/async/queue/task.ts +0 -67
- package/src/async/utils.test.ts +0 -28
- package/src/async/utils.ts +0 -8
- package/src/async/wait.ts +0 -9
- package/src/byte/format.test.ts +0 -64
- package/src/byte/format.ts +0 -44
- package/src/byte/index.ts +0 -2
- package/src/byte/node_modules/.vitest/results.json +0 -1
- package/src/byte/var.ts +0 -11
- package/src/cache/index.ts +0 -2
- package/src/cache/lru-with-timeout.test.ts +0 -88
- package/src/cache/lru-with-timeout.ts +0 -85
- package/src/cache/lru.test.ts +0 -56
- package/src/cache/lru.ts +0 -59
- package/src/context/context.test.ts +0 -17
- package/src/context/context.ts +0 -60
- package/src/context/index.ts +0 -8
- package/src/di/base.ts +0 -73
- package/src/di/container-service.test.ts +0 -179
- package/src/di/context.web.tsx +0 -41
- package/src/di/descriptor.ts +0 -31
- package/src/di/idle-value.test.ts +0 -73
- package/src/di/idle-value.ts +0 -63
- package/src/di/index.common.ts +0 -32
- package/src/di/index.ts +0 -2
- package/src/di/instantiation-service.interface.ts +0 -46
- package/src/di/instantiation-service.test.ts +0 -337
- package/src/di/instantiation-service.ts +0 -468
- package/src/di/lazy/foo.mock.ts +0 -28
- package/src/di/lazy/idle-load.ts +0 -39
- package/src/di/lazy/index.ts +0 -4
- package/src/di/lazy/lazy-service.test.ts +0 -65
- package/src/di/lazy/lazy-service.ts +0 -71
- package/src/di/lazy/type.ts +0 -5
- package/src/di/node_modules/.vitest/results.json +0 -1
- package/src/di/proxy-builder.test.ts +0 -45
- package/src/di/proxy-builder.ts +0 -38
- package/src/di/service-collection.test.ts +0 -27
- package/src/di/service-collection.ts +0 -46
- package/src/di/service-ownership-collection.test.ts +0 -39
- package/src/di/service-ownership-collection.ts +0 -38
- package/src/di/service-registry.test.ts +0 -66
- package/src/di/service-registry.ts +0 -99
- package/src/di/trace.ts +0 -85
- package/src/dispose/disposable-store.test.ts +0 -57
- package/src/dispose/disposable-store.ts +0 -80
- package/src/dispose/disposable-t.test.ts +0 -123
- package/src/dispose/disposable-t.ts +0 -238
- package/src/dispose/disposable-utils.test.ts +0 -15
- package/src/dispose/disposable-utils.ts +0 -28
- package/src/dispose/dispose-base.ts +0 -9
- package/src/dispose/index.ts +0 -34
- package/src/dispose/logger.test.ts +0 -65
- package/src/dispose/logger.ts +0 -39
- package/src/dispose/timer.test.ts +0 -30
- package/src/dispose/timer.ts +0 -16
- package/src/dispose/tracker.test.ts +0 -51
- package/src/dispose/tracker.ts +0 -105
- package/src/error/error-base.ts +0 -45
- package/src/error/error-code.ts +0 -39
- package/src/error/error-const.test.ts +0 -30
- package/src/error/error-const.ts +0 -16
- package/src/error/error-or.test.ts +0 -44
- package/src/error/error-or.ts +0 -2
- package/src/error/error-t.test.ts +0 -116
- package/src/error/error-t.ts +0 -100
- package/src/error/index.ts +0 -24
- package/src/error/node_modules/.vitest/results.json +0 -1
- package/src/event/disposable-linked-list.ts +0 -29
- package/src/event/emitter.test.ts +0 -191
- package/src/event/emitter.ts +0 -162
- package/src/event/error-handler.ts +0 -22
- package/src/event/index.ts +0 -34
- package/src/event/once.ts +0 -29
- package/src/event/phase-emitter.test.ts +0 -212
- package/src/event/phase-emitter.ts +0 -209
- package/src/event/shortcut-event-utils.ts +0 -33
- package/src/event/utils.ts +0 -6
- package/src/event/when.ts +0 -40
- package/src/function/debounce.test.ts +0 -274
- package/src/function/debounce.ts +0 -168
- package/src/function/index.ts +0 -2
- package/src/function/node_modules/.vitest/results.json +0 -1
- package/src/function/throttle.test.ts +0 -179
- package/src/function/throttle.ts +0 -26
- package/src/hash/hash-t.test.ts +0 -100
- package/src/hash/hash-t.ts +0 -51
- package/src/hash/index.ts +0 -3
- package/src/json/index.ts +0 -1
- package/src/json/node_modules/.vitest/results.json +0 -1
- package/src/json/parse.ts +0 -19
- package/src/launch/abstract-job.ts +0 -45
- package/src/launch/cost-recorder.ts +0 -22
- package/src/launch/index.ts +0 -2
- package/src/launch/job-scheduler.test.ts +0 -122
- package/src/launch/job-scheduler.ts +0 -118
- package/src/launch/node_modules/.vitest/deps/_metadata.json +0 -8
- package/src/launch/node_modules/.vitest/deps/package.json +0 -3
- package/src/launch/node_modules/.vitest/results.json +0 -1
- package/src/lock/README.md +0 -11
- package/src/lock/capability.test.ts +0 -110
- package/src/lock/capability.ts +0 -89
- package/src/lock/index.ts +0 -15
- package/src/lock/node_modules/.vitest/results.json +0 -1
- package/src/lock/semaphore.ts +0 -21
- package/src/lock/shared-mutex.test.ts +0 -537
- package/src/lock/shared-mutex.ts +0 -242
- package/src/lock/utils.test.ts +0 -165
- package/src/lock/utils.ts +0 -135
- package/src/lodash-es/index.ts +0 -1
- package/src/math/degree.ts +0 -16
- package/src/math/index.ts +0 -7
- package/src/math/math.test.ts +0 -40
- package/src/math/math.ts +0 -64
- package/src/math/node_modules/.vitest/results.json +0 -1
- package/src/math/vector.test.ts +0 -73
- package/src/math/vector.ts +0 -114
- package/src/network/client.interface.ts +0 -104
- package/src/network/client.web.ts +0 -24
- package/src/network/index.common.ts +0 -10
- package/src/network/index.ts +0 -2
- package/src/network/plugins/retry.ts +0 -98
- package/src/objects/deep-clone.test.ts +0 -40
- package/src/objects/deep-clone.ts +0 -13
- package/src/objects/deep-equal.test.ts +0 -86
- package/src/objects/deep-equal.ts +0 -60
- package/src/objects/index.ts +0 -4
- package/src/platform/index.ts +0 -64
- package/src/promise/index.ts +0 -16
- package/src/promise/promise.test.ts +0 -254
- package/src/promise/promise.ts +0 -212
- package/src/scheduler/callback-token.ts +0 -31
- package/src/scheduler/core/actuator-args.test.ts +0 -47
- package/src/scheduler/core/actuator.test.ts +0 -82
- package/src/scheduler/core/actuator.ts +0 -58
- package/src/scheduler/core/chunk-scheduler.test.ts +0 -54
- package/src/scheduler/core/chunk-scheduler.ts +0 -28
- package/src/scheduler/core/node_modules/.vitest/results.json +0 -1
- package/src/scheduler/core/scheduler.test.ts +0 -328
- package/src/scheduler/core/scheduler.ts +0 -172
- package/src/scheduler/core/task-queue.test.ts +0 -78
- package/src/scheduler/core/task-queue.ts +0 -44
- package/src/scheduler/core/task.test.ts +0 -34
- package/src/scheduler/core/task.ts +0 -52
- package/src/scheduler/core/utils.ts +0 -48
- package/src/scheduler/executor/abstract-executor.test.ts +0 -44
- package/src/scheduler/executor/abstract-executor.ts +0 -38
- package/src/scheduler/executor/executor.interface.ts +0 -39
- package/src/scheduler/executor/idle-callback-executor.test.ts +0 -70
- package/src/scheduler/executor/idle-callback-executor.ts +0 -98
- package/src/scheduler/executor/make-executor.ts +0 -18
- package/src/scheduler/executor/post-message-executor.test.ts +0 -66
- package/src/scheduler/executor/post-message-executor.ts +0 -52
- package/src/scheduler/index.ts +0 -15
- package/src/scheduler/lv-scheduler-callback.ts +0 -19
- package/src/scheduler/lv-scheduler-config.ts +0 -17
- package/src/scheduler/type.ts +0 -48
- package/src/sprintf/index.ts +0 -2
- package/src/sprintf/sprintf.test.ts +0 -95
- package/src/sprintf/sprintf.ts +0 -97
- package/src/structure/graph.test.ts +0 -181
- package/src/structure/graph.ts +0 -105
- package/src/structure/index.ts +0 -8
- package/src/structure/linked-list.test.ts +0 -74
- package/src/structure/linked-list.ts +0 -145
- package/src/structure/min-heap.test.ts +0 -71
- package/src/structure/min-heap.ts +0 -91
- package/src/type/REAME.md +0 -2
- package/src/type/distributive-omit.interface.ts +0 -4
- package/src/type/index.ts +0 -3
- package/src/type/object-key-paths.interface.ts +0 -40
- package/src/undo-redo-stack/README.md +0 -61
- package/src/undo-redo-stack/action-stack.test.ts +0 -330
- package/src/undo-redo-stack/action-stack.ts +0 -150
- package/src/undo-redo-stack/element.ts +0 -4
- package/src/undo-redo-stack/index.ts +0 -7
- package/src/undo-redo-stack/state-stack.test.ts +0 -118
- package/src/undo-redo-stack/state-stack.ts +0 -133
- package/src/uuid/index.ts +0 -7
- package/src/uuid/uuid.ts +0 -86
- package/src/worker/cors-worker.ts +0 -38
- package/src/worker/index.ts +0 -4
- package/src/worker/node_modules/.vitest/results.json +0 -1
- package/src/worker/promise-worker-main-thread.test.ts +0 -91
- package/src/worker/promise-worker-main-thread.ts +0 -76
- package/src/worker/promise-worker-worker-thread.ts +0 -64
- package/src/worker/promise-worker.interface.ts +0 -15
package/src/lock/shared-mutex.ts
DELETED
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
import { lvAssert, lvAssertNotNil } from '@/assert';
|
|
2
|
-
import { listenOnce } from '@/event';
|
|
3
|
-
import { SharedCapability, Capability, CapabilityStatus } from './capability';
|
|
4
|
-
import { Semaphore } from './semaphore';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 提供读写能力的共享互斥量
|
|
8
|
-
*
|
|
9
|
-
* 参考C++17标准库双门思想实现
|
|
10
|
-
* 接口也与标准库保持一致
|
|
11
|
-
* 方法内部禁止promise,只可以对外暴露promise
|
|
12
|
-
*
|
|
13
|
-
* 核心
|
|
14
|
-
* - 写写互斥,读写互斥,读读可重入
|
|
15
|
-
*
|
|
16
|
-
* 使用举例:
|
|
17
|
-
* class Foo {
|
|
18
|
-
* private _mutex = new SharedMutex();
|
|
19
|
-
*
|
|
20
|
-
* async add() {
|
|
21
|
-
* // 上写锁
|
|
22
|
-
* await this._mutex.lock();
|
|
23
|
-
* // ...write something
|
|
24
|
-
* this._mutex.unlock();
|
|
25
|
-
* }
|
|
26
|
-
*
|
|
27
|
-
* async getSomething1() {
|
|
28
|
-
* // 上读锁
|
|
29
|
-
* await this._mutex.lockShared();
|
|
30
|
-
* try {
|
|
31
|
-
* return xxx;
|
|
32
|
-
* } finally {
|
|
33
|
-
* this._mutex.unlockShared();
|
|
34
|
-
* }
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* async getSomething2() {
|
|
38
|
-
* // 上读锁
|
|
39
|
-
* await this._mutex.lockShared();
|
|
40
|
-
* try {
|
|
41
|
-
* return xxx;
|
|
42
|
-
* } finally {
|
|
43
|
-
* this._mutex.unlockShared();
|
|
44
|
-
* }
|
|
45
|
-
* }
|
|
46
|
-
* }
|
|
47
|
-
*/
|
|
48
|
-
export class SharedMutex {
|
|
49
|
-
// 在第一道门外等待的写者
|
|
50
|
-
private readonly _waitingWriters: Semaphore[] = [];
|
|
51
|
-
|
|
52
|
-
// 已经通过了第一道门的写者
|
|
53
|
-
// 如果在第二道门外等待,状态为sharedLocked
|
|
54
|
-
// 如果已经进入到第二道门内拿到了锁,状态为locked
|
|
55
|
-
private _writer?: Capability;
|
|
56
|
-
|
|
57
|
-
// 在第一道门外等待的读者
|
|
58
|
-
private _waitingReader?: Semaphore;
|
|
59
|
-
|
|
60
|
-
// 拿到锁的读者
|
|
61
|
-
private _reader?: SharedCapability;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 是否被锁住
|
|
65
|
-
*/
|
|
66
|
-
public isLocked() {
|
|
67
|
-
return this._writer || this._readerCount !== 0;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 等待并获取写锁
|
|
72
|
-
*/
|
|
73
|
-
public lock(): Promise<void> {
|
|
74
|
-
return new Promise<void>((resolve) => {
|
|
75
|
-
// 第一道门
|
|
76
|
-
if (this._writer) {
|
|
77
|
-
// 如果已经有写者进入了,其他写者等待
|
|
78
|
-
const token = new Semaphore();
|
|
79
|
-
this._waitingWriters.push(token);
|
|
80
|
-
token.onActive(() => {
|
|
81
|
-
this._writerEnterGate1(resolve);
|
|
82
|
-
});
|
|
83
|
-
} else {
|
|
84
|
-
this._writerEnterGate1(resolve);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* 尝试获取写锁,立刻返回结果
|
|
91
|
-
*/
|
|
92
|
-
public tryLock(): boolean {
|
|
93
|
-
if (this._writer || this._readerCount > 0) {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
// 这里不需要await,一定可以上锁
|
|
97
|
-
this.lock();
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* 解除写锁
|
|
103
|
-
*/
|
|
104
|
-
public unLock(): void {
|
|
105
|
-
lvAssertNotNil(this._writer);
|
|
106
|
-
|
|
107
|
-
// 打开第一道门
|
|
108
|
-
this._writer.release();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* 等待并获取读锁
|
|
113
|
-
*/
|
|
114
|
-
public lockShared(): Promise<void> {
|
|
115
|
-
return new Promise<void>((resolve) => {
|
|
116
|
-
// 读者只需要进第一道门
|
|
117
|
-
if (this._writer) {
|
|
118
|
-
// 如果有写者已经进入了第一道门,读者等待
|
|
119
|
-
if (!this._waitingReader) {
|
|
120
|
-
this._waitingReader = new Semaphore();
|
|
121
|
-
}
|
|
122
|
-
this._waitingReader.onActive(() => {
|
|
123
|
-
this._readerEnterGate1(resolve);
|
|
124
|
-
});
|
|
125
|
-
} else {
|
|
126
|
-
this._readerEnterGate1(resolve);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* 尝试获取读锁,立刻返回结果
|
|
133
|
-
*/
|
|
134
|
-
public tryLockShared(): boolean {
|
|
135
|
-
if (this._writer) {
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
// 不需要await,一定可以上锁
|
|
139
|
-
this.lockShared();
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* 解除读锁
|
|
145
|
-
*/
|
|
146
|
-
public unLockShared(): void {
|
|
147
|
-
lvAssertNotNil(this._reader);
|
|
148
|
-
if (this._writer) {
|
|
149
|
-
// TODO(niurouwan): 暂时保留,方便验证,稳定后可以去掉
|
|
150
|
-
lvAssert(this._writer.status === CapabilityStatus.Unlocked);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
this._reader.release();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* 获取当前读者数量
|
|
158
|
-
*/
|
|
159
|
-
private get _readerCount(): number {
|
|
160
|
-
return this._reader ? this._reader.counter : 0;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* 写者进入第一道门
|
|
165
|
-
*/
|
|
166
|
-
private _writerEnterGate1(resolve: () => void): void {
|
|
167
|
-
lvAssert(!this._writer);
|
|
168
|
-
// 确定写者,关第一道门
|
|
169
|
-
this._writer = new Capability();
|
|
170
|
-
|
|
171
|
-
// 第二道门
|
|
172
|
-
// 等待所有读者出去
|
|
173
|
-
if (this._readerCount > 0) {
|
|
174
|
-
listenOnce(this._reader!.onUnlocked)(() => {
|
|
175
|
-
this._writerEnterGate2(resolve);
|
|
176
|
-
});
|
|
177
|
-
} else {
|
|
178
|
-
this._writerEnterGate2(resolve);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* 写者进入第二道门
|
|
184
|
-
*/
|
|
185
|
-
private _writerEnterGate2(resolve: () => void): void {
|
|
186
|
-
lvAssertNotNil(this._writer);
|
|
187
|
-
lvAssert(this._readerCount === 0);
|
|
188
|
-
|
|
189
|
-
// 成功加锁
|
|
190
|
-
this._writer.acquire();
|
|
191
|
-
listenOnce(this._writer.onUnlocked)(() => {
|
|
192
|
-
lvAssertNotNil(this._writer);
|
|
193
|
-
// 不再持有
|
|
194
|
-
this._writer = undefined;
|
|
195
|
-
this._moveForward();
|
|
196
|
-
});
|
|
197
|
-
resolve();
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* 读者进入第一道门
|
|
202
|
-
*/
|
|
203
|
-
private _readerEnterGate1(resolve: () => void): void {
|
|
204
|
-
lvAssert(!this._writer);
|
|
205
|
-
|
|
206
|
-
// 门外等待的读者清除
|
|
207
|
-
this._waitingReader = undefined;
|
|
208
|
-
|
|
209
|
-
if (!this._reader) {
|
|
210
|
-
this._reader = new SharedCapability();
|
|
211
|
-
this._reader.acquire();
|
|
212
|
-
listenOnce(this._reader.onUnlocked)(() => {
|
|
213
|
-
this._moveForward();
|
|
214
|
-
});
|
|
215
|
-
} else {
|
|
216
|
-
this._reader.acquire();
|
|
217
|
-
}
|
|
218
|
-
resolve();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* 锁释放时推进流程
|
|
223
|
-
*/
|
|
224
|
-
private _moveForward(): void {
|
|
225
|
-
// 如果有写者在等待在第二道门前面,那么此时推进的一定是读锁释放,直接return即可
|
|
226
|
-
if (this._writer) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// 写者优先,优先通知在第一道门前面的写者
|
|
231
|
-
if (this._waitingWriters.length > 0) {
|
|
232
|
-
const semaphore = this._waitingWriters.shift()!;
|
|
233
|
-
semaphore.notify();
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// 最后通知第一道门前面的读者
|
|
238
|
-
if (this._waitingReader) {
|
|
239
|
-
this._waitingReader.notify();
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
package/src/lock/utils.test.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { SharedMutex } from './shared-mutex';
|
|
2
|
-
import { transferSharedLock, transferLock, tryTransferLock } from './utils';
|
|
3
|
-
|
|
4
|
-
function isMutexReleased(mutex: SharedMutex) {
|
|
5
|
-
return !mutex.isLocked();
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
describe('transferLock', () => {
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
vi.useFakeTimers();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// 正常上锁并且解锁
|
|
14
|
-
it('lock and unlock', async () => {
|
|
15
|
-
const mutex = new SharedMutex();
|
|
16
|
-
const unlockable = await transferLock(mutex);
|
|
17
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
18
|
-
unlockable.unlock();
|
|
19
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
// 上锁,超时导致释放锁
|
|
23
|
-
it('lock and timeout', async () => {
|
|
24
|
-
const mutex = new SharedMutex();
|
|
25
|
-
await transferLock(mutex, 10);
|
|
26
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
27
|
-
vi.advanceTimersByTime(15);
|
|
28
|
-
await Promise.resolve();
|
|
29
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// 超时后,重复解锁,不报错
|
|
33
|
-
it('timeout then unlock', async () => {
|
|
34
|
-
const mutex = new SharedMutex();
|
|
35
|
-
const unlockable = await transferLock(mutex, 10);
|
|
36
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
37
|
-
vi.advanceTimersByTime(15);
|
|
38
|
-
await Promise.resolve();
|
|
39
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
40
|
-
expect(() => {
|
|
41
|
-
unlockable.unlock();
|
|
42
|
-
unlockable.dispose();
|
|
43
|
-
}).not.toThrowError();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// 上锁,超时导致释放锁,锁转移
|
|
47
|
-
it('repeatedly lock', async () => {
|
|
48
|
-
const mutex = new SharedMutex();
|
|
49
|
-
await transferLock(mutex, 10);
|
|
50
|
-
transferLock(mutex).then(() => {
|
|
51
|
-
// ...
|
|
52
|
-
});
|
|
53
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
54
|
-
vi.advanceTimersByTime(15);
|
|
55
|
-
await Promise.resolve();
|
|
56
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe('tryTransferLock', () => {
|
|
61
|
-
beforeEach(() => {
|
|
62
|
-
vi.useFakeTimers();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// 正常上锁并且解锁
|
|
66
|
-
it('lock and unlock', () => {
|
|
67
|
-
const mutex = new SharedMutex();
|
|
68
|
-
const unlockable = tryTransferLock(mutex);
|
|
69
|
-
expect(unlockable).not.toBeUndefined();
|
|
70
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
71
|
-
unlockable!.unlock();
|
|
72
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// 上锁,超时导致释放锁
|
|
76
|
-
it('lock and timeout', async () => {
|
|
77
|
-
const mutex = new SharedMutex();
|
|
78
|
-
expect(tryTransferLock(mutex, 10)).not.toBeUndefined();
|
|
79
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
80
|
-
vi.advanceTimersByTime(15);
|
|
81
|
-
await Promise.resolve();
|
|
82
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// 超时后,重复解锁,不报错
|
|
86
|
-
it('timeout then unlock', async () => {
|
|
87
|
-
const mutex = new SharedMutex();
|
|
88
|
-
const unlockable = tryTransferLock(mutex, 10);
|
|
89
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
90
|
-
vi.advanceTimersByTime(15);
|
|
91
|
-
await Promise.resolve();
|
|
92
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
93
|
-
expect(() => {
|
|
94
|
-
unlockable!.unlock();
|
|
95
|
-
unlockable!.dispose();
|
|
96
|
-
}).not.toThrowError();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// 上锁,超时导致释放锁,锁转移
|
|
100
|
-
it('repeatedly lock', async () => {
|
|
101
|
-
const mutex = new SharedMutex();
|
|
102
|
-
await transferLock(mutex, 10);
|
|
103
|
-
expect(tryTransferLock(mutex)).toBeUndefined();
|
|
104
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
105
|
-
vi.advanceTimersByTime(15);
|
|
106
|
-
await Promise.resolve();
|
|
107
|
-
expect(tryTransferLock(mutex)).not.toBeUndefined();
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
describe('transferSharedLock', () => {
|
|
112
|
-
beforeEach(() => {
|
|
113
|
-
vi.useFakeTimers();
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// 正常上锁并且解锁
|
|
117
|
-
it('lock and unlock', async () => {
|
|
118
|
-
const mutex = new SharedMutex();
|
|
119
|
-
const unlockable = await transferSharedLock(mutex);
|
|
120
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
121
|
-
unlockable.unlock();
|
|
122
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// 上锁,超时导致释放锁
|
|
126
|
-
it('lock and timeout', async () => {
|
|
127
|
-
const mutex = new SharedMutex();
|
|
128
|
-
await transferSharedLock(mutex, 10);
|
|
129
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
130
|
-
vi.advanceTimersByTime(15);
|
|
131
|
-
await Promise.resolve();
|
|
132
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// 超时后,重复解锁,不报错
|
|
136
|
-
it('timeout then unlock', async () => {
|
|
137
|
-
const mutex = new SharedMutex();
|
|
138
|
-
const unlockable = await transferSharedLock(mutex, 10);
|
|
139
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
140
|
-
vi.advanceTimersByTime(15);
|
|
141
|
-
await Promise.resolve();
|
|
142
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
143
|
-
expect(() => {
|
|
144
|
-
unlockable.unlock();
|
|
145
|
-
unlockable.dispose();
|
|
146
|
-
}).not.toThrowError();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// 上锁,超时导致释放锁,锁转移
|
|
150
|
-
it('repeatedly lock', async () => {
|
|
151
|
-
const mutex = new SharedMutex();
|
|
152
|
-
await transferSharedLock(mutex, 10);
|
|
153
|
-
transferSharedLock(mutex, 20).then(() => {
|
|
154
|
-
// ...
|
|
155
|
-
});
|
|
156
|
-
await Promise.resolve();
|
|
157
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
158
|
-
vi.advanceTimersByTime(15);
|
|
159
|
-
await Promise.resolve();
|
|
160
|
-
expect(isMutexReleased(mutex)).toBeFalsy();
|
|
161
|
-
vi.advanceTimersByTime(15);
|
|
162
|
-
await Promise.resolve();
|
|
163
|
-
expect(isMutexReleased(mutex)).toBeTruthy();
|
|
164
|
-
});
|
|
165
|
-
});
|
package/src/lock/utils.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import type { IDisposable } from '@/dispose';
|
|
2
|
-
import { setDisposableTimeout } from '@/dispose';
|
|
3
|
-
import type { SharedMutex } from './shared-mutex';
|
|
4
|
-
|
|
5
|
-
export interface IUnlockable extends IDisposable {
|
|
6
|
-
unlock: () => void;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 转移独占锁
|
|
11
|
-
*/
|
|
12
|
-
export async function transferLock(mutex: SharedMutex, timeout?: number): Promise<IUnlockable> {
|
|
13
|
-
await mutex.lock();
|
|
14
|
-
let didUnlock = false;
|
|
15
|
-
let timerDisposable: IDisposable | undefined;
|
|
16
|
-
|
|
17
|
-
if (timeout !== undefined) {
|
|
18
|
-
timerDisposable = setDisposableTimeout(() => {
|
|
19
|
-
if (!didUnlock) {
|
|
20
|
-
mutex.unLock();
|
|
21
|
-
didUnlock = true;
|
|
22
|
-
}
|
|
23
|
-
}, timeout);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const unlock = () => {
|
|
27
|
-
timerDisposable?.dispose();
|
|
28
|
-
if (!didUnlock) {
|
|
29
|
-
mutex.unLock();
|
|
30
|
-
didUnlock = true;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
dispose: unlock,
|
|
36
|
-
unlock,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 尝试转移独占锁
|
|
42
|
-
*/
|
|
43
|
-
export function tryTransferLock(mutex: SharedMutex, timeout?: number): IUnlockable | undefined {
|
|
44
|
-
if (!mutex.tryLock()) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
let didUnlock = false;
|
|
48
|
-
let timerDisposable: IDisposable | undefined;
|
|
49
|
-
|
|
50
|
-
if (timeout !== undefined) {
|
|
51
|
-
timerDisposable = setDisposableTimeout(() => {
|
|
52
|
-
if (!didUnlock) {
|
|
53
|
-
mutex.unLock();
|
|
54
|
-
didUnlock = true;
|
|
55
|
-
}
|
|
56
|
-
}, timeout);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const unlock = () => {
|
|
60
|
-
timerDisposable?.dispose();
|
|
61
|
-
if (!didUnlock) {
|
|
62
|
-
mutex.unLock();
|
|
63
|
-
didUnlock = true;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
dispose: unlock,
|
|
69
|
-
unlock,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* 转移共享锁
|
|
75
|
-
*/
|
|
76
|
-
export async function transferSharedLock(mutex: SharedMutex, timeout?: number): Promise<IUnlockable> {
|
|
77
|
-
await mutex.lockShared();
|
|
78
|
-
let didUnlock = false;
|
|
79
|
-
let timerDisposable: IDisposable | undefined;
|
|
80
|
-
|
|
81
|
-
if (timeout !== undefined) {
|
|
82
|
-
timerDisposable = setDisposableTimeout(() => {
|
|
83
|
-
if (!didUnlock) {
|
|
84
|
-
mutex.unLockShared();
|
|
85
|
-
didUnlock = true;
|
|
86
|
-
}
|
|
87
|
-
}, timeout);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const unlock = () => {
|
|
91
|
-
timerDisposable?.dispose();
|
|
92
|
-
if (!didUnlock) {
|
|
93
|
-
mutex.unLockShared();
|
|
94
|
-
didUnlock = true;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
dispose: unlock,
|
|
100
|
-
unlock,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* 尝试转移共享锁
|
|
106
|
-
*/
|
|
107
|
-
export function tryTransferSharedLock(mutex: SharedMutex, timeout?: number): IUnlockable | undefined {
|
|
108
|
-
if (!mutex.tryLockShared()) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
let didUnlock = false;
|
|
112
|
-
let timerDisposable: IDisposable | undefined;
|
|
113
|
-
|
|
114
|
-
if (timeout !== undefined) {
|
|
115
|
-
timerDisposable = setDisposableTimeout(() => {
|
|
116
|
-
if (!didUnlock) {
|
|
117
|
-
mutex.unLockShared();
|
|
118
|
-
didUnlock = true;
|
|
119
|
-
}
|
|
120
|
-
}, timeout);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const unlock = () => {
|
|
124
|
-
timerDisposable?.dispose();
|
|
125
|
-
if (!didUnlock) {
|
|
126
|
-
mutex.unLockShared();
|
|
127
|
-
didUnlock = true;
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
dispose: unlock,
|
|
133
|
-
unlock,
|
|
134
|
-
};
|
|
135
|
-
}
|
package/src/lodash-es/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from 'lodash-es';
|
package/src/math/degree.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const DEG2RAD = Math.PI / 180;
|
|
2
|
-
const RAD2DEG = 180 / Math.PI;
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 弧度转角度
|
|
6
|
-
*/
|
|
7
|
-
export function radToDeg(radians: number): number {
|
|
8
|
-
return radians * RAD2DEG;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 角度转弧度
|
|
13
|
-
*/
|
|
14
|
-
export function degToRad(degree: number): number {
|
|
15
|
-
return degree * DEG2RAD;
|
|
16
|
-
}
|
package/src/math/index.ts
DELETED
package/src/math/math.test.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { toFixedDecimal } from './math';
|
|
2
|
-
|
|
3
|
-
describe('Math', () => {
|
|
4
|
-
it('toFixedDecimal', () => {
|
|
5
|
-
expect(toFixedDecimal(0.6 * 3, 1)).toEqual(1.8);
|
|
6
|
-
|
|
7
|
-
// 整数没问题
|
|
8
|
-
expect(toFixedDecimal(1 * 3, 1)).toEqual(3);
|
|
9
|
-
|
|
10
|
-
// 负数没问题
|
|
11
|
-
expect(toFixedDecimal(-0.6 * 3, 1)).toEqual(-1.8);
|
|
12
|
-
|
|
13
|
-
expect(toFixedDecimal(1.44, 1)).toEqual(1.4);
|
|
14
|
-
expect(toFixedDecimal(1.45, 1)).toEqual(1.5);
|
|
15
|
-
|
|
16
|
-
// js直接计算2.333 * 9.452结果为22.051516000000003
|
|
17
|
-
expect(toFixedDecimal(2.333 * 9.452, 3)).toEqual(22.052);
|
|
18
|
-
|
|
19
|
-
// 外部用例
|
|
20
|
-
const arr = [
|
|
21
|
-
0.01, 0.0149, 0.015, 0.016, 0.017, 0.019, 0.026, 0.029, 0.02111, 0.078, 0.0711, 0.0701, 0.1, 0.11,
|
|
22
|
-
0.145, 0.149, 0.15, 0.151, 0.155, 0.159, 1.001, 1.004, 1.005, 1.006, 1.009, 1.105, 1.104, 1.109, 1.6,
|
|
23
|
-
1.0, 1.423, 1.531, 1.555, 1.504, 1.506, 1.669, 1.998, 998, 996, 910, 1, 12, 33, 151, 99999, 333.01232,
|
|
24
|
-
333.09139, 333.93153, 148.898342, 231.09002, 231.000002329, 21.98, 67.473, 33.234, 12.982, 12.238,
|
|
25
|
-
896.023, 99999.99999,
|
|
26
|
-
];
|
|
27
|
-
const res = [
|
|
28
|
-
0.01, 0.01, 0.02, 0.02, 0.02, 0.02, 0.03, 0.03, 0.02, 0.08, 0.07, 0.07, 0.1, 0.11, 0.15, 0.15, 0.15,
|
|
29
|
-
0.15, 0.16, 0.16, 1, 1, 1.01, 1.01, 1.01, 1.11, 1.1, 1.11, 1.6, 1, 1.42, 1.53, 1.56, 1.5, 1.51, 1.67, 2,
|
|
30
|
-
998, 996, 910, 1, 12, 33, 151, 99999, 333.01, 333.09, 333.93, 148.9, 231.09, 231, 21.98, 67.47, 33.23,
|
|
31
|
-
12.98, 12.24, 896.02, 100000,
|
|
32
|
-
];
|
|
33
|
-
for (let i = 0; i < arr.length; i++) {
|
|
34
|
-
expect(toFixedDecimal(arr[i], 2)).toEqual(res[i]);
|
|
35
|
-
}
|
|
36
|
-
for (let i = 0; i < arr.length; i++) {
|
|
37
|
-
expect(toFixedDecimal(-1 * arr[i], 2)).toEqual(-1 * res[i]);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
});
|
package/src/math/math.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 安全的toFixed,不会出现小数精度的特殊情况
|
|
3
|
-
*/
|
|
4
|
-
function safeToFixed(value: string, precision = 0) {
|
|
5
|
-
let formattedValue = value;
|
|
6
|
-
if (!precision) {
|
|
7
|
-
precision = 0;
|
|
8
|
-
}
|
|
9
|
-
if (formattedValue.indexOf('.') === -1) {
|
|
10
|
-
formattedValue += '.';
|
|
11
|
-
}
|
|
12
|
-
formattedValue += '0'.repeat(precision + 1);
|
|
13
|
-
|
|
14
|
-
const regex = new RegExp(`^(-|\\+)?(\\d+(\\.\\d{0,${precision + 1}})?)\\d*$`);
|
|
15
|
-
if (!regex.test(formattedValue)) {
|
|
16
|
-
return value;
|
|
17
|
-
}
|
|
18
|
-
const match = regex.exec(formattedValue)!;
|
|
19
|
-
let integerPart = `0${match[2]}`;
|
|
20
|
-
const pm = match[1] ?? '';
|
|
21
|
-
const decimalPartLength = match[3].length;
|
|
22
|
-
let shouldRoundUp = true;
|
|
23
|
-
|
|
24
|
-
if (decimalPartLength === precision + 2) {
|
|
25
|
-
const decimalArray = integerPart.match(/\d/g)!;
|
|
26
|
-
|
|
27
|
-
if (parseInt(decimalArray[decimalArray.length - 1], 10) > 4) {
|
|
28
|
-
for (let i = decimalArray.length - 2; i >= 0; i--) {
|
|
29
|
-
const temp = parseInt(decimalArray[i], 10) + 1;
|
|
30
|
-
|
|
31
|
-
// eslint-disable-next-line max-depth
|
|
32
|
-
if (temp === 10) {
|
|
33
|
-
decimalArray[i] = '0';
|
|
34
|
-
shouldRoundUp = i !== 1;
|
|
35
|
-
} else {
|
|
36
|
-
decimalArray[i] = String(temp);
|
|
37
|
-
break;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
integerPart = decimalArray.join('').replace(new RegExp(`(\\d+)(\\d{${precision}})\\d$`), '$1.$2');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (shouldRoundUp) {
|
|
45
|
-
integerPart = integerPart.substring(1);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return (pm + integerPart).replace(/\.$/, '');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 将某个double转为指定精度小数位
|
|
53
|
-
*
|
|
54
|
-
* 注意:
|
|
55
|
-
* 0.6 * 3 = 1.7999999999999998
|
|
56
|
-
* toFixedDecimal(0.6 * 3, 1) = 1.8
|
|
57
|
-
* 没有使用系统默认的toFixed(),会有精度问题
|
|
58
|
-
*
|
|
59
|
-
* @param value 原始double类型值
|
|
60
|
-
* @param precision 期望小数的精度
|
|
61
|
-
*/
|
|
62
|
-
export function toFixedDecimal(value: number, precision: number): number {
|
|
63
|
-
return Number(safeToFixed(String(value), precision));
|
|
64
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"1.0.1","results":[[":math.test.ts",{"duration":4,"failed":false}],[":vector.test.ts",{"duration":0,"failed":false}]]}
|