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 LIBPANDABASE_TASKMANAGER_UTILS_WAIT_LIST_H 17 #define LIBPANDABASE_TASKMANAGER_UTILS_WAIT_LIST_H 18 19 #include "libpandabase/utils/time.h" 20 #include <atomic> 21 #include <functional> 22 #include <optional> 23 #include <list> 24 #include <memory> 25 #include <limits> 26 27 namespace ark::taskmanager { 28 29 using WaiterId = size_t; 30 inline constexpr WaiterId INVALID_WAITER_ID = 0U; 31 32 template <class T> 33 class WaitList { 34 class WaitValue { 35 public: WaitValue(T && value,uint64_t targetTime,size_t id)36 WaitValue(T &&value, uint64_t targetTime, size_t id) 37 : value_(std::move(value)), targetTime_(targetTime), id_(id) 38 { 39 } 40 DEFAULT_MOVE_SEMANTIC(WaitValue); 41 NO_COPY_SEMANTIC(WaitValue); 42 ~WaitValue() = default; 43 GetValue()44 T &&GetValue() 45 { 46 return std::move(value_); 47 } 48 GetValue()49 const T &GetValue() const 50 { 51 return value_; 52 } 53 GetTargetTime()54 uint64_t GetTargetTime() const 55 { 56 return targetTime_; 57 } 58 SetTargetTime(uint64_t newTargetTime)59 void SetTargetTime(uint64_t newTargetTime) 60 { 61 targetTime_ = newTargetTime; 62 } 63 GetId()64 WaiterId GetId() const 65 { 66 return id_; 67 } 68 69 private: 70 T value_; 71 uint64_t targetTime_; 72 WaiterId id_; 73 }; 74 75 public: 76 /** 77 * @returns value with targetTime less than or equal to current time. If such a value doesn't exist returns 78 * std::nullopt. 79 */ GetReadyValue()80 std::optional<T> GetReadyValue() 81 { 82 auto currentTime = time::GetCurrentTimeInMillis(true); 83 for (auto iter = waitList_.begin(); iter != waitList_.end(); iter = next(iter)) { 84 if (currentTime >= iter->GetTargetTime()) { 85 T value = iter->GetValue(); 86 waitList_.erase(iter); 87 return value; 88 } 89 } 90 return std::nullopt; 91 } 92 93 /// @returns true if there is a value with a targetTime less or equal to current time. Otherwise false. HaveReadyValue()94 bool HaveReadyValue() const 95 { 96 auto currentTime = time::GetCurrentTimeInMillis(true); 97 for (auto iter = waitList_.begin(); iter != waitList_.end(); iter = next(iter)) { 98 if (currentTime >= iter->GetTargetTime()) { 99 return true; 100 } 101 } 102 return false; 103 } 104 105 /// @brief adds value in waitQueues_ with timeToWait if it's setted. 106 WaiterId AddValueToWait(T value, uint64_t timeToWait = std::numeric_limits<uint64_t>().max()) 107 { 108 addCounter_++; 109 uint64_t currentTime = time::GetCurrentTimeInMillis(true); 110 uint64_t targetTime = 0; 111 112 // Check if we need to set max possible time 113 if (std::numeric_limits<uint64_t>().max() - timeToWait < currentTime) { 114 targetTime = std::numeric_limits<uint64_t>().max(); 115 } else { 116 targetTime = currentTime + timeToWait; 117 } 118 119 waitList_.emplace_back(std::move(value), targetTime, addCounter_); 120 return waitList_.back().GetId(); 121 } 122 123 /// @returns value with specified WaiterId. It it doesn't exists returns std::nullopt. GetValueById(WaiterId id)124 std::optional<T> GetValueById(WaiterId id) 125 { 126 auto waitValue = 127 std::find_if(waitList_.begin(), waitList_.end(), [id](const auto &value) { return value.GetId() == id; }); 128 if (waitValue == waitList_.end()) { 129 return std::nullopt; 130 } 131 auto val = waitValue->GetValue(); 132 waitList_.erase(waitValue); 133 return val; 134 } 135 136 private: 137 std::list<WaitValue> waitList_; 138 size_t addCounter_ = 0U; 139 }; 140 141 } // namespace ark::taskmanager 142 143 #endif // LIBPANDABASE_TASKMANAGER_UTILS_WAIT_LIST_H 144