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 WorkFactory, { WorkerType } from '../WorkFactory' 17import worker from '@ohos.worker'; 18import { HiLog } from '../../../../../../common' 19import buffer from '@ohos.buffer' 20 21const TAG = 'WorkerWrapper' 22 23export class WorkerMessage { 24 request: string; 25 callBackId: number; 26 type?: WorkerType; 27 param?: any; 28} 29 30/* 31 * WorkerWrapper 32 * 33 * Processes sending tasks to workers and receiving work processing results. 34 */ 35export default class WorkerWrapper { 36 protected mWorker: worker.ThreadWorker = undefined; 37 private callBacks: Map<string, (result?: any) => void> = new Map(); 38 private requestIndex: number = 0; 39 private workType: WorkerType; 40 private useWorker: boolean; 41 42 constructor(workType: WorkerType, useWorker: boolean) { 43 this.workType = workType; 44 this.useWorker = useWorker; 45 if (useWorker) { 46 this.initWorker(); 47 } 48 } 49 50 async initWorker() { 51 HiLog.i(TAG, `WorkerWrapper initWorker ${WorkerType[this.getWorkerType()]}`) 52 let initWorker = await new worker.ThreadWorker('entry/ets/workers/base/Worker.ts', { 53 name: WorkerType[this.getWorkerType()] 54 }); 55 let that = this; 56 initWorker.onexit = function (message) { 57 HiLog.w(TAG, 'onexit') 58 that.mWorker = undefined; 59 } 60 initWorker.onerror = function (e) { 61 HiLog.w(TAG, 'onerror:' + JSON.stringify(e)) 62 } 63 initWorker.onmessageerror = function (e) { 64 HiLog.w(TAG, 'onmessageerror:' + JSON.stringify(e)) 65 } 66 initWorker.onmessage = function (message) { 67 const buff = <ArrayBuffer> message.data; 68 const str = buffer.from(buff).toString(); 69 let data = <WorkerMessage> JSON.parse(str) 70 HiLog.i(TAG, `onmessage ${data.request}`) 71 const key = that.getCallBackKey(data); 72 if (that.callBacks.has(key)) { 73 HiLog.i(TAG, `onmessage notify result.`) 74 const callback = that.callBacks.get(key); 75 if (callback) { 76 callback(data.param); 77 } 78 that.callBacks.delete(key); 79 } 80 } 81 this.mWorker = initWorker; 82 HiLog.i(TAG, `WorkerWrapper initWorker end`) 83 } 84 85 public getWorkerType(): WorkerType { 86 return this.workType; 87 } 88 89 /** 90 * SendRequest to worker thread. 91 * 92 * @param {string} request the request worker to do 93 * @param {Object} requestData request param Data 94 * @param {Object} callBack Call back from worker 95 */ 96 public async sendRequest(request: string, requestData?: any, callBack?: (result?: any) => void) { 97 HiLog.i(TAG, 'sendRequest in ' + request) 98 if (!this.useWorker) { 99 WorkFactory.getTask(this.getWorkerType()).runInWorker(request, callBack, requestData); 100 } else if (this.mWorker) { 101 const message = { 102 request: request, 103 callBackId: this.requestIndex, 104 type: this.getWorkerType(), 105 param: requestData 106 } 107 if (callBack) { 108 this.callBacks.set(this.getCallBackKey(message), callBack); 109 } 110 this.mWorker?.postMessage(message); 111 HiLog.d(TAG, `${this.getWorkerType()} ${request} send succ!`); 112 this.requestIndex++; 113 } else { 114 HiLog.w(TAG, `${this.getWorkerType()} ${request} send fail, worker has been closed!`); 115 } 116 } 117 118 /** 119 * Close close worker thread. 120 */ 121 public close() { 122 HiLog.i(TAG, `${this.getWorkerType()} worker close!`); 123 this.mWorker?.terminate(); 124 this.mWorker = undefined; 125 this.callBacks.clear(); 126 } 127 128 private getCallBackKey(message: WorkerMessage): string { 129 return message.request + message.callBackId; 130 } 131} 132