1 /* 2 * Copyright (c) 2024 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 FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_UPDATE_CONFIG_MANAGER_H 17 #define FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_UPDATE_CONFIG_MANAGER_H 18 19 #include <mutex> 20 #include <string> 21 #include <thread> 22 23 #include "base/memory/ace_type.h" 24 #include "base/thread/cancelable_callback.h" 25 #include "base/thread/task_executor.h" 26 #include "core/common/container.h" 27 28 namespace OHOS::Ace { 29 template<class T> 30 class UpdateConfigManager : public virtual AceType { 31 DECLARE_ACE_TYPE(UpdateConfigManager<T>, AceType); 32 public: 33 struct UpdateTask { 34 CancelableCallback<void()> updateTask; 35 std::unordered_map<int32_t, CancelableCallback<void()>> promiseTaskMap; 36 T target; 37 }; 38 UpdateConfigSync(const T & config,std::function<void ()> && task)39 void UpdateConfigSync(const T& config, std::function<void()> &&task) 40 { 41 // Update current state 42 { 43 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 44 currentTask_.updateTask.Cancel(); 45 currentTask_.target = config; 46 } 47 48 task(); 49 } 50 UpdateViewConfigTaskDone(int32_t taskId)51 void UpdateViewConfigTaskDone(int32_t taskId) 52 { 53 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 54 currentTask_.promiseTaskMap.erase(taskId); 55 } 56 CancelAllPromiseTaskLocked()57 void CancelAllPromiseTaskLocked() 58 { 59 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 60 for (auto it = currentTask_.promiseTaskMap.begin(); it != currentTask_.promiseTaskMap.end();) { 61 it = it->second.Cancel() ? currentTask_.promiseTaskMap.erase(it) : ++it; 62 } 63 } 64 65 void UpdatePromiseConfig(const T& config, std::function<void()> &&task, const RefPtr<Container>& container, 66 int32_t taskId, const std::string& taskName, TaskExecutor::TaskType type = TaskExecutor::TaskType::PLATFORM) 67 { 68 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 69 CancelUselessTaskLocked(); 70 CancelableCallback<void()> promiseTask(std::move(task)); 71 currentTask_.promiseTaskMap[taskId] = promiseTask; 72 currentTask_.target = config; 73 74 auto taskExecutor = container->GetTaskExecutor(); 75 CHECK_NULL_VOID(taskExecutor); 76 taskExecutor->PostTask(std::move(promiseTask), type, taskName); 77 } 78 79 void UpdateConfig(const T& config, std::function<void()> &&task, const RefPtr<Container>& container, 80 const std::string& taskName, TaskExecutor::TaskType type = TaskExecutor::TaskType::PLATFORM) 81 { 82 CancelableCallback<void()> cancelableTask(std::move(task)); 83 84 std::lock_guard<std::mutex> taskLock(updateTaskMutex_); 85 if (config == currentTask_.target) { 86 // If config is same as current/next state, return directely. 87 return; 88 } else { 89 // Try to cancel useless task. 90 CancelUselessTaskLocked(); 91 // Post new task. 92 PostUpdateConfigTaskLocked(config, std::move(cancelableTask), container, taskName, type); 93 } 94 } 95 StoreConfig(T & config)96 void StoreConfig(T& config) 97 { 98 aceConfig_ = config; 99 } 100 IsConfigsEqual(const ViewportConfig & other)101 bool IsConfigsEqual(const ViewportConfig& other) 102 { 103 return aceConfig_.config_ == other; 104 } 105 MakeTaskId()106 int32_t MakeTaskId() 107 { 108 return nextTaskId_.fetch_add(1); 109 } 110 private: PostUpdateConfigTaskLocked(const T & config,CancelableCallback<void ()> && task,const RefPtr<Container> & container,const std::string & taskName,TaskExecutor::TaskType type)111 void PostUpdateConfigTaskLocked(const T& config, CancelableCallback<void()> &&task, 112 const RefPtr<Container>& container, const std::string& taskName, TaskExecutor::TaskType type) 113 { 114 currentTask_ = { 115 .updateTask = std::move(task), 116 .target = config, 117 }; 118 auto taskExecutor = container->GetTaskExecutor(); 119 CHECK_NULL_VOID(taskExecutor); 120 taskExecutor->PostTask(currentTask_.updateTask, type, taskName); 121 } 122 CancelUselessTaskLocked()123 void CancelUselessTaskLocked() 124 { 125 currentTask_.updateTask.Cancel(); 126 } 127 128 std::mutex updateTaskMutex_; 129 130 UpdateTask currentTask_; 131 132 std::atomic<int32_t> nextTaskId_ = 0; 133 134 T aceConfig_; 135 }; 136 } // OHOS::Ace 137 #endif // FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_UPDATE_CONFIG_MANAGER_H 138