1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { DbPool, getThreadPoolTraceBufferCacheKey, setThreadPoolTraceBuffer } from './SqlLite'; 17 18class ConvertThread { 19 isCancelled: boolean = false; 20 id: number = -1; 21 taskMap: unknown = {}; 22 name: string | undefined; 23 worker?: Worker; 24 busy: boolean = false; 25 constructor(worker: Worker) { 26 this.worker = worker; 27 } 28 uuid(): string { 29 // @ts-ignore 30 return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => 31 (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) 32 ); 33 } 34 35 getConvertData(handler: (status: boolean, msg: string, results: Blob) => void): void { 36 this.busy = true; 37 let id = this.uuid(); 38 // @ts-ignore 39 this.taskMap[id] = (res: unknown): void => { 40 // @ts-ignore 41 setThreadPoolTraceBuffer('1', res.buffer); 42 // @ts-ignore 43 handler(res.status, res.msg, res.results); 44 }; 45 caches.match(getThreadPoolTraceBufferCacheKey('1')).then((resData) => { 46 if (resData) { 47 resData.arrayBuffer().then((buffer) => { 48 this.worker!.postMessage( 49 { 50 id: id, 51 action: 'getConvertData', 52 buffer: buffer!, 53 }, 54 [buffer!] 55 ); 56 }); 57 } 58 }); 59 } 60} 61 62class ConvertPool { 63 maxThreadNumber: number = 0; 64 works: Array<ConvertThread> = []; 65 progress: Function | undefined | null; 66 static data: Array<string> = []; 67 num = Math.floor(Math.random() * 10 + 1) + 20; 68 init = async (type: string): Promise<void> => { 69 // server 70 await this.close(); 71 if (type === 'convert') { 72 this.maxThreadNumber = 1; 73 } 74 for (let i = 0; i < this.maxThreadNumber; i++) { 75 let thread: ConvertThread; 76 if (type === 'convert') { 77 thread = new ConvertThread(new Worker(new URL('./ConvertTraceWorker', import.meta.url))); 78 } 79 thread!.worker!.onmessage = (event: MessageEvent): void => { 80 thread.busy = false; 81 ConvertPool.data = event.data.results; 82 // @ts-ignore 83 if (Reflect.has(thread.taskMap, event.data.id)) { 84 if (event.data.results) { 85 // @ts-ignore 86 let fun = thread.taskMap[event.data.id]; 87 if (fun) { 88 fun(event.data); 89 } 90 // @ts-ignore 91 Reflect.deleteProperty(thread.taskMap, event.data.id); 92 } else { 93 // @ts-ignore 94 let fun = thread.taskMap[event.data.id]; 95 if (fun) { 96 fun([]); 97 } 98 // @ts-ignore 99 Reflect.deleteProperty(thread.taskMap, event.data.id); 100 } 101 } 102 }; 103 thread!.worker!.onmessageerror = (e): void => {}; 104 thread!.worker!.onerror = (e): void => {}; 105 thread!.id = i; 106 thread!.busy = false; 107 this.works?.push(thread!); 108 } 109 }; 110 111 clearCache = (): void => { 112 for (let i = 0; i < this.works.length; i++) { 113 let thread = this.works[i]; 114 thread.getConvertData(() => {}); 115 } 116 }; 117 118 close = async (): Promise<void> => { 119 for (let i = 0; i < this.works.length; i++) { 120 let thread = this.works[i]; 121 thread.worker!.terminate(); 122 } 123 this.works.length = 0; 124 }; 125 126 // @ts-ignore 127 submitWithName( 128 name: string, 129 handler: (status: boolean, msg: string, results: Blob) => void 130 ): ConvertThread | undefined { 131 let noBusyThreads = this.works; 132 let thread: ConvertThread | undefined; 133 if (noBusyThreads.length > 0) { 134 //取第一个空闲的线程进行任务 135 thread = noBusyThreads[0]; 136 thread!.getConvertData(handler); 137 } 138 return thread; 139 } 140 141 isIdle(): boolean { 142 return this.works.every((it) => !it.busy); 143 } 144} 145 146export const convertPool = new ConvertPool(); 147