front-cpu 0.1.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.
- package/README.md +475 -0
- package/README.zh-CN.md +474 -0
- package/dist/Pipeline.d.ts +119 -0
- package/dist/Pipeline.d.ts.map +1 -0
- package/dist/Pipeline.js +373 -0
- package/dist/Pipeline.js.map +1 -0
- package/dist/debug.d.ts +3 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +12 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +49 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +8 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/isa/index.d.ts +20 -0
- package/dist/isa/index.d.ts.map +1 -0
- package/dist/isa/index.js +26 -0
- package/dist/isa/index.js.map +1 -0
- package/dist/isa/types.d.ts +144 -0
- package/dist/isa/types.d.ts.map +1 -0
- package/dist/isa/types.js +10 -0
- package/dist/isa/types.js.map +1 -0
- package/dist/logging/CPUConsole.d.ts +105 -0
- package/dist/logging/CPUConsole.d.ts.map +1 -0
- package/dist/logging/CPUConsole.js +471 -0
- package/dist/logging/CPUConsole.js.map +1 -0
- package/dist/logging/CPUDebugger.d.ts +91 -0
- package/dist/logging/CPUDebugger.d.ts.map +1 -0
- package/dist/logging/CPUDebugger.js +166 -0
- package/dist/logging/CPUDebugger.js.map +1 -0
- package/dist/logging/CPUEventCollector.d.ts +90 -0
- package/dist/logging/CPUEventCollector.d.ts.map +1 -0
- package/dist/logging/CPUEventCollector.js +353 -0
- package/dist/logging/CPUEventCollector.js.map +1 -0
- package/dist/logging/CPULogger.d.ts +150 -0
- package/dist/logging/CPULogger.d.ts.map +1 -0
- package/dist/logging/CPULogger.js +336 -0
- package/dist/logging/CPULogger.js.map +1 -0
- package/dist/logging/index.d.ts +10 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +16 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/runtime.d.ts +37 -0
- package/dist/logging/runtime.d.ts.map +1 -0
- package/dist/logging/runtime.js +42 -0
- package/dist/logging/runtime.js.map +1 -0
- package/dist/logging/stack-parser.d.ts +22 -0
- package/dist/logging/stack-parser.d.ts.map +1 -0
- package/dist/logging/stack-parser.js +144 -0
- package/dist/logging/stack-parser.js.map +1 -0
- package/dist/logging/types.d.ts +73 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +47 -0
- package/dist/logging/types.js.map +1 -0
- package/dist/scheduling/ResourceStrategyRegistry.d.ts +61 -0
- package/dist/scheduling/ResourceStrategyRegistry.d.ts.map +1 -0
- package/dist/scheduling/ResourceStrategyRegistry.js +109 -0
- package/dist/scheduling/ResourceStrategyRegistry.js.map +1 -0
- package/dist/scheduling/index.d.ts +6 -0
- package/dist/scheduling/index.d.ts.map +1 -0
- package/dist/scheduling/index.js +5 -0
- package/dist/scheduling/index.js.map +1 -0
- package/dist/scheduling/types.d.ts +44 -0
- package/dist/scheduling/types.d.ts.map +1 -0
- package/dist/scheduling/types.js +5 -0
- package/dist/scheduling/types.js.map +1 -0
- package/dist/stages/EX.d.ts +17 -0
- package/dist/stages/EX.d.ts.map +1 -0
- package/dist/stages/EX.js +95 -0
- package/dist/stages/EX.js.map +1 -0
- package/dist/stages/IF.d.ts +41 -0
- package/dist/stages/IF.d.ts.map +1 -0
- package/dist/stages/IF.js +83 -0
- package/dist/stages/IF.js.map +1 -0
- package/dist/stages/RES.d.ts +17 -0
- package/dist/stages/RES.d.ts.map +1 -0
- package/dist/stages/RES.js +37 -0
- package/dist/stages/RES.js.map +1 -0
- package/dist/stages/SCH.d.ts +77 -0
- package/dist/stages/SCH.d.ts.map +1 -0
- package/dist/stages/SCH.js +270 -0
- package/dist/stages/SCH.js.map +1 -0
- package/dist/stages/WB.d.ts +19 -0
- package/dist/stages/WB.d.ts.map +1 -0
- package/dist/stages/WB.js +102 -0
- package/dist/stages/WB.js.map +1 -0
- package/dist/types.d.ts +111 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +26 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/InstructionCancellation.d.ts +31 -0
- package/dist/utils/InstructionCancellation.d.ts.map +1 -0
- package/dist/utils/InstructionCancellation.js +53 -0
- package/dist/utils/InstructionCancellation.js.map +1 -0
- package/dist/utils/abortable.d.ts +30 -0
- package/dist/utils/abortable.d.ts.map +1 -0
- package/dist/utils/abortable.js +76 -0
- package/dist/utils/abortable.js.map +1 -0
- package/dist/utils/request.d.ts +27 -0
- package/dist/utils/request.d.ts.map +1 -0
- package/dist/utils/request.js +96 -0
- package/dist/utils/request.js.map +1 -0
- package/package.json +74 -0
- package/src/Pipeline.ts +475 -0
- package/src/debug.ts +15 -0
- package/src/index.ts +67 -0
- package/src/interfaces.ts +53 -0
- package/src/isa/index.ts +34 -0
- package/src/isa/types.ts +178 -0
- package/src/logging/CPUConsole.md +843 -0
- package/src/logging/CPUConsole.ts +631 -0
- package/src/logging/CPUDebugger.ts +235 -0
- package/src/logging/CPUEventCollector.ts +418 -0
- package/src/logging/CPULogger.ts +435 -0
- package/src/logging/CPU_LOGGING_DESIGN.md +1319 -0
- package/src/logging/USAGE_GUIDE.md +505 -0
- package/src/logging/index.ts +21 -0
- package/src/logging/runtime.ts +96 -0
- package/src/logging/stack-parser.ts +168 -0
- package/src/logging/types.ts +101 -0
- package/src/scheduling/ResourceStrategyRegistry.ts +124 -0
- package/src/scheduling/index.ts +13 -0
- package/src/scheduling/types.ts +47 -0
- package/src/stages/EX.ts +121 -0
- package/src/stages/IF.ts +103 -0
- package/src/stages/RES.ts +46 -0
- package/src/stages/SCH.ts +331 -0
- package/src/stages/WB.ts +127 -0
- package/src/types.ts +118 -0
- package/src/utils/InstructionCancellation.ts +73 -0
- package/src/utils/abortable.ts +89 -0
- package/src/utils/request.ts +125 -0
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "front-cpu",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "FrontCPU - Frontend instruction execution system with out-of-order execution",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./debug": {
|
|
15
|
+
"import": "./dist/debug.js",
|
|
16
|
+
"types": "./dist/debug.d.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dev": "vite",
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"build:playground": "vite build",
|
|
27
|
+
"prepublishOnly": "pnpm -s build",
|
|
28
|
+
"preview": "vite preview",
|
|
29
|
+
"test": "vitest",
|
|
30
|
+
"test:ui": "vitest --ui",
|
|
31
|
+
"bench": "vitest bench",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"lint": "eslint src --ext .ts",
|
|
34
|
+
"size:bundle": "node ./scripts/check-bundle-size.mjs",
|
|
35
|
+
"format": "prettier --write \"src/**/*.ts\""
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"front-cpu",
|
|
39
|
+
"frontcpu",
|
|
40
|
+
"cpu",
|
|
41
|
+
"pipeline",
|
|
42
|
+
"instruction",
|
|
43
|
+
"scheduler",
|
|
44
|
+
"out-of-order",
|
|
45
|
+
"concurrency",
|
|
46
|
+
"frontend-architecture",
|
|
47
|
+
"async",
|
|
48
|
+
"debugging"
|
|
49
|
+
],
|
|
50
|
+
"author": "",
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^20.0.0",
|
|
54
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
55
|
+
"@vitest/ui": "^1.0.0",
|
|
56
|
+
"@vue/tsconfig": "^0.5.0",
|
|
57
|
+
"esbuild": "^0.27.2",
|
|
58
|
+
"typescript": "^5.3.0",
|
|
59
|
+
"vite": "^5.0.0",
|
|
60
|
+
"vitest": "^1.0.0",
|
|
61
|
+
"vue": "^3.4.0"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"vue": "^3.0.0"
|
|
65
|
+
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"vue": {
|
|
68
|
+
"optional": true
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"lucide-vue-next": "^0.547.0"
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/Pipeline.ts
ADDED
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CPU流水线主控制器(解耦版)
|
|
3
|
+
*
|
|
4
|
+
* 通过依赖注入实现零耦合架构
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { InstructionFetchStage } from './stages/IF'
|
|
8
|
+
import { SchedulerStage } from './stages/SCH'
|
|
9
|
+
import { ExecuteStage } from './stages/EX'
|
|
10
|
+
import { ResponseStage } from './stages/RES'
|
|
11
|
+
import { WriteBackStage } from './stages/WB'
|
|
12
|
+
import { cpuEventCollector, cpuConsole, captureCallSource } from './logging/runtime'
|
|
13
|
+
import type { QueuedInstruction } from './types'
|
|
14
|
+
import { InstructionStatus } from './types'
|
|
15
|
+
import type { IReactiveState } from './interfaces'
|
|
16
|
+
import { isInstructionCancelled, cancelInstruction } from './utils/InstructionCancellation'
|
|
17
|
+
|
|
18
|
+
export interface PipelineStatus {
|
|
19
|
+
ifBufferSize: number
|
|
20
|
+
schPendingSize: number
|
|
21
|
+
schActiveSize: number
|
|
22
|
+
totalCompleted: number
|
|
23
|
+
totalFailed: number
|
|
24
|
+
totalCancelled: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Pipeline配置
|
|
29
|
+
*/
|
|
30
|
+
export interface PipelineConfig {
|
|
31
|
+
/** Tick间隔(ms),默认16 */
|
|
32
|
+
tickInterval?: number
|
|
33
|
+
/** 最大并发数,默认10 */
|
|
34
|
+
maxConcurrency?: number
|
|
35
|
+
/** 响应式状态工厂(用于适配不同框架) */
|
|
36
|
+
reactiveStateFactory?: <T>(initialValue: T) => IReactiveState<T>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 默认状态实现(非响应式)
|
|
41
|
+
*/
|
|
42
|
+
function createPlainState<T>(initialValue: T): IReactiveState<T> {
|
|
43
|
+
let value = initialValue
|
|
44
|
+
const subscribers: Array<(value: T) => void> = []
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
get value() {
|
|
48
|
+
return value
|
|
49
|
+
},
|
|
50
|
+
setValue(newValue: T) {
|
|
51
|
+
value = newValue
|
|
52
|
+
subscribers.forEach((cb) => cb(value))
|
|
53
|
+
},
|
|
54
|
+
subscribe(callback) {
|
|
55
|
+
subscribers.push(callback)
|
|
56
|
+
return () => {
|
|
57
|
+
const index = subscribers.indexOf(callback)
|
|
58
|
+
if (index > -1) subscribers.splice(index, 1)
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class Pipeline {
|
|
65
|
+
private IF: InstructionFetchStage
|
|
66
|
+
private SCH: SchedulerStage
|
|
67
|
+
private EX: ExecuteStage
|
|
68
|
+
private RES: ResponseStage
|
|
69
|
+
private WB: WriteBackStage
|
|
70
|
+
|
|
71
|
+
private isRunning = false
|
|
72
|
+
private tickInterval: ReturnType<typeof setInterval> | null = null
|
|
73
|
+
private readonly TICK_INTERVAL_MS: number
|
|
74
|
+
private readonly MAX_CONCURRENCY: number
|
|
75
|
+
private totalCompleted = 0
|
|
76
|
+
private totalFailed = 0
|
|
77
|
+
private totalCancelled = 0
|
|
78
|
+
|
|
79
|
+
// 响应式状态
|
|
80
|
+
public status: IReactiveState<PipelineStatus>
|
|
81
|
+
|
|
82
|
+
// 🔥 Promise resolvers for awaitable dispatch
|
|
83
|
+
private promiseResolvers = new Map<
|
|
84
|
+
string,
|
|
85
|
+
{
|
|
86
|
+
resolve: (result: any) => void
|
|
87
|
+
reject: (error: Error) => void
|
|
88
|
+
}
|
|
89
|
+
>()
|
|
90
|
+
|
|
91
|
+
constructor(config: PipelineConfig = {}) {
|
|
92
|
+
// 配置参数
|
|
93
|
+
this.TICK_INTERVAL_MS = config.tickInterval ?? 16
|
|
94
|
+
this.MAX_CONCURRENCY = config.maxConcurrency ?? 10
|
|
95
|
+
|
|
96
|
+
// 创建响应式状态
|
|
97
|
+
const stateFactory = config.reactiveStateFactory ?? createPlainState
|
|
98
|
+
this.status = stateFactory<PipelineStatus>({
|
|
99
|
+
ifBufferSize: 0,
|
|
100
|
+
schPendingSize: 0,
|
|
101
|
+
schActiveSize: 0,
|
|
102
|
+
totalCompleted: 0,
|
|
103
|
+
totalFailed: 0,
|
|
104
|
+
totalCancelled: 0,
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// 创建流水线阶段
|
|
108
|
+
this.IF = new InstructionFetchStage()
|
|
109
|
+
this.SCH = new SchedulerStage(this.MAX_CONCURRENCY)
|
|
110
|
+
this.EX = new ExecuteStage()
|
|
111
|
+
this.RES = new ResponseStage()
|
|
112
|
+
this.WB = new WriteBackStage()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 发射指令(外部API)
|
|
117
|
+
*
|
|
118
|
+
* @returns Promise that resolves with the instruction result or rejects with error
|
|
119
|
+
*/
|
|
120
|
+
dispatch<TPayload, TResult = any>(
|
|
121
|
+
type: string,
|
|
122
|
+
payload: TPayload,
|
|
123
|
+
source: 'user' | 'system' | 'test' = 'user',
|
|
124
|
+
options?: { tags?: string[] }
|
|
125
|
+
): Promise<TResult> {
|
|
126
|
+
return new Promise((resolve, reject) => {
|
|
127
|
+
// 🔒 检查流水线是否在运行
|
|
128
|
+
if (!this.isRunning) {
|
|
129
|
+
console.warn('%c⚠️ 流水线未启动,指令被拒绝', 'color: #FF9800; font-weight: bold', {
|
|
130
|
+
type,
|
|
131
|
+
payload,
|
|
132
|
+
})
|
|
133
|
+
reject(new Error('Pipeline is not running'))
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 🔍 捕获调用源(跳过 1 层:Promise constructor)
|
|
138
|
+
const callSource = captureCallSource(1)
|
|
139
|
+
|
|
140
|
+
// IF: 获取指令
|
|
141
|
+
const instruction = this.IF.fetchInstruction(type, payload, source, callSource, options?.tags)
|
|
142
|
+
|
|
143
|
+
// 🔥 保存 Promise resolvers
|
|
144
|
+
this.promiseResolvers.set(instruction.id, { resolve, reject })
|
|
145
|
+
|
|
146
|
+
// 🎯 记录指令创建事件
|
|
147
|
+
cpuEventCollector.onInstructionCreated(instruction)
|
|
148
|
+
cpuConsole.onInstructionCreated(instruction)
|
|
149
|
+
|
|
150
|
+
// 加入调度队列
|
|
151
|
+
this.SCH.addInstruction(instruction)
|
|
152
|
+
|
|
153
|
+
// 立即尝试调度
|
|
154
|
+
this.SCH.tick()
|
|
155
|
+
|
|
156
|
+
// 🔥 立即执行新发射的指令(避免tick延迟)
|
|
157
|
+
this.processActiveInstructions()
|
|
158
|
+
|
|
159
|
+
// 更新状态
|
|
160
|
+
this.updateStatus()
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 启动流水线
|
|
166
|
+
*/
|
|
167
|
+
start(): void {
|
|
168
|
+
if (this.isRunning) return
|
|
169
|
+
|
|
170
|
+
this.isRunning = true
|
|
171
|
+
|
|
172
|
+
// 启动调度器的tick循环
|
|
173
|
+
this.tickInterval = globalThis.setInterval(() => {
|
|
174
|
+
this.SCH.tick()
|
|
175
|
+
this.processActiveInstructions()
|
|
176
|
+
this.updateStatus()
|
|
177
|
+
}, this.TICK_INTERVAL_MS)
|
|
178
|
+
|
|
179
|
+
console.log('%c🚀 CPU流水线已启动', 'color: #2196F3; font-weight: bold')
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 停止流水线
|
|
184
|
+
*/
|
|
185
|
+
stop(): void {
|
|
186
|
+
if (!this.isRunning) return
|
|
187
|
+
|
|
188
|
+
this.isRunning = false
|
|
189
|
+
|
|
190
|
+
if (this.tickInterval !== null) {
|
|
191
|
+
globalThis.clearInterval(this.tickInterval)
|
|
192
|
+
this.tickInterval = null
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
console.log('%c⏸️ CPU流水线已停止', 'color: #FF9800; font-weight: bold')
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* 重置流水线
|
|
200
|
+
*/
|
|
201
|
+
reset(): void {
|
|
202
|
+
this.stop()
|
|
203
|
+
|
|
204
|
+
// 清空所有阶段
|
|
205
|
+
this.IF.clear()
|
|
206
|
+
this.SCH.clear()
|
|
207
|
+
|
|
208
|
+
// 🔥 Reject all pending promises
|
|
209
|
+
for (const [, resolver] of this.promiseResolvers.entries()) {
|
|
210
|
+
resolver.reject(new Error('Pipeline was reset'))
|
|
211
|
+
}
|
|
212
|
+
this.promiseResolvers.clear()
|
|
213
|
+
|
|
214
|
+
// 重置状态
|
|
215
|
+
this.totalCompleted = 0
|
|
216
|
+
this.totalFailed = 0
|
|
217
|
+
this.totalCancelled = 0
|
|
218
|
+
this.status.setValue({
|
|
219
|
+
ifBufferSize: 0,
|
|
220
|
+
schPendingSize: 0,
|
|
221
|
+
schActiveSize: 0,
|
|
222
|
+
totalCompleted: 0,
|
|
223
|
+
totalFailed: 0,
|
|
224
|
+
totalCancelled: 0,
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
console.log('%c🔄 CPU流水线已重置', 'color: #9C27B0; font-weight: bold')
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 处理正在执行的指令
|
|
232
|
+
*/
|
|
233
|
+
private async processActiveInstructions(): Promise<void> {
|
|
234
|
+
const activeInstructions = this.SCH.getActiveInstructions()
|
|
235
|
+
|
|
236
|
+
for (const instruction of activeInstructions) {
|
|
237
|
+
// 已经在执行中,跳过
|
|
238
|
+
if (instruction.timestamps.EX) {
|
|
239
|
+
continue
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// 🔥 检查是否已被取消(switchMap 等场景)
|
|
243
|
+
if (isInstructionCancelled(instruction)) {
|
|
244
|
+
// 立即处理取消,不再进入执行流程
|
|
245
|
+
this.handleCancelledInstruction(instruction)
|
|
246
|
+
continue
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 异步执行指令
|
|
250
|
+
this.executeInstruction(instruction)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 处理已取消的指令
|
|
256
|
+
* 直接完成清理工作,不再进入 EX/RES/WB 流程
|
|
257
|
+
*/
|
|
258
|
+
private handleCancelledInstruction(instruction: QueuedInstruction): void {
|
|
259
|
+
// 标记 WB 时间戳(虽然没有真正执行 WB)
|
|
260
|
+
instruction.timestamps.WB = Date.now()
|
|
261
|
+
|
|
262
|
+
// 释放资源
|
|
263
|
+
this.SCH.releaseInstruction(instruction.id)
|
|
264
|
+
|
|
265
|
+
// 计算持续时间
|
|
266
|
+
const duration =
|
|
267
|
+
(instruction.timestamps.WB || Date.now()) - (instruction.timestamps.IF || Date.now())
|
|
268
|
+
|
|
269
|
+
// 记录取消事件
|
|
270
|
+
cpuEventCollector.onInstructionCancelled(instruction)
|
|
271
|
+
cpuConsole.onInstructionCancelled(instruction, duration)
|
|
272
|
+
this.totalCancelled += 1
|
|
273
|
+
|
|
274
|
+
// Reject Promise
|
|
275
|
+
const resolver = this.promiseResolvers.get(instruction.id)
|
|
276
|
+
if (resolver) {
|
|
277
|
+
resolver.reject(instruction.error || new Error('Instruction was cancelled'))
|
|
278
|
+
this.promiseResolvers.delete(instruction.id)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// 更新状态
|
|
282
|
+
this.updateStatus()
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* 执行单个指令
|
|
287
|
+
*/
|
|
288
|
+
private async executeInstruction(instruction: QueuedInstruction): Promise<void> {
|
|
289
|
+
let executionError: Error | undefined
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
// EX: 执行
|
|
293
|
+
await this.EX.execute(instruction)
|
|
294
|
+
} catch (err) {
|
|
295
|
+
executionError = err as Error
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// RES: 处理响应
|
|
299
|
+
const { success } = this.RES.processResponse(instruction, executionError)
|
|
300
|
+
|
|
301
|
+
// WB: 写回
|
|
302
|
+
await this.WB.writeBack(instruction, success)
|
|
303
|
+
|
|
304
|
+
// 释放资源
|
|
305
|
+
this.SCH.releaseInstruction(instruction.id)
|
|
306
|
+
|
|
307
|
+
// 🎯 获取最终错误信息
|
|
308
|
+
// 优先级:instruction.error(可能在 SCH/EX/RES 任何阶段设置) > 执行时捕获的错误 > 未知错误
|
|
309
|
+
const finalError = instruction.error || executionError || new Error('未知错误')
|
|
310
|
+
|
|
311
|
+
// 🎯 记录指令完成/失败/取消事件
|
|
312
|
+
const duration =
|
|
313
|
+
(instruction.timestamps.WB || Date.now()) - (instruction.timestamps.IF || Date.now())
|
|
314
|
+
|
|
315
|
+
if (success) {
|
|
316
|
+
// 成功
|
|
317
|
+
cpuEventCollector.onInstructionCommitted(instruction)
|
|
318
|
+
cpuConsole.onInstructionSuccess(instruction, duration)
|
|
319
|
+
this.totalCompleted += 1
|
|
320
|
+
} else if (instruction.status === InstructionStatus.CANCELLED) {
|
|
321
|
+
// 被取消(不算失败)
|
|
322
|
+
cpuEventCollector.onInstructionCancelled(instruction)
|
|
323
|
+
cpuConsole.onInstructionCancelled(instruction, duration)
|
|
324
|
+
this.totalCancelled += 1
|
|
325
|
+
} else {
|
|
326
|
+
// 失败
|
|
327
|
+
cpuEventCollector.onInstructionFailed(instruction, finalError)
|
|
328
|
+
cpuConsole.onInstructionFailure(instruction, finalError, duration)
|
|
329
|
+
this.totalFailed += 1
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// 🔥 Resolve/Reject Promise (if awaited)
|
|
333
|
+
const resolver = this.promiseResolvers.get(instruction.id)
|
|
334
|
+
if (resolver) {
|
|
335
|
+
if (success) {
|
|
336
|
+
resolver.resolve(instruction.result)
|
|
337
|
+
} else {
|
|
338
|
+
resolver.reject(finalError)
|
|
339
|
+
}
|
|
340
|
+
this.promiseResolvers.delete(instruction.id)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// 更新状态
|
|
344
|
+
this.updateStatus()
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* 按标签批量取消指令
|
|
349
|
+
* @param tags 要取消的标签(字符串或字符串数组)
|
|
350
|
+
* @returns 取消的指令数量
|
|
351
|
+
*/
|
|
352
|
+
flush(tags: string | string[]): number {
|
|
353
|
+
const targetTags = Array.isArray(tags) ? tags : [tags]
|
|
354
|
+
let cancelledCount = 0
|
|
355
|
+
|
|
356
|
+
// 1. 取消 SCH 中的 pending 指令
|
|
357
|
+
const pendingInstructions = this.SCH.getPendingInstructions()
|
|
358
|
+
for (const instruction of pendingInstructions) {
|
|
359
|
+
if (this.hasMatchingTags(instruction, targetTags)) {
|
|
360
|
+
cancelInstruction(instruction, `Flushed by tags: ${targetTags.join(', ')}`, 'SCH')
|
|
361
|
+
cancelledCount++
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// 2. 取消 SCH 中的 active 指令
|
|
366
|
+
const activeInstructions = this.SCH.getActiveInstructions()
|
|
367
|
+
for (const instruction of activeInstructions) {
|
|
368
|
+
if (this.hasMatchingTags(instruction, targetTags)) {
|
|
369
|
+
cancelInstruction(instruction, `Flushed by tags: ${targetTags.join(', ')}`, 'SCH')
|
|
370
|
+
cancelledCount++
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return cancelledCount
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* 检查指令是否包含匹配的标签
|
|
379
|
+
*/
|
|
380
|
+
private hasMatchingTags(instruction: QueuedInstruction, targetTags: string[]): boolean {
|
|
381
|
+
if (!instruction.tags || instruction.tags.length === 0) {
|
|
382
|
+
return false
|
|
383
|
+
}
|
|
384
|
+
return targetTags.some(tag => instruction.tags!.includes(tag))
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* 获取带特定标签的指令
|
|
389
|
+
*/
|
|
390
|
+
getInstructionsByTags(tags: string[]): QueuedInstruction[] {
|
|
391
|
+
const allInstructions = [
|
|
392
|
+
...this.SCH.getPendingInstructions(),
|
|
393
|
+
...this.SCH.getActiveInstructions()
|
|
394
|
+
]
|
|
395
|
+
return allInstructions.filter(instruction => this.hasMatchingTags(instruction, tags))
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* 获取所有活跃标签
|
|
400
|
+
*/
|
|
401
|
+
getActiveTags(): string[] {
|
|
402
|
+
const allInstructions = [
|
|
403
|
+
...this.SCH.getPendingInstructions(),
|
|
404
|
+
...this.SCH.getActiveInstructions()
|
|
405
|
+
]
|
|
406
|
+
const tagSet = new Set<string>()
|
|
407
|
+
for (const instruction of allInstructions) {
|
|
408
|
+
if (instruction.tags) {
|
|
409
|
+
instruction.tags.forEach(tag => tagSet.add(tag))
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return Array.from(tagSet)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* 获取标签统计信息
|
|
417
|
+
*/
|
|
418
|
+
getTagStats(): Record<string, number> {
|
|
419
|
+
const allInstructions = [
|
|
420
|
+
...this.SCH.getPendingInstructions(),
|
|
421
|
+
...this.SCH.getActiveInstructions()
|
|
422
|
+
]
|
|
423
|
+
const tagStats: Record<string, number> = {}
|
|
424
|
+
for (const instruction of allInstructions) {
|
|
425
|
+
if (instruction.tags) {
|
|
426
|
+
instruction.tags.forEach(tag => {
|
|
427
|
+
tagStats[tag] = (tagStats[tag] || 0) + 1
|
|
428
|
+
})
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return tagStats
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* 更新流水线状态
|
|
436
|
+
*/
|
|
437
|
+
private updateStatus(): void {
|
|
438
|
+
this.status.setValue({
|
|
439
|
+
ifBufferSize: this.IF.getBufferSize(),
|
|
440
|
+
schPendingSize: this.SCH.getPendingQueueSize(),
|
|
441
|
+
schActiveSize: this.SCH.getActiveCount(),
|
|
442
|
+
totalCompleted: this.totalCompleted,
|
|
443
|
+
totalFailed: this.totalFailed,
|
|
444
|
+
totalCancelled: this.totalCancelled,
|
|
445
|
+
})
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* 获取流水线状态(供外部使用)
|
|
450
|
+
*/
|
|
451
|
+
getStatus(): PipelineStatus {
|
|
452
|
+
return this.status.value
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* 获取IF缓冲区
|
|
457
|
+
*/
|
|
458
|
+
getIFBuffer(): QueuedInstruction[] {
|
|
459
|
+
return this.IF.getBuffer()
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 获取SCH pending队列
|
|
464
|
+
*/
|
|
465
|
+
getSCHPendingQueue(): QueuedInstruction[] {
|
|
466
|
+
return this.SCH.getPendingQueue()
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* 获取SCH active指令
|
|
471
|
+
*/
|
|
472
|
+
getSCHActiveInstructions(): QueuedInstruction[] {
|
|
473
|
+
return this.SCH.getActiveInstructions()
|
|
474
|
+
}
|
|
475
|
+
}
|
package/src/debug.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cpuEventCollector, cpuConsole, cpuLogger } from './logging'
|
|
2
|
+
import { captureCallSource } from './logging/stack-parser'
|
|
3
|
+
import { setLoggingProvider } from './logging/runtime'
|
|
4
|
+
|
|
5
|
+
setLoggingProvider({
|
|
6
|
+
cpuEventCollector,
|
|
7
|
+
cpuConsole,
|
|
8
|
+
cpuLogger,
|
|
9
|
+
captureCallSource,
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
export * from './index'
|
|
13
|
+
export * from './logging'
|
|
14
|
+
|
|
15
|
+
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrontCPU - 前端指令执行系统
|
|
3
|
+
*
|
|
4
|
+
* 解耦版:通过依赖注入实现零耦合架构
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// 核心Pipeline
|
|
8
|
+
export { Pipeline } from './Pipeline'
|
|
9
|
+
export type { PipelineStatus, PipelineConfig } from './Pipeline'
|
|
10
|
+
|
|
11
|
+
// 核心类型
|
|
12
|
+
export type {
|
|
13
|
+
QueuedInstruction,
|
|
14
|
+
InstructionContext,
|
|
15
|
+
InstructionStatus,
|
|
16
|
+
PipelineStage,
|
|
17
|
+
WriteBackExecution,
|
|
18
|
+
} from './types'
|
|
19
|
+
export {
|
|
20
|
+
PipelineStage as PipelineStageEnum,
|
|
21
|
+
InstructionStatus as InstructionStatusEnum,
|
|
22
|
+
} from './types'
|
|
23
|
+
|
|
24
|
+
// ISA相关
|
|
25
|
+
export { registerISA, getISA, clearISA } from './isa'
|
|
26
|
+
export type { ISADefinition, InstructionDefinition } from './isa/types'
|
|
27
|
+
export type {
|
|
28
|
+
InstructionMeta,
|
|
29
|
+
HttpMethod,
|
|
30
|
+
RequestConfig,
|
|
31
|
+
MultiRequestConfig,
|
|
32
|
+
OptimisticSnapshot,
|
|
33
|
+
OptimisticConfig,
|
|
34
|
+
SchedulingStrategy,
|
|
35
|
+
} from './isa/types'
|
|
36
|
+
|
|
37
|
+
// 调度策略
|
|
38
|
+
export type { ResourceStrategyConfig, StrategyContext } from './scheduling'
|
|
39
|
+
export {
|
|
40
|
+
registerResourceStrategy,
|
|
41
|
+
registerResourceStrategies,
|
|
42
|
+
setDefaultSchedulingStrategy,
|
|
43
|
+
} from './scheduling'
|
|
44
|
+
|
|
45
|
+
// 依赖注入
|
|
46
|
+
export { setHttpClient } from './utils/request'
|
|
47
|
+
export { setCorrelationIdGenerator } from './stages/IF'
|
|
48
|
+
|
|
49
|
+
// 抽象接口
|
|
50
|
+
export type {
|
|
51
|
+
IHttpClient,
|
|
52
|
+
ILogger,
|
|
53
|
+
ICorrelationIdGenerator,
|
|
54
|
+
IReactiveState,
|
|
55
|
+
RequestConfig as IRequestConfig,
|
|
56
|
+
} from './interfaces'
|
|
57
|
+
|
|
58
|
+
// 指令取消工具
|
|
59
|
+
export {
|
|
60
|
+
cancelInstruction,
|
|
61
|
+
isInstructionCancelled,
|
|
62
|
+
getCancellationInfo,
|
|
63
|
+
cancelInstructions,
|
|
64
|
+
} from './utils/InstructionCancellation'
|
|
65
|
+
|
|
66
|
+
// 可取消工具
|
|
67
|
+
export { makeAbortable, cancellableDelay } from './utils/abortable'
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrontCPU 抽象接口定义
|
|
3
|
+
*
|
|
4
|
+
* 这些接口用于解耦CPU核心系统与具体实现,
|
|
5
|
+
* 通过依赖注入实现零耦合架构。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* HTTP客户端接口
|
|
10
|
+
*/
|
|
11
|
+
export interface IHttpClient {
|
|
12
|
+
get<T>(url: string, config?: RequestConfig): Promise<T>
|
|
13
|
+
post<T>(url: string, data?: any, config?: RequestConfig): Promise<T>
|
|
14
|
+
patch<T>(url: string, data?: any, config?: RequestConfig): Promise<T>
|
|
15
|
+
put<T>(url: string, data?: any, config?: RequestConfig): Promise<T>
|
|
16
|
+
delete<T>(url: string, config?: RequestConfig): Promise<T>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* HTTP请求配置
|
|
21
|
+
*/
|
|
22
|
+
export interface RequestConfig {
|
|
23
|
+
headers?: Record<string, string>
|
|
24
|
+
[key: string]: any
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 日志接口
|
|
29
|
+
*/
|
|
30
|
+
export interface ILogger {
|
|
31
|
+
debug(tag: string, message: string, data?: any): void
|
|
32
|
+
info(tag: string, message: string, data?: any): void
|
|
33
|
+
warn(tag: string, message: string, data?: any): void
|
|
34
|
+
error(tag: string, message: string, data?: any): void
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* CorrelationId生成器接口
|
|
39
|
+
*/
|
|
40
|
+
export interface ICorrelationIdGenerator {
|
|
41
|
+
generate(): string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 响应式状态接口
|
|
46
|
+
*
|
|
47
|
+
* 用于适配不同框架的响应式系统(Vue、React、Svelte等)
|
|
48
|
+
*/
|
|
49
|
+
export interface IReactiveState<T> {
|
|
50
|
+
value: T
|
|
51
|
+
setValue(newValue: T): void
|
|
52
|
+
subscribe(callback: (value: T) => void): () => void
|
|
53
|
+
}
|