@zk-tech/bedrock 0.0.1

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.
Files changed (390) hide show
  1. package/README.md +24 -0
  2. package/dist/array/index.cjs +22 -0
  3. package/dist/array/index.cjs.map +1 -0
  4. package/dist/array/index.d.cts +13 -0
  5. package/dist/array/index.d.ts +13 -0
  6. package/dist/array/index.js +19 -0
  7. package/dist/array/index.js.map +1 -0
  8. package/dist/assert/index.cjs +29 -0
  9. package/dist/assert/index.cjs.map +1 -0
  10. package/dist/assert/index.d.cts +25 -0
  11. package/dist/assert/index.d.ts +25 -0
  12. package/dist/assert/index.js +24 -0
  13. package/dist/assert/index.js.map +1 -0
  14. package/dist/async/index.cjs +746 -0
  15. package/dist/async/index.cjs.map +1 -0
  16. package/dist/async/index.d.cts +47 -0
  17. package/dist/async/index.d.ts +47 -0
  18. package/dist/async/index.js +738 -0
  19. package/dist/async/index.js.map +1 -0
  20. package/dist/barrier-316Xonfd.d.cts +18 -0
  21. package/dist/barrier-316Xonfd.d.ts +18 -0
  22. package/dist/byte/index.cjs +59 -0
  23. package/dist/byte/index.cjs.map +1 -0
  24. package/dist/byte/index.d.cts +12 -0
  25. package/dist/byte/index.d.ts +12 -0
  26. package/dist/byte/index.js +49 -0
  27. package/dist/byte/index.js.map +1 -0
  28. package/dist/cache/index.cjs +418 -0
  29. package/dist/cache/index.cjs.map +1 -0
  30. package/dist/cache/index.d.cts +40 -0
  31. package/dist/cache/index.d.ts +40 -0
  32. package/dist/cache/index.js +415 -0
  33. package/dist/cache/index.js.map +1 -0
  34. package/dist/cancellation-BIIv2UJm.d.cts +25 -0
  35. package/dist/cancellation-ClqPPsV1.d.ts +25 -0
  36. package/dist/context/index.cjs +59 -0
  37. package/dist/context/index.cjs.map +1 -0
  38. package/dist/context/index.d.cts +33 -0
  39. package/dist/context/index.d.ts +33 -0
  40. package/dist/context/index.js +51 -0
  41. package/dist/context/index.js.map +1 -0
  42. package/dist/di/index.cjs +1965 -0
  43. package/dist/di/index.cjs.map +1 -0
  44. package/dist/di/index.d.cts +140 -0
  45. package/dist/di/index.d.ts +140 -0
  46. package/dist/di/index.js +1949 -0
  47. package/dist/di/index.js.map +1 -0
  48. package/dist/disposable-t-B15Nu57y.d.ts +93 -0
  49. package/dist/disposable-t-CVsiyHPL.d.cts +93 -0
  50. package/dist/dispose/index.cjs +356 -0
  51. package/dist/dispose/index.cjs.map +1 -0
  52. package/dist/dispose/index.d.cts +26 -0
  53. package/dist/dispose/index.d.ts +26 -0
  54. package/dist/dispose/index.js +340 -0
  55. package/dist/dispose/index.js.map +1 -0
  56. package/dist/dispose-base-CAeXDpjg.d.cts +6 -0
  57. package/dist/dispose-base-CAeXDpjg.d.ts +6 -0
  58. package/dist/emitter-CAfCtSTg.d.cts +35 -0
  59. package/dist/emitter-DeM5mlEm.d.ts +35 -0
  60. package/dist/error/index.cjs +145 -0
  61. package/dist/error/index.cjs.map +1 -0
  62. package/dist/error/index.d.cts +45 -0
  63. package/dist/error/index.d.ts +45 -0
  64. package/dist/error/index.js +126 -0
  65. package/dist/error/index.js.map +1 -0
  66. package/dist/error-base-B4zaiJ5m.d.cts +32 -0
  67. package/dist/error-base-B4zaiJ5m.d.ts +32 -0
  68. package/dist/event/index.cjs +550 -0
  69. package/dist/event/index.cjs.map +1 -0
  70. package/dist/event/index.d.cts +139 -0
  71. package/dist/event/index.d.ts +139 -0
  72. package/dist/event/index.js +538 -0
  73. package/dist/event/index.js.map +1 -0
  74. package/dist/function/index.cjs +132 -0
  75. package/dist/function/index.cjs.map +1 -0
  76. package/dist/function/index.d.cts +26 -0
  77. package/dist/function/index.d.ts +26 -0
  78. package/dist/function/index.js +129 -0
  79. package/dist/function/index.js.map +1 -0
  80. package/dist/graph-BGbNOniY.d.cts +23 -0
  81. package/dist/graph-BGbNOniY.d.ts +23 -0
  82. package/dist/hash/index.cjs +54 -0
  83. package/dist/hash/index.cjs.map +1 -0
  84. package/dist/hash/index.d.cts +5 -0
  85. package/dist/hash/index.d.ts +5 -0
  86. package/dist/hash/index.js +50 -0
  87. package/dist/hash/index.js.map +1 -0
  88. package/dist/instantiation-service.interface-CVFMBUUD.d.cts +78 -0
  89. package/dist/instantiation-service.interface-CVFMBUUD.d.ts +78 -0
  90. package/dist/json/index.cjs +28 -0
  91. package/dist/json/index.cjs.map +1 -0
  92. package/dist/json/index.d.cts +8 -0
  93. package/dist/json/index.d.ts +8 -0
  94. package/dist/json/index.js +26 -0
  95. package/dist/json/index.js.map +1 -0
  96. package/dist/launch/index.cjs +213 -0
  97. package/dist/launch/index.cjs.map +1 -0
  98. package/dist/launch/index.d.cts +46 -0
  99. package/dist/launch/index.d.ts +46 -0
  100. package/dist/launch/index.js +211 -0
  101. package/dist/launch/index.js.map +1 -0
  102. package/dist/linked-list-CUkue5DZ.d.cts +24 -0
  103. package/dist/linked-list-CUkue5DZ.d.ts +24 -0
  104. package/dist/lock/index.cjs +662 -0
  105. package/dist/lock/index.cjs.map +1 -0
  106. package/dist/lock/index.d.cts +145 -0
  107. package/dist/lock/index.d.ts +145 -0
  108. package/dist/lock/index.js +656 -0
  109. package/dist/lock/index.js.map +1 -0
  110. package/dist/lodash-es/index.cjs +14 -0
  111. package/dist/lodash-es/index.cjs.map +1 -0
  112. package/dist/lodash-es/index.d.cts +1 -0
  113. package/dist/lodash-es/index.d.ts +1 -0
  114. package/dist/lodash-es/index.js +3 -0
  115. package/dist/lodash-es/index.js.map +1 -0
  116. package/dist/math/index.cjs +161 -0
  117. package/dist/math/index.cjs.map +1 -0
  118. package/dist/math/index.d.cts +76 -0
  119. package/dist/math/index.d.ts +76 -0
  120. package/dist/math/index.js +156 -0
  121. package/dist/math/index.js.map +1 -0
  122. package/dist/network/index.cjs +91 -0
  123. package/dist/network/index.cjs.map +1 -0
  124. package/dist/network/index.d.cts +62 -0
  125. package/dist/network/index.d.ts +62 -0
  126. package/dist/network/index.js +82 -0
  127. package/dist/network/index.js.map +1 -0
  128. package/dist/objects/index.cjs +80 -0
  129. package/dist/objects/index.cjs.map +1 -0
  130. package/dist/objects/index.d.cts +11 -0
  131. package/dist/objects/index.d.ts +11 -0
  132. package/dist/objects/index.js +77 -0
  133. package/dist/objects/index.js.map +1 -0
  134. package/dist/platform/index.cjs +62 -0
  135. package/dist/platform/index.cjs.map +1 -0
  136. package/dist/platform/index.d.cts +21 -0
  137. package/dist/platform/index.d.ts +21 -0
  138. package/dist/platform/index.js +48 -0
  139. package/dist/platform/index.js.map +1 -0
  140. package/dist/promise/index.cjs +639 -0
  141. package/dist/promise/index.cjs.map +1 -0
  142. package/dist/promise/index.d.cts +63 -0
  143. package/dist/promise/index.d.ts +63 -0
  144. package/dist/promise/index.js +633 -0
  145. package/dist/promise/index.js.map +1 -0
  146. package/dist/scheduler/index.cjs +599 -0
  147. package/dist/scheduler/index.cjs.map +1 -0
  148. package/dist/scheduler/index.d.cts +57 -0
  149. package/dist/scheduler/index.d.ts +57 -0
  150. package/dist/scheduler/index.js +594 -0
  151. package/dist/scheduler/index.js.map +1 -0
  152. package/dist/sprintf/index.cjs +101 -0
  153. package/dist/sprintf/index.cjs.map +1 -0
  154. package/dist/sprintf/index.d.cts +3 -0
  155. package/dist/sprintf/index.d.ts +3 -0
  156. package/dist/sprintf/index.js +99 -0
  157. package/dist/sprintf/index.js.map +1 -0
  158. package/dist/structure/index.cjs +300 -0
  159. package/dist/structure/index.cjs.map +1 -0
  160. package/dist/structure/index.d.cts +21 -0
  161. package/dist/structure/index.d.ts +21 -0
  162. package/dist/structure/index.js +296 -0
  163. package/dist/structure/index.js.map +1 -0
  164. package/dist/type/index.cjs +4 -0
  165. package/dist/type/index.cjs.map +1 -0
  166. package/dist/type/index.d.cts +20 -0
  167. package/dist/type/index.d.ts +20 -0
  168. package/dist/type/index.js +3 -0
  169. package/dist/type/index.js.map +1 -0
  170. package/dist/undo-redo-stack/index.cjs +545 -0
  171. package/dist/undo-redo-stack/index.cjs.map +1 -0
  172. package/dist/undo-redo-stack/index.d.cts +130 -0
  173. package/dist/undo-redo-stack/index.d.ts +130 -0
  174. package/dist/undo-redo-stack/index.js +542 -0
  175. package/dist/undo-redo-stack/index.js.map +1 -0
  176. package/dist/uuid/index.cjs +67 -0
  177. package/dist/uuid/index.cjs.map +1 -0
  178. package/dist/uuid/index.d.cts +17 -0
  179. package/dist/uuid/index.d.ts +17 -0
  180. package/dist/uuid/index.js +61 -0
  181. package/dist/uuid/index.js.map +1 -0
  182. package/dist/worker/index.cjs +271 -0
  183. package/dist/worker/index.cjs.map +1 -0
  184. package/dist/worker/index.d.cts +66 -0
  185. package/dist/worker/index.d.ts +66 -0
  186. package/dist/worker/index.js +267 -0
  187. package/dist/worker/index.js.map +1 -0
  188. package/package.json +285 -0
  189. package/src/_internal/logger.ts +59 -0
  190. package/src/array/array.test.ts +35 -0
  191. package/src/array/array.ts +25 -0
  192. package/src/array/index.ts +1 -0
  193. package/src/assert/assert.test.ts +86 -0
  194. package/src/assert/assert.ts +42 -0
  195. package/src/assert/index.ts +2 -0
  196. package/src/async/barrier.test.ts +90 -0
  197. package/src/async/barrier.ts +58 -0
  198. package/src/async/cancellation.test.ts +85 -0
  199. package/src/async/cancellation.ts +193 -0
  200. package/src/async/index.ts +18 -0
  201. package/src/async/queue/queue.test.ts +70 -0
  202. package/src/async/queue/queue.ts +56 -0
  203. package/src/async/queue/task.test.ts +155 -0
  204. package/src/async/queue/task.ts +67 -0
  205. package/src/async/utils.test.ts +28 -0
  206. package/src/async/utils.ts +8 -0
  207. package/src/async/wait.ts +9 -0
  208. package/src/byte/format.test.ts +64 -0
  209. package/src/byte/format.ts +44 -0
  210. package/src/byte/index.ts +2 -0
  211. package/src/byte/node_modules/.vitest/results.json +1 -0
  212. package/src/byte/var.ts +11 -0
  213. package/src/cache/index.ts +2 -0
  214. package/src/cache/lru-with-timeout.test.ts +88 -0
  215. package/src/cache/lru-with-timeout.ts +85 -0
  216. package/src/cache/lru.test.ts +56 -0
  217. package/src/cache/lru.ts +59 -0
  218. package/src/context/context.test.ts +17 -0
  219. package/src/context/context.ts +60 -0
  220. package/src/context/index.ts +8 -0
  221. package/src/di/base.ts +73 -0
  222. package/src/di/container-service.test.ts +179 -0
  223. package/src/di/context.web.tsx +41 -0
  224. package/src/di/descriptor.ts +31 -0
  225. package/src/di/idle-value.test.ts +73 -0
  226. package/src/di/idle-value.ts +63 -0
  227. package/src/di/index.common.ts +32 -0
  228. package/src/di/index.ts +2 -0
  229. package/src/di/instantiation-service.interface.ts +46 -0
  230. package/src/di/instantiation-service.test.ts +337 -0
  231. package/src/di/instantiation-service.ts +468 -0
  232. package/src/di/lazy/foo.mock.ts +28 -0
  233. package/src/di/lazy/idle-load.ts +39 -0
  234. package/src/di/lazy/index.ts +4 -0
  235. package/src/di/lazy/lazy-service.test.ts +65 -0
  236. package/src/di/lazy/lazy-service.ts +71 -0
  237. package/src/di/lazy/type.ts +5 -0
  238. package/src/di/node_modules/.vitest/results.json +1 -0
  239. package/src/di/proxy-builder.test.ts +45 -0
  240. package/src/di/proxy-builder.ts +38 -0
  241. package/src/di/service-collection.test.ts +27 -0
  242. package/src/di/service-collection.ts +46 -0
  243. package/src/di/service-ownership-collection.test.ts +39 -0
  244. package/src/di/service-ownership-collection.ts +38 -0
  245. package/src/di/service-registry.test.ts +66 -0
  246. package/src/di/service-registry.ts +99 -0
  247. package/src/di/trace.ts +85 -0
  248. package/src/dispose/disposable-store.test.ts +57 -0
  249. package/src/dispose/disposable-store.ts +80 -0
  250. package/src/dispose/disposable-t.test.ts +123 -0
  251. package/src/dispose/disposable-t.ts +238 -0
  252. package/src/dispose/disposable-utils.test.ts +15 -0
  253. package/src/dispose/disposable-utils.ts +28 -0
  254. package/src/dispose/dispose-base.ts +9 -0
  255. package/src/dispose/index.ts +34 -0
  256. package/src/dispose/logger.test.ts +65 -0
  257. package/src/dispose/logger.ts +39 -0
  258. package/src/dispose/timer.test.ts +30 -0
  259. package/src/dispose/timer.ts +16 -0
  260. package/src/dispose/tracker.test.ts +51 -0
  261. package/src/dispose/tracker.ts +105 -0
  262. package/src/error/error-base.ts +45 -0
  263. package/src/error/error-code.ts +39 -0
  264. package/src/error/error-const.test.ts +30 -0
  265. package/src/error/error-const.ts +16 -0
  266. package/src/error/error-or.test.ts +44 -0
  267. package/src/error/error-or.ts +2 -0
  268. package/src/error/error-t.test.ts +116 -0
  269. package/src/error/error-t.ts +100 -0
  270. package/src/error/index.ts +24 -0
  271. package/src/error/node_modules/.vitest/results.json +1 -0
  272. package/src/event/disposable-linked-list.ts +29 -0
  273. package/src/event/emitter.test.ts +191 -0
  274. package/src/event/emitter.ts +162 -0
  275. package/src/event/error-handler.ts +22 -0
  276. package/src/event/index.ts +34 -0
  277. package/src/event/once.ts +29 -0
  278. package/src/event/phase-emitter.test.ts +212 -0
  279. package/src/event/phase-emitter.ts +209 -0
  280. package/src/event/shortcut-event-utils.ts +33 -0
  281. package/src/event/utils.ts +6 -0
  282. package/src/event/when.ts +40 -0
  283. package/src/function/debounce.test.ts +274 -0
  284. package/src/function/debounce.ts +168 -0
  285. package/src/function/index.ts +2 -0
  286. package/src/function/node_modules/.vitest/results.json +1 -0
  287. package/src/function/throttle.test.ts +179 -0
  288. package/src/function/throttle.ts +26 -0
  289. package/src/hash/hash-t.test.ts +100 -0
  290. package/src/hash/hash-t.ts +51 -0
  291. package/src/hash/index.ts +3 -0
  292. package/src/json/index.ts +1 -0
  293. package/src/json/node_modules/.vitest/results.json +1 -0
  294. package/src/json/parse.ts +19 -0
  295. package/src/launch/abstract-job.ts +45 -0
  296. package/src/launch/cost-recorder.ts +22 -0
  297. package/src/launch/index.ts +2 -0
  298. package/src/launch/job-scheduler.test.ts +122 -0
  299. package/src/launch/job-scheduler.ts +118 -0
  300. package/src/launch/node_modules/.vitest/deps/_metadata.json +8 -0
  301. package/src/launch/node_modules/.vitest/deps/package.json +3 -0
  302. package/src/launch/node_modules/.vitest/results.json +1 -0
  303. package/src/lock/README.md +11 -0
  304. package/src/lock/capability.test.ts +110 -0
  305. package/src/lock/capability.ts +89 -0
  306. package/src/lock/index.ts +15 -0
  307. package/src/lock/node_modules/.vitest/results.json +1 -0
  308. package/src/lock/semaphore.ts +21 -0
  309. package/src/lock/shared-mutex.test.ts +537 -0
  310. package/src/lock/shared-mutex.ts +242 -0
  311. package/src/lock/utils.test.ts +165 -0
  312. package/src/lock/utils.ts +135 -0
  313. package/src/lodash-es/index.ts +1 -0
  314. package/src/math/degree.ts +16 -0
  315. package/src/math/index.ts +7 -0
  316. package/src/math/math.test.ts +40 -0
  317. package/src/math/math.ts +64 -0
  318. package/src/math/node_modules/.vitest/results.json +1 -0
  319. package/src/math/vector.test.ts +73 -0
  320. package/src/math/vector.ts +114 -0
  321. package/src/network/client.interface.ts +104 -0
  322. package/src/network/client.web.ts +24 -0
  323. package/src/network/index.common.ts +10 -0
  324. package/src/network/index.ts +2 -0
  325. package/src/network/plugins/retry.ts +98 -0
  326. package/src/objects/deep-clone.test.ts +40 -0
  327. package/src/objects/deep-clone.ts +13 -0
  328. package/src/objects/deep-equal.test.ts +86 -0
  329. package/src/objects/deep-equal.ts +60 -0
  330. package/src/objects/index.ts +4 -0
  331. package/src/platform/index.ts +64 -0
  332. package/src/promise/index.ts +16 -0
  333. package/src/promise/promise.test.ts +254 -0
  334. package/src/promise/promise.ts +212 -0
  335. package/src/scheduler/callback-token.ts +31 -0
  336. package/src/scheduler/core/actuator-args.test.ts +47 -0
  337. package/src/scheduler/core/actuator.test.ts +82 -0
  338. package/src/scheduler/core/actuator.ts +58 -0
  339. package/src/scheduler/core/chunk-scheduler.test.ts +54 -0
  340. package/src/scheduler/core/chunk-scheduler.ts +28 -0
  341. package/src/scheduler/core/node_modules/.vitest/results.json +1 -0
  342. package/src/scheduler/core/scheduler.test.ts +328 -0
  343. package/src/scheduler/core/scheduler.ts +172 -0
  344. package/src/scheduler/core/task-queue.test.ts +78 -0
  345. package/src/scheduler/core/task-queue.ts +44 -0
  346. package/src/scheduler/core/task.test.ts +34 -0
  347. package/src/scheduler/core/task.ts +52 -0
  348. package/src/scheduler/core/utils.ts +48 -0
  349. package/src/scheduler/executor/abstract-executor.test.ts +44 -0
  350. package/src/scheduler/executor/abstract-executor.ts +38 -0
  351. package/src/scheduler/executor/executor.interface.ts +39 -0
  352. package/src/scheduler/executor/idle-callback-executor.test.ts +70 -0
  353. package/src/scheduler/executor/idle-callback-executor.ts +98 -0
  354. package/src/scheduler/executor/make-executor.ts +18 -0
  355. package/src/scheduler/executor/post-message-executor.test.ts +66 -0
  356. package/src/scheduler/executor/post-message-executor.ts +52 -0
  357. package/src/scheduler/index.ts +15 -0
  358. package/src/scheduler/lv-scheduler-callback.ts +19 -0
  359. package/src/scheduler/lv-scheduler-config.ts +17 -0
  360. package/src/scheduler/type.ts +48 -0
  361. package/src/sprintf/index.ts +2 -0
  362. package/src/sprintf/sprintf.test.ts +95 -0
  363. package/src/sprintf/sprintf.ts +97 -0
  364. package/src/structure/graph.test.ts +181 -0
  365. package/src/structure/graph.ts +105 -0
  366. package/src/structure/index.ts +8 -0
  367. package/src/structure/linked-list.test.ts +74 -0
  368. package/src/structure/linked-list.ts +145 -0
  369. package/src/structure/min-heap.test.ts +71 -0
  370. package/src/structure/min-heap.ts +91 -0
  371. package/src/type/REAME.md +2 -0
  372. package/src/type/distributive-omit.interface.ts +4 -0
  373. package/src/type/index.ts +3 -0
  374. package/src/type/object-key-paths.interface.ts +40 -0
  375. package/src/undo-redo-stack/README.md +61 -0
  376. package/src/undo-redo-stack/action-stack.test.ts +330 -0
  377. package/src/undo-redo-stack/action-stack.ts +150 -0
  378. package/src/undo-redo-stack/element.ts +4 -0
  379. package/src/undo-redo-stack/index.ts +7 -0
  380. package/src/undo-redo-stack/state-stack.test.ts +118 -0
  381. package/src/undo-redo-stack/state-stack.ts +133 -0
  382. package/src/uuid/index.ts +7 -0
  383. package/src/uuid/uuid.ts +86 -0
  384. package/src/worker/cors-worker.ts +38 -0
  385. package/src/worker/index.ts +4 -0
  386. package/src/worker/node_modules/.vitest/results.json +1 -0
  387. package/src/worker/promise-worker-main-thread.test.ts +91 -0
  388. package/src/worker/promise-worker-main-thread.ts +76 -0
  389. package/src/worker/promise-worker-worker-thread.ts +64 -0
  390. package/src/worker/promise-worker.interface.ts +15 -0
@@ -0,0 +1,122 @@
1
+ import { JobScheduler } from './job-scheduler';
2
+ import { AbstractJob } from './abstract-job';
3
+ import { InstantiationService } from '@/di';
4
+
5
+ enum Lifecycle {
6
+ A,
7
+ B,
8
+ C,
9
+ }
10
+
11
+ class Job1 extends AbstractJob<Lifecycle> {
12
+ protected _name = 'job1';
13
+
14
+ constructor(private readonly _fn: () => void) {
15
+ super();
16
+ }
17
+
18
+ protected _executePhase(phase: Lifecycle) {
19
+ switch (phase) {
20
+ case Lifecycle.A:
21
+ case Lifecycle.B:
22
+ this._fn();
23
+ break;
24
+ default:
25
+ return;
26
+ }
27
+ }
28
+ }
29
+
30
+ class Job2 extends AbstractJob<Lifecycle> {
31
+ protected _name = 'job2';
32
+
33
+ constructor(private readonly _fn: () => void) {
34
+ super();
35
+ }
36
+
37
+ protected _executePhase(phase: Lifecycle) {
38
+ switch (phase) {
39
+ case Lifecycle.C:
40
+ this._fn();
41
+ break;
42
+ default:
43
+ return;
44
+ }
45
+ }
46
+ }
47
+
48
+ class Job3 extends AbstractJob<Lifecycle> {
49
+ protected _name = 'job3';
50
+
51
+ constructor(private readonly _fn: () => void) {
52
+ super();
53
+ this._fn();
54
+ }
55
+
56
+ protected _executePhase(phase: Lifecycle) {
57
+ // donothing
58
+ }
59
+ }
60
+
61
+ describe('jobscheduler', () => {
62
+ it('addJob', async () => {
63
+ const fn1 = vi.fn();
64
+ const fn2 = vi.fn();
65
+ const instantiationService = new InstantiationService();
66
+ const jobScheduler = instantiationService.createInstance(JobScheduler, Lifecycle.A);
67
+ jobScheduler.addJob(new Job1(fn1));
68
+ jobScheduler.addJob(new Job2(fn2));
69
+
70
+ jobScheduler.prepare(Lifecycle.A);
71
+ await jobScheduler.wait(Lifecycle.A);
72
+
73
+ jobScheduler.prepare(Lifecycle.B);
74
+ await jobScheduler.wait(Lifecycle.B);
75
+
76
+ jobScheduler.prepare(Lifecycle.C);
77
+ await jobScheduler.wait(Lifecycle.C);
78
+
79
+ expect(fn1).toBeCalledTimes(2);
80
+ expect(fn2).toBeCalledTimes(1);
81
+ });
82
+
83
+ it('registerJob', async () => {
84
+ const fn1 = vi.fn();
85
+ const fn2 = vi.fn();
86
+ const instantiationService = new InstantiationService();
87
+ const jobScheduler = instantiationService.createInstance(JobScheduler, Lifecycle.A);
88
+ jobScheduler.registerJob(Lifecycle.A, Job1, fn1);
89
+ jobScheduler.registerJob(Lifecycle.B, Job2, fn2);
90
+
91
+ jobScheduler.prepare(Lifecycle.A);
92
+ await jobScheduler.wait(Lifecycle.A);
93
+
94
+ jobScheduler.prepare(Lifecycle.B);
95
+ await jobScheduler.wait(Lifecycle.B);
96
+
97
+ jobScheduler.prepare(Lifecycle.C);
98
+ await jobScheduler.wait(Lifecycle.C);
99
+
100
+ expect(fn1).toBeCalledTimes(2);
101
+ expect(fn2).toBeCalledTimes(1);
102
+ });
103
+
104
+ it('delayConstructJob', async () => {
105
+ const fn = vi.fn();
106
+ const instantiationService = new InstantiationService();
107
+ const jobScheduler = instantiationService.createInstance(JobScheduler, Lifecycle.A);
108
+ jobScheduler.registerJob(Lifecycle.C, Job3, fn);
109
+
110
+ jobScheduler.prepare(Lifecycle.A);
111
+ await jobScheduler.wait(Lifecycle.A);
112
+ expect(fn).not.toBeCalled();
113
+
114
+ jobScheduler.prepare(Lifecycle.B);
115
+ await jobScheduler.wait(Lifecycle.B);
116
+ expect(fn).not.toBeCalled();
117
+
118
+ jobScheduler.prepare(Lifecycle.C);
119
+ await jobScheduler.wait(Lifecycle.C);
120
+ expect(fn).toBeCalled();
121
+ });
122
+ });
@@ -0,0 +1,118 @@
1
+ import { IInstantiationService, type GetLeadingNonServiceArgs } from '@/di';
2
+ import { lvAssert, lvAssertNotHere } from '@/assert';
3
+ import type { AbstractJob } from './abstract-job';
4
+ import { CostRecorder } from './cost-recorder';
5
+
6
+ class JobDescriptor<T, K extends T> {
7
+ readonly ctor: new (...args: any[]) => AbstractJob<T, K>;
8
+ readonly staticArguments: any[];
9
+
10
+ constructor(ctor: new (...args: any[]) => AbstractJob<T, K>, args: any[]) {
11
+ this.ctor = ctor;
12
+ this.staticArguments = args;
13
+ }
14
+ }
15
+
16
+ export class JobScheduler<T, K extends T = T> {
17
+ private readonly _jobPools: Map<string, AbstractJob<T, K>> = new Map();
18
+ private readonly _costRecorder = new CostRecorder();
19
+ private readonly _unconstructedJobs: Map<K, JobDescriptor<AbstractJob<T, K>, any>[]> = new Map();
20
+
21
+ constructor(
22
+ private _currentPhase: K,
23
+ @IInstantiationService private readonly _instantiationService: IInstantiationService,
24
+ ) {}
25
+
26
+ get currentPhase() {
27
+ return this._currentPhase;
28
+ }
29
+
30
+ /**
31
+ * 按需添加一个job,job会在phase时刻才进行实例化
32
+ * @param phase job实例化时机
33
+ * @param ctor job构造函数
34
+ * @param args job构造静态参数
35
+ */
36
+ registerJob<Ctor extends new (...args: any[]) => AbstractJob<T, K>>(
37
+ phase: K,
38
+ ctor: Ctor,
39
+ ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>>
40
+ ) {
41
+ if (!this._unconstructedJobs.has(phase)) {
42
+ this._unconstructedJobs.set(phase, [new JobDescriptor(ctor, args)]);
43
+ } else {
44
+ this._unconstructedJobs.get(phase)!.push(new JobDescriptor(ctor, args));
45
+ }
46
+ }
47
+
48
+ /**
49
+ * 添加一个构造好的job
50
+ * @param job 任务
51
+ */
52
+ addJob(job: AbstractJob<T, K>) {
53
+ lvAssert(!this._jobPools.has(job.name), 'cant duplicate add job.');
54
+ this._jobPools.set(job.name, job);
55
+ }
56
+
57
+ removeJob(jobName: string) {
58
+ this._jobPools.delete(jobName);
59
+ }
60
+
61
+ prepare(phase: K) {
62
+ const descriptors = this._unconstructedJobs.get(phase) ?? [];
63
+ for (const d of descriptors) {
64
+ this.addJob(this._instantiationService.createInstance(d.ctor, ...d.staticArguments));
65
+ }
66
+ let shouldWait = false;
67
+ this._unconstructedJobs.delete(phase);
68
+ for (const [, job] of this._jobPools) {
69
+ const start = Date.now();
70
+ job.prepare(phase);
71
+ this._costRecorder.record(job.name, phase as number | string, Date.now() - start);
72
+
73
+ if (job.shouldWait(phase)) {
74
+ shouldWait = true;
75
+ }
76
+ }
77
+
78
+ return shouldWait;
79
+ }
80
+
81
+ getCost() {
82
+ return this._costRecorder.toString();
83
+ }
84
+
85
+ /**
86
+ * 推进到目标阶段,要求目标阶段没有需要等待的任务
87
+ * @param phase 目标阶段
88
+ */
89
+ advanceToPhase(phase: K) {
90
+ for (const [, job] of this._jobPools) {
91
+ if (job.shouldWait(phase)) {
92
+ lvAssertNotHere(`exists job should wait, job name: ${job.name}, phase: ${phase}`);
93
+ }
94
+ }
95
+
96
+ this._currentPhase = phase;
97
+ }
98
+
99
+ async wait(phase: K) {
100
+ const jobPromises: Promise<void>[] = [];
101
+ for (const [, job] of this._jobPools) {
102
+ if (!job.shouldWait(phase)) {
103
+ continue;
104
+ }
105
+ jobPromises.push(
106
+ (() => {
107
+ const start = Date.now();
108
+ return job.wait(phase).then(() => {
109
+ this._costRecorder.record(job.name, phase as number | string, Date.now() - start);
110
+ });
111
+ })(),
112
+ );
113
+ }
114
+
115
+ await Promise.all(jobPromises);
116
+ this._currentPhase = phase;
117
+ }
118
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "hash": "ec1fa8f3",
3
+ "configHash": "a2dd8394",
4
+ "lockfileHash": "d75a6bc5",
5
+ "browserHash": "cb29fc16",
6
+ "optimized": {},
7
+ "chunks": {}
8
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1 @@
1
+ {"version":"1.0.1","results":[[":job-scheduler.test.ts",{"duration":2,"failed":false}]]}
@@ -0,0 +1,11 @@
1
+ # 读写锁
2
+ TODO(niurouwan): 补上
3
+
4
+ ## 核心
5
+ - 写写互斥、读写互斥,读读可重入
6
+ - 写者优先于读者
7
+ - 写者唤醒顺序按调用顺序来
8
+
9
+ ## 实现原理
10
+
11
+ ## 使用举例
@@ -0,0 +1,110 @@
1
+ import { CapabilityStatus, Capability, SharedCapability } from './capability';
2
+
3
+ describe('Capability', () => {
4
+ // 初始化
5
+ it('init', () => {
6
+ const capability = new Capability();
7
+ // 初始化完成,默认是没有锁状态
8
+ expect(capability.status).toBe(CapabilityStatus.Unlocked);
9
+ });
10
+
11
+ // 获取控制权成功
12
+ it('acquire success', () => {
13
+ const capability = new Capability();
14
+ expect(capability.status).toBe(CapabilityStatus.Unlocked);
15
+ capability.acquire();
16
+ expect(capability.status).toBe(CapabilityStatus.Locked);
17
+ });
18
+
19
+ // 获取控制权失败
20
+ it('acquire fail', () => {
21
+ const capability = new Capability();
22
+ capability.acquire();
23
+ expect(() => {
24
+ capability.acquire();
25
+ }).toThrowError();
26
+ });
27
+
28
+ // 释放控制权成功
29
+ it('release success', () => {
30
+ let locked = false;
31
+ const capability = new Capability();
32
+ capability.onUnlocked(() => {
33
+ locked = false;
34
+ });
35
+ expect(capability.status).toBe(CapabilityStatus.Unlocked);
36
+ capability.acquire();
37
+ locked = true;
38
+ expect(capability.status).toBe(CapabilityStatus.Locked);
39
+ expect(locked).toBeTruthy();
40
+
41
+ capability.release();
42
+ expect(capability.status).toBe(CapabilityStatus.Unlocked);
43
+ expect(locked).toBeFalsy();
44
+ });
45
+
46
+ // 直接释放控制权失败
47
+ it('release fail1', () => {
48
+ const capability = new Capability();
49
+ expect(() => {
50
+ capability.release();
51
+ }).toThrowError();
52
+ });
53
+
54
+ // 重复释放控制权失败
55
+ it('release fail2', () => {
56
+ const capability = new Capability();
57
+ capability.acquire();
58
+ capability.release();
59
+ expect(() => {
60
+ capability.release();
61
+ }).toThrowError();
62
+ });
63
+ });
64
+
65
+ describe('SharedCapability', () => {
66
+ // 初始化
67
+ it('init', () => {
68
+ const capability = new SharedCapability();
69
+ // 初始化完成,默认是没有锁状态
70
+ expect(capability.status).toBe(CapabilityStatus.Unlocked);
71
+ });
72
+
73
+ // 获取控制权成功
74
+ it('acquire success', () => {
75
+ const capability = new SharedCapability();
76
+ capability.acquire();
77
+ expect(capability.status).toBe(CapabilityStatus.Locked);
78
+ expect(() => {
79
+ capability.acquire();
80
+ }).not.toThrowError();
81
+ });
82
+
83
+ // 释放控制权成功
84
+ it('release success', () => {
85
+ const capability = new SharedCapability();
86
+ capability.acquire();
87
+ expect(capability.status).toBe(CapabilityStatus.Locked);
88
+ capability.acquire();
89
+ expect(() => {
90
+ capability.release();
91
+ capability.release();
92
+ }).not.toThrowError();
93
+ expect(capability.status).toBe(CapabilityStatus.Unlocked);
94
+ });
95
+
96
+ // 释放控制权失败
97
+ it('release fail', () => {
98
+ const capability = new SharedCapability();
99
+ capability.acquire();
100
+ expect(capability.status).toBe(CapabilityStatus.Locked);
101
+ capability.acquire();
102
+ expect(() => {
103
+ capability.release();
104
+ capability.release();
105
+ }).not.toThrowError();
106
+ expect(() => {
107
+ capability.release();
108
+ }).toThrowError();
109
+ });
110
+ });
@@ -0,0 +1,89 @@
1
+ import { lvAssert } from '@/assert';
2
+ import { Emitter, type Event } from '@/event';
3
+
4
+ //
5
+ // 资源对应的是标准库中的 unsigned state 以及相关的位运算
6
+ // 我们用两个具体的Capability结构实现(Capability命名来源于标准库)
7
+ //
8
+
9
+ /**
10
+ * 资源状态
11
+ */
12
+ export enum CapabilityStatus {
13
+ Unlocked,
14
+ Locked,
15
+ }
16
+
17
+ /**
18
+ * 独享的资源
19
+ *
20
+ * acquire 获取控制权
21
+ * release 释放控制权
22
+ */
23
+ export class Capability {
24
+ public onUnlocked: Event<[]>;
25
+
26
+ private readonly _onUnlocked = new Emitter<[]>();
27
+ private _status = CapabilityStatus.Unlocked;
28
+
29
+ constructor() {
30
+ this.onUnlocked = this._onUnlocked.event;
31
+ }
32
+
33
+ get status(): CapabilityStatus {
34
+ return this._status;
35
+ }
36
+
37
+ public acquire(): void {
38
+ lvAssert(this._status === CapabilityStatus.Unlocked);
39
+ this._status = CapabilityStatus.Locked;
40
+ }
41
+
42
+ public release(): void {
43
+ lvAssert(this._status === CapabilityStatus.Locked);
44
+ this._status = CapabilityStatus.Unlocked;
45
+ this._onUnlocked.fire();
46
+ }
47
+ }
48
+
49
+ /**
50
+ * 共享的资源
51
+ *
52
+ * acquire 获取控制权
53
+ * release 释放控制权
54
+ */
55
+ export class SharedCapability {
56
+ public onUnlocked: Event<[]>;
57
+
58
+ private readonly _onUnlocked = new Emitter<[]>();
59
+ private _status = CapabilityStatus.Unlocked;
60
+ private _counter = 0;
61
+
62
+ constructor() {
63
+ this.onUnlocked = this._onUnlocked.event;
64
+ }
65
+
66
+ get status(): CapabilityStatus {
67
+ return this._status;
68
+ }
69
+
70
+ get counter(): number {
71
+ return this._counter;
72
+ }
73
+
74
+ public acquire() {
75
+ if (this._status === CapabilityStatus.Unlocked) {
76
+ this._status = CapabilityStatus.Locked;
77
+ }
78
+ this._counter++;
79
+ }
80
+
81
+ public release() {
82
+ lvAssert(this._counter > 0);
83
+ this._counter--;
84
+ if (this._counter === 0) {
85
+ this._status = CapabilityStatus.Unlocked;
86
+ this._onUnlocked.fire();
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,15 @@
1
+ // 读写能力的互斥量,实现读写锁的能力
2
+ export { SharedMutex } from './shared-mutex';
3
+
4
+ // 可解锁的句柄
5
+ export type { IUnlockable } from './utils';
6
+
7
+ // 转移独享锁控制权
8
+ export { transferLock } from './utils';
9
+ // 尝试转移独享锁控制权
10
+ export { tryTransferLock } from './utils';
11
+
12
+ // 转移共享锁控制权
13
+ export { transferSharedLock } from './utils';
14
+ // 尝试转移共享锁控制权
15
+ export { tryTransferSharedLock } from './utils';
@@ -0,0 +1 @@
1
+ {"version":"1.0.1","results":[]}
@@ -0,0 +1,21 @@
1
+ import type { Event } from '@/event';
2
+ import { Emitter } from '@/event';
3
+
4
+ /**
5
+ * 信号
6
+ *
7
+ * 用来模拟标准库的condition_variable
8
+ * 提供监听某个信号被激活的能力
9
+ */
10
+ export class Semaphore {
11
+ public onActive: Event<[]>;
12
+ private readonly _onActive = new Emitter<[]>();
13
+
14
+ constructor() {
15
+ this.onActive = this._onActive.event;
16
+ }
17
+
18
+ public notify(): void {
19
+ this._onActive.fire();
20
+ }
21
+ }