1 /* 2 * Copyright (c) 2021 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 16 #ifndef ECMASCRIPT_TASKPOOL_RUNNER_H 17 #define ECMASCRIPT_TASKPOOL_RUNNER_H 18 19 #include <array> 20 #include <memory> 21 #include <thread> 22 #include <vector> 23 #include <functional> 24 25 #include "ecmascript/common.h" 26 #include "ecmascript/taskpool/task_queue.h" 27 #include "ecmascript/platform/mutex.h" 28 #include "libpandabase/os/thread.h" 29 30 namespace panda::ecmascript { 31 static constexpr uint32_t MIN_TASKPOOL_THREAD_NUM = 3; 32 static constexpr uint32_t MAX_TASKPOOL_THREAD_NUM = 5; 33 static constexpr uint32_t DEFAULT_TASKPOOL_THREAD_NUM = 0; 34 35 enum class PriorityMode { 36 STW, 37 FOREGROUND, 38 BACKGROUND 39 }; 40 41 class Runner { 42 public: 43 explicit Runner(uint32_t threadNum, 44 const std::function<void(os::thread::native_handle_type)> prologueHook, 45 const std::function<void(os::thread::native_handle_type)> epilogueHook); 46 ~Runner() = default; 47 48 NO_COPY_SEMANTIC(Runner); 49 NO_MOVE_SEMANTIC(Runner); 50 PostTask(std::unique_ptr<Task> task)51 void PostTask(std::unique_ptr<Task> task) 52 { 53 taskQueue_.PostTask(std::move(task)); 54 } 55 56 void PUBLIC_API TerminateThread(); 57 void TerminateTask(int32_t id, TaskType type); 58 void SetQosPriority(PriorityMode mode); 59 void RecordThreadId(); 60 GetTotalThreadNum() const61 uint32_t GetTotalThreadNum() const 62 { 63 return totalThreadNum_; 64 } 65 IsInThreadPool(std::thread::id id)66 bool IsInThreadPool(std::thread::id id) 67 { 68 LockHolder holder(mtxPool_); 69 for (auto &thread : threadPool_) { 70 if (thread->get_id() == id) { 71 return true; 72 } 73 } 74 return false; 75 } 76 PrologueHook(os::thread::native_handle_type thread)77 void PrologueHook(os::thread::native_handle_type thread) 78 { 79 if (prologueHook_ != nullptr) { 80 prologueHook_(thread); 81 } 82 } EpilogueHook(os::thread::native_handle_type thread)83 void EpilogueHook(os::thread::native_handle_type thread) 84 { 85 if (epilogueHook_ != nullptr) { 86 epilogueHook_(thread); 87 } 88 } 89 void ForEachTask(const std::function<void(Task*)> &f); 90 91 private: 92 void Run(uint32_t threadId); 93 void SetRunTask(uint32_t threadId, Task *task); 94 95 std::vector<std::unique_ptr<std::thread>> threadPool_ {}; 96 TaskQueue taskQueue_ {}; 97 std::array<Task*, MAX_TASKPOOL_THREAD_NUM + 1> runningTask_; 98 uint32_t totalThreadNum_ {0}; 99 std::vector<uint32_t> gcThreadId_ {}; 100 Mutex mtx_; 101 Mutex mtxPool_; 102 103 std::function<void(os::thread::native_handle_type)> prologueHook_; 104 std::function<void(os::thread::native_handle_type)> epilogueHook_; 105 }; 106 } // namespace panda::ecmascript 107 #endif // ECMASCRIPT_TASKPOOL_RUNNER_H 108