1fb726d48Sopenharmony_ci/* 2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb726d48Sopenharmony_ci * You may obtain a copy of the License at 6fb726d48Sopenharmony_ci * 7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb726d48Sopenharmony_ci * 9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 13fb726d48Sopenharmony_ci * limitations under the License. 14fb726d48Sopenharmony_ci */ 15fb726d48Sopenharmony_ci 16fb726d48Sopenharmony_ciimport { query } from './SqlLite'; 17fb726d48Sopenharmony_ci 18fb726d48Sopenharmony_ciclass ProcedureThread { 19fb726d48Sopenharmony_ci busy: boolean = false; 20fb726d48Sopenharmony_ci isCancelled: boolean = false; 21fb726d48Sopenharmony_ci id: number = -1; //@ts-ignore 22fb726d48Sopenharmony_ci taskMap: unknown = {}; 23fb726d48Sopenharmony_ci name: string | undefined; 24fb726d48Sopenharmony_ci worker?: Worker; 25fb726d48Sopenharmony_ci constructor(worker: Worker) { 26fb726d48Sopenharmony_ci this.worker = worker; 27fb726d48Sopenharmony_ci } 28fb726d48Sopenharmony_ci uuid(): string { 29fb726d48Sopenharmony_ci // @ts-ignore 30fb726d48Sopenharmony_ci return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => 31fb726d48Sopenharmony_ci (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) 32fb726d48Sopenharmony_ci ); 33fb726d48Sopenharmony_ci } 34fb726d48Sopenharmony_ci //@ts-ignore 35fb726d48Sopenharmony_ci queryFunc(type: string, args: unknown, transfer: unknown, handler: Function): void { 36fb726d48Sopenharmony_ci this.busy = true; 37fb726d48Sopenharmony_ci let id = this.uuid(); // @ts-ignore 38fb726d48Sopenharmony_ci this.taskMap[id] = handler; 39fb726d48Sopenharmony_ci let pam = { 40fb726d48Sopenharmony_ci id: id, 41fb726d48Sopenharmony_ci type: type, 42fb726d48Sopenharmony_ci params: args, 43fb726d48Sopenharmony_ci }; 44fb726d48Sopenharmony_ci if (transfer) { 45fb726d48Sopenharmony_ci try { 46fb726d48Sopenharmony_ci if (Array.isArray(transfer)) { 47fb726d48Sopenharmony_ci if (transfer.length > 0) { 48fb726d48Sopenharmony_ci this.worker!.postMessage(pam, [...transfer]); 49fb726d48Sopenharmony_ci } else { 50fb726d48Sopenharmony_ci this.worker!.postMessage(pam); 51fb726d48Sopenharmony_ci } 52fb726d48Sopenharmony_ci } else { 53fb726d48Sopenharmony_ci // @ts-ignore 54fb726d48Sopenharmony_ci this.worker!.postMessage(pam, [transfer]); 55fb726d48Sopenharmony_ci } 56fb726d48Sopenharmony_ci } catch ( 57fb726d48Sopenharmony_ci //@ts-ignore 58fb726d48Sopenharmony_ci e: unknown 59fb726d48Sopenharmony_ci ) {} 60fb726d48Sopenharmony_ci } else { 61fb726d48Sopenharmony_ci this.worker!.postMessage(pam); 62fb726d48Sopenharmony_ci } 63fb726d48Sopenharmony_ci } 64fb726d48Sopenharmony_ci 65fb726d48Sopenharmony_ci cancel(): void { 66fb726d48Sopenharmony_ci this.isCancelled = true; 67fb726d48Sopenharmony_ci this.worker!.terminate(); 68fb726d48Sopenharmony_ci } 69fb726d48Sopenharmony_ci} 70fb726d48Sopenharmony_ci 71fb726d48Sopenharmony_ciclass ProcedurePool { 72fb726d48Sopenharmony_ci static cpuCount = Math.floor((window.navigator.hardwareConcurrency || 4) / 2); 73fb726d48Sopenharmony_ci maxThreadNumber: number = 1; 74fb726d48Sopenharmony_ci works: Array<ProcedureThread> = []; 75fb726d48Sopenharmony_ci timelineChange: 76fb726d48Sopenharmony_ci | (( 77fb726d48Sopenharmony_ci //@ts-ignore 78fb726d48Sopenharmony_ci a: unknown 79fb726d48Sopenharmony_ci ) => void) 80fb726d48Sopenharmony_ci | undefined 81fb726d48Sopenharmony_ci | null = null; 82fb726d48Sopenharmony_ci cpusLen = ProcedurePool.build('cpu', 0); 83fb726d48Sopenharmony_ci freqLen = ProcedurePool.build('freq', 0); 84fb726d48Sopenharmony_ci processLen = ProcedurePool.build('process', 0); 85fb726d48Sopenharmony_ci logicDataLen = ProcedurePool.build('logic', 2); 86fb726d48Sopenharmony_ci names = [...this.cpusLen, ...this.processLen, ...this.freqLen]; 87fb726d48Sopenharmony_ci logicDataHandles = [...this.logicDataLen]; 88fb726d48Sopenharmony_ci 89fb726d48Sopenharmony_ci onComplete: Function | undefined; //任务完成回调 90fb726d48Sopenharmony_ci 91fb726d48Sopenharmony_ci constructor(threadBuild: (() => ProcedureThread) | undefined = undefined) { 92fb726d48Sopenharmony_ci this.init(threadBuild); 93fb726d48Sopenharmony_ci } 94fb726d48Sopenharmony_ci 95fb726d48Sopenharmony_ci static build(name: string, len: number): string[] { 96fb726d48Sopenharmony_ci return [...Array(len).keys()].map((it) => `${name}${it}`); 97fb726d48Sopenharmony_ci } 98fb726d48Sopenharmony_ci 99fb726d48Sopenharmony_ci init(threadBuild: (() => ProcedureThread) | undefined = undefined): void { 100fb726d48Sopenharmony_ci this.maxThreadNumber = this.names.length; 101fb726d48Sopenharmony_ci for (let i = 0; i < this.maxThreadNumber; i++) { 102fb726d48Sopenharmony_ci this.newThread(); 103fb726d48Sopenharmony_ci } 104fb726d48Sopenharmony_ci for (let j = 0; j < this.logicDataHandles.length; j++) { 105fb726d48Sopenharmony_ci this.logicDataThread(); 106fb726d48Sopenharmony_ci } 107fb726d48Sopenharmony_ci } 108fb726d48Sopenharmony_ci 109fb726d48Sopenharmony_ci newThread(): void { 110fb726d48Sopenharmony_ci // @ts-ignore 111fb726d48Sopenharmony_ci if (window.useWb) { 112fb726d48Sopenharmony_ci return; 113fb726d48Sopenharmony_ci } 114fb726d48Sopenharmony_ci let newThread: ProcedureThread = new ProcedureThread( 115fb726d48Sopenharmony_ci new Worker(new URL('./ui-worker/ProcedureWorker', import.meta.url), { 116fb726d48Sopenharmony_ci type: 'module', 117fb726d48Sopenharmony_ci }) 118fb726d48Sopenharmony_ci ); 119fb726d48Sopenharmony_ci newThread.name = this.names[this.works.length]; 120fb726d48Sopenharmony_ci newThread.worker!.onmessage = (event: MessageEvent): void => { 121fb726d48Sopenharmony_ci newThread.busy = false; 122fb726d48Sopenharmony_ci if ((event.data.type as string) === 'timeline-range-changed') { 123fb726d48Sopenharmony_ci this.timelineChange?.(event.data.results); 124fb726d48Sopenharmony_ci newThread.busy = false; 125fb726d48Sopenharmony_ci return; 126fb726d48Sopenharmony_ci } // @ts-ignore 127fb726d48Sopenharmony_ci if (Reflect.has(newThread.taskMap, event.data.id)) { 128fb726d48Sopenharmony_ci if (event.data) { 129fb726d48Sopenharmony_ci // @ts-ignore 130fb726d48Sopenharmony_ci let fun = newThread.taskMap[event.data.id]; 131fb726d48Sopenharmony_ci if (fun) { 132fb726d48Sopenharmony_ci fun(event.data.results, event.data.hover); 133fb726d48Sopenharmony_ci } // @ts-ignore 134fb726d48Sopenharmony_ci Reflect.deleteProperty(newThread.taskMap, event.data.id); 135fb726d48Sopenharmony_ci } 136fb726d48Sopenharmony_ci } 137fb726d48Sopenharmony_ci if (this.isIdle() && this.onComplete) { 138fb726d48Sopenharmony_ci this.onComplete(); 139fb726d48Sopenharmony_ci } 140fb726d48Sopenharmony_ci }; 141fb726d48Sopenharmony_ci newThread.worker!.onmessageerror = (e): void => {}; 142fb726d48Sopenharmony_ci newThread.worker!.onerror = (e): void => {}; 143fb726d48Sopenharmony_ci newThread.id = this.works.length; 144fb726d48Sopenharmony_ci newThread.busy = false; 145fb726d48Sopenharmony_ci this.works?.push(newThread); 146fb726d48Sopenharmony_ci } 147fb726d48Sopenharmony_ci 148fb726d48Sopenharmony_ci private logicDataThread(): void { 149fb726d48Sopenharmony_ci // @ts-ignore 150fb726d48Sopenharmony_ci if (window.useWb) { 151fb726d48Sopenharmony_ci return; 152fb726d48Sopenharmony_ci } 153fb726d48Sopenharmony_ci let thread: ProcedureThread = new ProcedureThread( 154fb726d48Sopenharmony_ci new Worker(new URL('./logic-worker/ProcedureLogicWorker', import.meta.url), { 155fb726d48Sopenharmony_ci type: 'module', 156fb726d48Sopenharmony_ci }) 157fb726d48Sopenharmony_ci ); 158fb726d48Sopenharmony_ci thread.name = this.logicDataHandles[this.works.length - this.names.length]; 159fb726d48Sopenharmony_ci this.sendMessage(thread); 160fb726d48Sopenharmony_ci thread.worker!.onmessageerror = (e): void => {}; 161fb726d48Sopenharmony_ci thread.worker!.onerror = (e): void => {}; 162fb726d48Sopenharmony_ci thread.id = this.works.length; 163fb726d48Sopenharmony_ci thread.busy = false; 164fb726d48Sopenharmony_ci this.works?.push(thread); 165fb726d48Sopenharmony_ci } 166fb726d48Sopenharmony_ci 167fb726d48Sopenharmony_ci private sendMessage(thread: ProcedureThread): void { 168fb726d48Sopenharmony_ci thread.worker!.onmessage = (event: MessageEvent): void => { 169fb726d48Sopenharmony_ci thread.busy = false; 170fb726d48Sopenharmony_ci if (event.data.isQuery) { 171fb726d48Sopenharmony_ci query(event.data.type, event.data.sql, event.data.args, { action : 'exec-buf' }).then( 172fb726d48Sopenharmony_ci ( 173fb726d48Sopenharmony_ci // @ts-ignore 174fb726d48Sopenharmony_ci res: unknown 175fb726d48Sopenharmony_ci ) => { 176fb726d48Sopenharmony_ci thread.worker!.postMessage({ 177fb726d48Sopenharmony_ci type: event.data.type, 178fb726d48Sopenharmony_ci params: { 179fb726d48Sopenharmony_ci list: res, 180fb726d48Sopenharmony_ci }, 181fb726d48Sopenharmony_ci id: event.data.id, 182fb726d48Sopenharmony_ci }); 183fb726d48Sopenharmony_ci } 184fb726d48Sopenharmony_ci ); 185fb726d48Sopenharmony_ci return; 186fb726d48Sopenharmony_ci } 187fb726d48Sopenharmony_ci if (event.data.isSending) { 188fb726d48Sopenharmony_ci if ( 189fb726d48Sopenharmony_ci Reflect.has( 190fb726d48Sopenharmony_ci // @ts-ignore 191fb726d48Sopenharmony_ci thread.taskMap, 192fb726d48Sopenharmony_ci event.data.id 193fb726d48Sopenharmony_ci ) 194fb726d48Sopenharmony_ci ) { 195fb726d48Sopenharmony_ci if (event.data) { 196fb726d48Sopenharmony_ci // @ts-ignore 197fb726d48Sopenharmony_ci let fun = thread.taskMap[event.data.id]; 198fb726d48Sopenharmony_ci if (fun) { 199fb726d48Sopenharmony_ci fun(event.data.results, event.data.hover); 200fb726d48Sopenharmony_ci } 201fb726d48Sopenharmony_ci return; 202fb726d48Sopenharmony_ci } 203fb726d48Sopenharmony_ci } 204fb726d48Sopenharmony_ci } // @ts-ignore 205fb726d48Sopenharmony_ci if (Reflect.has(thread.taskMap, event.data.id)) { 206fb726d48Sopenharmony_ci if (event.data) { 207fb726d48Sopenharmony_ci // @ts-ignore 208fb726d48Sopenharmony_ci let fun = thread.taskMap[event.data.id]; 209fb726d48Sopenharmony_ci if (fun) { 210fb726d48Sopenharmony_ci fun(event.data.results, event.data.hover); 211fb726d48Sopenharmony_ci } // @ts-ignore 212fb726d48Sopenharmony_ci Reflect.deleteProperty(thread.taskMap, event.data.id); 213fb726d48Sopenharmony_ci } 214fb726d48Sopenharmony_ci } 215fb726d48Sopenharmony_ci if (this.isIdle() && this.onComplete) { 216fb726d48Sopenharmony_ci this.onComplete(); 217fb726d48Sopenharmony_ci } 218fb726d48Sopenharmony_ci }; 219fb726d48Sopenharmony_ci } 220fb726d48Sopenharmony_ci 221fb726d48Sopenharmony_ci close = (): void => { 222fb726d48Sopenharmony_ci for (let thread of this.works) { 223fb726d48Sopenharmony_ci thread.worker!.terminate(); 224fb726d48Sopenharmony_ci } 225fb726d48Sopenharmony_ci this.works.length = 0; 226fb726d48Sopenharmony_ci }; 227fb726d48Sopenharmony_ci 228fb726d48Sopenharmony_ci clearCache = (): void => { 229fb726d48Sopenharmony_ci for (let thread of this.works) { 230fb726d48Sopenharmony_ci thread.queryFunc('clear', {}, undefined, () => {}); 231fb726d48Sopenharmony_ci } 232fb726d48Sopenharmony_ci }; 233fb726d48Sopenharmony_ci 234fb726d48Sopenharmony_ci submitWithName(name: string, type: string, args: unknown, transfer: unknown, handler: Function): unknown { 235fb726d48Sopenharmony_ci let noBusyThreads = this.works.filter((it) => it.name === name); 236fb726d48Sopenharmony_ci let thread: ProcedureThread | undefined; 237fb726d48Sopenharmony_ci if (noBusyThreads.length > 0) { 238fb726d48Sopenharmony_ci //取第一个空闲的线程进行任务 239fb726d48Sopenharmony_ci thread = noBusyThreads[0]; 240fb726d48Sopenharmony_ci thread!.queryFunc(type, args, transfer, handler); 241fb726d48Sopenharmony_ci } 242fb726d48Sopenharmony_ci return thread; 243fb726d48Sopenharmony_ci } 244fb726d48Sopenharmony_ci // @ts-ignore 245fb726d48Sopenharmony_ci submitWithNamePromise(name: string, type: string, args: unknown, transfer: unknown): Promise<unknown> { 246fb726d48Sopenharmony_ci return new Promise((resolve, reject) => { 247fb726d48Sopenharmony_ci let noBusyThreads = this.works.filter((it) => it.name === name); 248fb726d48Sopenharmony_ci let thread: ProcedureThread | undefined; 249fb726d48Sopenharmony_ci if (noBusyThreads.length > 0) { 250fb726d48Sopenharmony_ci //取第一个空闲的线程进行任务 251fb726d48Sopenharmony_ci thread = noBusyThreads[0]; // @ts-ignore 252fb726d48Sopenharmony_ci thread!.queryFunc(type, args, transfer, (res: unknown, hover: unknown) => { 253fb726d48Sopenharmony_ci resolve({ 254fb726d48Sopenharmony_ci res: res, 255fb726d48Sopenharmony_ci hover: hover, 256fb726d48Sopenharmony_ci }); 257fb726d48Sopenharmony_ci }); 258fb726d48Sopenharmony_ci } 259fb726d48Sopenharmony_ci }); 260fb726d48Sopenharmony_ci } 261fb726d48Sopenharmony_ci 262fb726d48Sopenharmony_ci isIdle(): boolean { 263fb726d48Sopenharmony_ci return this.works.every((it) => !it.busy); 264fb726d48Sopenharmony_ci } 265fb726d48Sopenharmony_ci} 266fb726d48Sopenharmony_ci 267fb726d48Sopenharmony_ciexport const procedurePool = new ProcedurePool(); 268