1cb7eb8c9Sopenharmony_ci/* 2cb7eb8c9Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3cb7eb8c9Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cb7eb8c9Sopenharmony_ci * you may not use this file except in compliance with the License. 5cb7eb8c9Sopenharmony_ci * You may obtain a copy of the License at 6cb7eb8c9Sopenharmony_ci * 7cb7eb8c9Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cb7eb8c9Sopenharmony_ci * 9cb7eb8c9Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cb7eb8c9Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cb7eb8c9Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cb7eb8c9Sopenharmony_ci * See the License for the specific language governing permissions and 13cb7eb8c9Sopenharmony_ci * limitations under the License. 14cb7eb8c9Sopenharmony_ci */ 15cb7eb8c9Sopenharmony_ci#ifndef DFSU_THREAD_H 16cb7eb8c9Sopenharmony_ci#define DFSU_THREAD_H 17cb7eb8c9Sopenharmony_ci 18cb7eb8c9Sopenharmony_ci#include <atomic> 19cb7eb8c9Sopenharmony_ci#include <condition_variable> 20cb7eb8c9Sopenharmony_ci#include <functional> 21cb7eb8c9Sopenharmony_ci#include <mutex> 22cb7eb8c9Sopenharmony_ci#include <thread> 23cb7eb8c9Sopenharmony_ci#include "utils_log.h" 24cb7eb8c9Sopenharmony_ci 25cb7eb8c9Sopenharmony_cinamespace OHOS { 26cb7eb8c9Sopenharmony_cinamespace Storage { 27cb7eb8c9Sopenharmony_cinamespace DistributedFile { 28cb7eb8c9Sopenharmony_cinamespace Utils { 29cb7eb8c9Sopenharmony_ciclass DfsuThread { 30cb7eb8c9Sopenharmony_cipublic: 31cb7eb8c9Sopenharmony_ci DfsuThread() = default; 32cb7eb8c9Sopenharmony_ci DfsuThread(const DfsuThread &) = delete; 33cb7eb8c9Sopenharmony_ci DfsuThread &operator=(const DfsuThread &) = delete; 34cb7eb8c9Sopenharmony_ci 35cb7eb8c9Sopenharmony_ci ~DfsuThread() 36cb7eb8c9Sopenharmony_ci { 37cb7eb8c9Sopenharmony_ci Stop(); 38cb7eb8c9Sopenharmony_ci } 39cb7eb8c9Sopenharmony_ci 40cb7eb8c9Sopenharmony_ci template<class Fn, class... Args> 41cb7eb8c9Sopenharmony_ci bool Run(Fn &&Fx, Args &&...Ax) 42cb7eb8c9Sopenharmony_ci { 43cb7eb8c9Sopenharmony_ci std::unique_lock<std::mutex> lock(threadMutex_); 44cb7eb8c9Sopenharmony_ci if (thread_ != nullptr) { 45cb7eb8c9Sopenharmony_ci return false; 46cb7eb8c9Sopenharmony_ci } 47cb7eb8c9Sopenharmony_ci running_ = true; 48cb7eb8c9Sopenharmony_ci thread_ = std::make_unique<std::thread>(std::forward<Fn>(Fx), std::forward<Args>(Ax)...); 49cb7eb8c9Sopenharmony_ci return true; 50cb7eb8c9Sopenharmony_ci } 51cb7eb8c9Sopenharmony_ci 52cb7eb8c9Sopenharmony_ci bool RunLoop(std::function<bool()> task, uint64_t interval, uint32_t retryTimes = UINT32_MAX) 53cb7eb8c9Sopenharmony_ci { 54cb7eb8c9Sopenharmony_ci std::unique_lock<std::mutex> lock(threadMutex_); 55cb7eb8c9Sopenharmony_ci if (thread_ != nullptr) { 56cb7eb8c9Sopenharmony_ci return false; 57cb7eb8c9Sopenharmony_ci } 58cb7eb8c9Sopenharmony_ci running_ = true; 59cb7eb8c9Sopenharmony_ci thread_ = std::make_unique<std::thread>([this, task, interval, retryTimes] { 60cb7eb8c9Sopenharmony_ci uint32_t times = retryTimes; 61cb7eb8c9Sopenharmony_ci LOGD("DfsThread: entering loop"); 62cb7eb8c9Sopenharmony_ci while ((!task()) && (times > 0)) { 63cb7eb8c9Sopenharmony_ci times--; 64cb7eb8c9Sopenharmony_ci std::unique_lock<std::mutex> lock(sleepMutex_); 65cb7eb8c9Sopenharmony_ci bool stop = 66cb7eb8c9Sopenharmony_ci sleepCv_.wait_for(lock, std::chrono::milliseconds(interval), [this]() { return !this->running_; }); 67cb7eb8c9Sopenharmony_ci if (stop) { // is stopped 68cb7eb8c9Sopenharmony_ci break; 69cb7eb8c9Sopenharmony_ci } 70cb7eb8c9Sopenharmony_ci } 71cb7eb8c9Sopenharmony_ci LOGD("DfsThread: leaving loop"); 72cb7eb8c9Sopenharmony_ci }); 73cb7eb8c9Sopenharmony_ci return true; 74cb7eb8c9Sopenharmony_ci } 75cb7eb8c9Sopenharmony_ci 76cb7eb8c9Sopenharmony_ci bool RunLoopFlexible(std::function<bool(uint64_t &)> task, uint64_t interval, uint32_t retryTimes = UINT32_MAX) 77cb7eb8c9Sopenharmony_ci { 78cb7eb8c9Sopenharmony_ci std::unique_lock<std::mutex> lock(threadMutex_); 79cb7eb8c9Sopenharmony_ci if (thread_ != nullptr) { 80cb7eb8c9Sopenharmony_ci return false; 81cb7eb8c9Sopenharmony_ci } 82cb7eb8c9Sopenharmony_ci running_ = true; 83cb7eb8c9Sopenharmony_ci thread_ = std::make_unique<std::thread>([this, task, interval, retryTimes] { 84cb7eb8c9Sopenharmony_ci uint32_t times = retryTimes; 85cb7eb8c9Sopenharmony_ci uint64_t duration = interval; 86cb7eb8c9Sopenharmony_ci LOGD("DfsThread: entering flexible loop"); 87cb7eb8c9Sopenharmony_ci while ((!task(duration)) && (times > 0)) { 88cb7eb8c9Sopenharmony_ci times--; 89cb7eb8c9Sopenharmony_ci std::unique_lock<std::mutex> lock(sleepMutex_); 90cb7eb8c9Sopenharmony_ci bool stop = 91cb7eb8c9Sopenharmony_ci sleepCv_.wait_for(lock, std::chrono::milliseconds(duration), [this]() { return !this->running_; }); 92cb7eb8c9Sopenharmony_ci if (stop) { // is stopped 93cb7eb8c9Sopenharmony_ci break; 94cb7eb8c9Sopenharmony_ci } 95cb7eb8c9Sopenharmony_ci } 96cb7eb8c9Sopenharmony_ci LOGD("DfsThread: leaving flexible loop"); 97cb7eb8c9Sopenharmony_ci }); 98cb7eb8c9Sopenharmony_ci return true; 99cb7eb8c9Sopenharmony_ci } 100cb7eb8c9Sopenharmony_ci 101cb7eb8c9Sopenharmony_ci bool Stop() 102cb7eb8c9Sopenharmony_ci { 103cb7eb8c9Sopenharmony_ci std::unique_lock<std::mutex> lockThread(threadMutex_); 104cb7eb8c9Sopenharmony_ci if (thread_ == nullptr) { 105cb7eb8c9Sopenharmony_ci return true; 106cb7eb8c9Sopenharmony_ci } 107cb7eb8c9Sopenharmony_ci { 108cb7eb8c9Sopenharmony_ci std::unique_lock<std::mutex> lockSleep(sleepMutex_); 109cb7eb8c9Sopenharmony_ci running_ = false; 110cb7eb8c9Sopenharmony_ci sleepCv_.notify_one(); 111cb7eb8c9Sopenharmony_ci } 112cb7eb8c9Sopenharmony_ci LOGD("wait thread to stop"); 113cb7eb8c9Sopenharmony_ci if (thread_->joinable()) { 114cb7eb8c9Sopenharmony_ci thread_->join(); 115cb7eb8c9Sopenharmony_ci } 116cb7eb8c9Sopenharmony_ci thread_ = nullptr; 117cb7eb8c9Sopenharmony_ci return true; 118cb7eb8c9Sopenharmony_ci } 119cb7eb8c9Sopenharmony_ci 120cb7eb8c9Sopenharmony_ci bool operator==(std::thread::id id) 121cb7eb8c9Sopenharmony_ci { 122cb7eb8c9Sopenharmony_ci if (thread_ == nullptr) { 123cb7eb8c9Sopenharmony_ci return false; 124cb7eb8c9Sopenharmony_ci } 125cb7eb8c9Sopenharmony_ci return thread_->get_id() == id; 126cb7eb8c9Sopenharmony_ci } 127cb7eb8c9Sopenharmony_ci 128cb7eb8c9Sopenharmony_ciprivate: 129cb7eb8c9Sopenharmony_ci std::atomic_bool running_ {false}; 130cb7eb8c9Sopenharmony_ci std::mutex threadMutex_ {}; 131cb7eb8c9Sopenharmony_ci std::unique_ptr<std::thread> thread_ {nullptr}; 132cb7eb8c9Sopenharmony_ci std::mutex sleepMutex_ {}; 133cb7eb8c9Sopenharmony_ci std::condition_variable sleepCv_ {}; 134cb7eb8c9Sopenharmony_ci}; 135cb7eb8c9Sopenharmony_ci} // namespace Utils 136cb7eb8c9Sopenharmony_ci} // namespace DistributedFile 137cb7eb8c9Sopenharmony_ci} // namespace Storage 138cb7eb8c9Sopenharmony_ci} // namespace OHOS 139cb7eb8c9Sopenharmony_ci#endif // DFSU_THREAD_H