• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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