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