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 } from './SqlLite'; 17class ConvertThread { 18 isCancelled: boolean = false; 19 id: number = -1; 20 taskMap: any = {}; 21 name: string | undefined; 22 worker?: Worker; 23 busy: boolean = false; 24 constructor(worker: Worker) { 25 this.worker = worker; 26 } 27 uuid(): string { 28 // @ts-ignore 29 return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => 30 (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) 31 ); 32 } 33 34 getConvertData(handler: (status: boolean, msg: string, results: Blob) => void) { 35 this.busy = true; 36 let id = this.uuid(); 37 this.taskMap[id] = (res: any) => { 38 DbPool.sharedBuffer = res.buffer; 39 handler(res.status, res.msg, res.results); 40 }; 41 caches.match(DbPool.fileCacheKey).then((resData) => { 42 if (resData) { 43 resData.arrayBuffer().then((buffer) => { 44 this.worker!.postMessage( 45 { 46 id: id, 47 action: 'getConvertData', 48 buffer: buffer!, 49 }, 50 [buffer!] 51 ); 52 }); 53 } 54 }); 55 } 56} 57 58class ConvertPool { 59 maxThreadNumber: number = 0; 60 works: Array<ConvertThread> = []; 61 progress: Function | undefined | null; 62 static data: Array<string> = []; 63 num = Math.floor(Math.random() * 10 + 1) + 20; 64 init = async (type: string) => { 65 // server 66 await this.close(); 67 if (type === 'convert') { 68 this.maxThreadNumber = 1; 69 } 70 for (let i = 0; i < this.maxThreadNumber; i++) { 71 let thread: ConvertThread; 72 if (type === 'convert') { 73 thread = new ConvertThread(new Worker(new URL('./ConvertTraceWorker', import.meta.url))); 74 } 75 thread!.worker!.onmessage = (event: MessageEvent) => { 76 thread.busy = false; 77 ConvertPool.data = event.data.results; 78 if (Reflect.has(thread.taskMap, event.data.id)) { 79 if (event.data.results) { 80 let fun = thread.taskMap[event.data.id]; 81 if (fun) { 82 fun(event.data); 83 } 84 Reflect.deleteProperty(thread.taskMap, event.data.id); 85 } else { 86 let fun = thread.taskMap[event.data.id]; 87 if (fun) { 88 fun([]); 89 } 90 Reflect.deleteProperty(thread.taskMap, event.data.id); 91 } 92 } 93 }; 94 thread!.worker!.onmessageerror = (e) => {}; 95 thread!.worker!.onerror = (e) => {}; 96 thread!.id = i; 97 thread!.busy = false; 98 this.works?.push(thread!); 99 } 100 }; 101 102 clearCache = () => { 103 for (let i = 0; i < this.works.length; i++) { 104 let thread = this.works[i]; 105 thread.getConvertData(() => {}); 106 } 107 }; 108 109 close = () => { 110 for (let i = 0; i < this.works.length; i++) { 111 let thread = this.works[i]; 112 thread.worker!.terminate(); 113 } 114 this.works.length = 0; 115 }; 116 117 // @ts-ignore 118 submitWithName( 119 name: string, 120 handler: (status: boolean, msg: string, results: Blob) => void 121 ): ConvertThread | undefined { 122 let noBusyThreads = this.works; 123 let thread: ConvertThread | undefined; 124 if (noBusyThreads.length > 0) { 125 //取第一个空闲的线程进行任务 126 thread = noBusyThreads[0]; 127 thread!.getConvertData(handler); 128 } 129 return thread; 130 } 131 132 isIdle() { 133 return this.works.every((it) => !it.busy); 134 } 135} 136 137export const convertPool = new ConvertPool(); 138