1c29fa5a6Sopenharmony_ci/* 2c29fa5a6Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License. 5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at 6c29fa5a6Sopenharmony_ci * 7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8c29fa5a6Sopenharmony_ci * 9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and 13c29fa5a6Sopenharmony_ci * limitations under the License. 14c29fa5a6Sopenharmony_ci */ 15c29fa5a6Sopenharmony_ci 16c29fa5a6Sopenharmony_ci#include "delegate_tasks.h" 17c29fa5a6Sopenharmony_ci 18c29fa5a6Sopenharmony_ci#include <fcntl.h> 19c29fa5a6Sopenharmony_ci#include <sys/syscall.h> 20c29fa5a6Sopenharmony_ci#include <unistd.h> 21c29fa5a6Sopenharmony_ci 22c29fa5a6Sopenharmony_ci#include "error_multimodal.h" 23c29fa5a6Sopenharmony_ci#include "util.h" 24c29fa5a6Sopenharmony_ci 25c29fa5a6Sopenharmony_ci#undef MMI_LOG_DOMAIN 26c29fa5a6Sopenharmony_ci#define MMI_LOG_DOMAIN MMI_LOG_SERVER 27c29fa5a6Sopenharmony_ci#undef MMI_LOG_TAG 28c29fa5a6Sopenharmony_ci#define MMI_LOG_TAG "DelegateTasks" 29c29fa5a6Sopenharmony_ci 30c29fa5a6Sopenharmony_cinamespace OHOS { 31c29fa5a6Sopenharmony_cinamespace MMI { 32c29fa5a6Sopenharmony_civoid DelegateTasks::Task::ProcessTask() 33c29fa5a6Sopenharmony_ci{ 34c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 35c29fa5a6Sopenharmony_ci if (hasWaited_) { 36c29fa5a6Sopenharmony_ci MMI_HILOGE("Expired tasks will be discarded. id:%{public}d", id_); 37c29fa5a6Sopenharmony_ci return; 38c29fa5a6Sopenharmony_ci } 39c29fa5a6Sopenharmony_ci int32_t ret = fun_(); 40c29fa5a6Sopenharmony_ci std::string taskType = ((promise_ == nullptr) ? "Async" : "Sync"); 41c29fa5a6Sopenharmony_ci MMI_HILOGD("Process taskType:%{public}s, taskId:%{public}d, ret:%{public}d", taskType.c_str(), id_, ret); 42c29fa5a6Sopenharmony_ci if (!hasWaited_ && promise_ != nullptr) { 43c29fa5a6Sopenharmony_ci promise_->set_value(ret); 44c29fa5a6Sopenharmony_ci } 45c29fa5a6Sopenharmony_ci} 46c29fa5a6Sopenharmony_ci 47c29fa5a6Sopenharmony_ciDelegateTasks::~DelegateTasks() 48c29fa5a6Sopenharmony_ci{ 49c29fa5a6Sopenharmony_ci if (fds_[0] >= 0) { 50c29fa5a6Sopenharmony_ci close(fds_[0]); 51c29fa5a6Sopenharmony_ci fds_[0] = -1; 52c29fa5a6Sopenharmony_ci } 53c29fa5a6Sopenharmony_ci if (fds_[1] >= 0) { 54c29fa5a6Sopenharmony_ci close(fds_[1]); 55c29fa5a6Sopenharmony_ci fds_[1] = -1; 56c29fa5a6Sopenharmony_ci } 57c29fa5a6Sopenharmony_ci} 58c29fa5a6Sopenharmony_ci 59c29fa5a6Sopenharmony_cibool DelegateTasks::Init() 60c29fa5a6Sopenharmony_ci{ 61c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 62c29fa5a6Sopenharmony_ci if (pipe(fds_) == -1) { 63c29fa5a6Sopenharmony_ci MMI_HILOGE("The pipe create failed, errno:%{public}d", errno); 64c29fa5a6Sopenharmony_ci return false; 65c29fa5a6Sopenharmony_ci } 66c29fa5a6Sopenharmony_ci if (fcntl(fds_[0], F_SETFL, O_NONBLOCK) == -1) { 67c29fa5a6Sopenharmony_ci MMI_HILOGE("The fcntl read failed, errno:%{public}d", errno); 68c29fa5a6Sopenharmony_ci close(fds_[0]); 69c29fa5a6Sopenharmony_ci return false; 70c29fa5a6Sopenharmony_ci } 71c29fa5a6Sopenharmony_ci if (fcntl(fds_[1], F_SETFL, O_NONBLOCK) == -1) { 72c29fa5a6Sopenharmony_ci MMI_HILOGE("The fcntl write failed, errno:%{public}d", errno); 73c29fa5a6Sopenharmony_ci close(fds_[1]); 74c29fa5a6Sopenharmony_ci return false; 75c29fa5a6Sopenharmony_ci } 76c29fa5a6Sopenharmony_ci return true; 77c29fa5a6Sopenharmony_ci} 78c29fa5a6Sopenharmony_ci 79c29fa5a6Sopenharmony_civoid DelegateTasks::ProcessTasks() 80c29fa5a6Sopenharmony_ci{ 81c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 82c29fa5a6Sopenharmony_ci std::vector<TaskPtr> tasks; 83c29fa5a6Sopenharmony_ci PopPendingTaskList(tasks); 84c29fa5a6Sopenharmony_ci for (const auto &it : tasks) { 85c29fa5a6Sopenharmony_ci it->ProcessTask(); 86c29fa5a6Sopenharmony_ci } 87c29fa5a6Sopenharmony_ci} 88c29fa5a6Sopenharmony_ci 89c29fa5a6Sopenharmony_ciint32_t DelegateTasks::PostSyncTask(DTaskCallback callback) 90c29fa5a6Sopenharmony_ci{ 91c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 92c29fa5a6Sopenharmony_ci CHKPR(callback, ERROR_NULL_POINTER); 93c29fa5a6Sopenharmony_ci if (IsCallFromWorkerThread()) { 94c29fa5a6Sopenharmony_ci return callback(); 95c29fa5a6Sopenharmony_ci } 96c29fa5a6Sopenharmony_ci Promise promise; 97c29fa5a6Sopenharmony_ci Future future = promise.get_future(); 98c29fa5a6Sopenharmony_ci auto task = PostTask(callback, &promise); 99c29fa5a6Sopenharmony_ci CHKPR(task, ETASKS_POST_SYNCTASK_FAIL); 100c29fa5a6Sopenharmony_ci 101c29fa5a6Sopenharmony_ci static constexpr int32_t timeout = 3000; 102c29fa5a6Sopenharmony_ci std::chrono::milliseconds span(timeout); 103c29fa5a6Sopenharmony_ci auto res = future.wait_for(span); 104c29fa5a6Sopenharmony_ci task->SetWaited(); 105c29fa5a6Sopenharmony_ci if (res == std::future_status::timeout) { 106c29fa5a6Sopenharmony_ci MMI_HILOGE("Task timeout"); 107c29fa5a6Sopenharmony_ci return ETASKS_WAIT_TIMEOUT; 108c29fa5a6Sopenharmony_ci } else if (res == std::future_status::deferred) { 109c29fa5a6Sopenharmony_ci MMI_HILOGE("Task deferred"); 110c29fa5a6Sopenharmony_ci return ETASKS_WAIT_DEFERRED; 111c29fa5a6Sopenharmony_ci } 112c29fa5a6Sopenharmony_ci return future.get(); 113c29fa5a6Sopenharmony_ci} 114c29fa5a6Sopenharmony_ci 115c29fa5a6Sopenharmony_ciint32_t DelegateTasks::PostAsyncTask(DTaskCallback callback) 116c29fa5a6Sopenharmony_ci{ 117c29fa5a6Sopenharmony_ci CHKPR(callback, ERROR_NULL_POINTER); 118c29fa5a6Sopenharmony_ci if (IsCallFromWorkerThread()) { 119c29fa5a6Sopenharmony_ci return callback(); 120c29fa5a6Sopenharmony_ci } 121c29fa5a6Sopenharmony_ci CHKPR(PostTask(callback), ETASKS_POST_ASYNCTASK_FAIL); 122c29fa5a6Sopenharmony_ci return RET_OK; 123c29fa5a6Sopenharmony_ci} 124c29fa5a6Sopenharmony_ci 125c29fa5a6Sopenharmony_civoid DelegateTasks::PopPendingTaskList(std::vector<TaskPtr> &tasks) 126c29fa5a6Sopenharmony_ci{ 127c29fa5a6Sopenharmony_ci std::lock_guard<std::mutex> guard(mux_); 128c29fa5a6Sopenharmony_ci static constexpr int32_t onceProcessTaskLimit = 10; 129c29fa5a6Sopenharmony_ci for (int32_t count = 0; count < onceProcessTaskLimit; count++) { 130c29fa5a6Sopenharmony_ci if (tasks_.empty()) { 131c29fa5a6Sopenharmony_ci break; 132c29fa5a6Sopenharmony_ci } 133c29fa5a6Sopenharmony_ci auto task = tasks_.front(); 134c29fa5a6Sopenharmony_ci CHKPB(task); 135c29fa5a6Sopenharmony_ci RecoveryId(task->GetId()); 136c29fa5a6Sopenharmony_ci tasks.push_back(task->GetSharedPtr()); 137c29fa5a6Sopenharmony_ci tasks_.pop(); 138c29fa5a6Sopenharmony_ci } 139c29fa5a6Sopenharmony_ci} 140c29fa5a6Sopenharmony_ci 141c29fa5a6Sopenharmony_ciDelegateTasks::TaskPtr DelegateTasks::PostTask(DTaskCallback callback, Promise *promise) 142c29fa5a6Sopenharmony_ci{ 143c29fa5a6Sopenharmony_ci if (IsCallFromWorkerThread()) { 144c29fa5a6Sopenharmony_ci MMI_HILOGE("This interface cannot be called from a worker thread"); 145c29fa5a6Sopenharmony_ci return nullptr; 146c29fa5a6Sopenharmony_ci } 147c29fa5a6Sopenharmony_ci std::lock_guard<std::mutex> guard(mux_); 148c29fa5a6Sopenharmony_ci MMI_HILOGD("tasks_ size:%{public}d", static_cast<int32_t>(tasks_.size())); 149c29fa5a6Sopenharmony_ci static constexpr int32_t maxTasksLimit = 1000; 150c29fa5a6Sopenharmony_ci auto tsize = tasks_.size(); 151c29fa5a6Sopenharmony_ci if (tsize > maxTasksLimit) { 152c29fa5a6Sopenharmony_ci MMI_HILOGE("The task queue is full. size:%{public}zu, maxTasksLimit:%{public}d", tsize, maxTasksLimit); 153c29fa5a6Sopenharmony_ci return nullptr; 154c29fa5a6Sopenharmony_ci } 155c29fa5a6Sopenharmony_ci int32_t id = GenerateId(); 156c29fa5a6Sopenharmony_ci TaskData data = { GetThisThreadId(), id }; 157c29fa5a6Sopenharmony_ci auto res = write(fds_[1], &data, sizeof(data)); 158c29fa5a6Sopenharmony_ci if (res == -1) { 159c29fa5a6Sopenharmony_ci RecoveryId(id); 160c29fa5a6Sopenharmony_ci MMI_HILOGE("Pipe write failed, errno:%{public}d", errno); 161c29fa5a6Sopenharmony_ci return nullptr; 162c29fa5a6Sopenharmony_ci } 163c29fa5a6Sopenharmony_ci TaskPtr task = std::make_shared<Task>(id, callback, promise); 164c29fa5a6Sopenharmony_ci tasks_.push(task); 165c29fa5a6Sopenharmony_ci std::string taskType = ((promise == nullptr) ? "Async" : "Sync"); 166c29fa5a6Sopenharmony_ci MMI_HILOGD("Post taskType:%{public}s", taskType.c_str()); 167c29fa5a6Sopenharmony_ci return task->GetSharedPtr(); 168c29fa5a6Sopenharmony_ci} 169c29fa5a6Sopenharmony_ci} // namespace MMI 170c29fa5a6Sopenharmony_ci} // namespace OHOS