1 /*
2 * Copyright (c) 2025 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_TASK_QUEUE_SET_H
17 #define LIBPANDABASE_TASKMANAGER_TASK_QUEUE_SET_H
18
19 #include <queue>
20 #include "libpandabase/taskmanager/task_queue.h"
21
22 namespace ark::taskmanager::internal {
23
24 class TaskScheduler;
25
26 class TaskQueueSet {
27 public:
28 explicit TaskQueueSet(TaskWaitList *waitList,
29 TaskTimeStatsType taskTimeStatsType = TaskTimeStatsType::NO_STATISTICS);
30 ~TaskQueueSet();
31 NO_COPY_SEMANTIC(TaskQueueSet);
32 NO_MOVE_SEMANTIC(TaskQueueSet);
33
34 template <class Allocator>
35 TaskQueueInterface *CreateQueue(QueuePriority priority);
36 template <class Allocator>
37 void DeleteQueue(TaskQueueInterface *queue);
38 TaskQueueInterface *GetQueue(QueueId id);
39 TaskQueueInterface *SelectQueue();
40 bool AreQueuesEmpty() const;
41 size_t GetCountOfLiveTasks() const;
42
SetCallbacks(std::function<void ()> signalWorkersCallback)43 void SetCallbacks(std::function<void()> signalWorkersCallback)
44 {
45 signalWorkersCallback_ = std::move(signalWorkersCallback);
46 }
47 TaskTimeStatsBase *GetTaskTimeStats() const;
48
49 private:
50 TaskWaitList *waitList_ = nullptr;
51 std::function<void()> signalWorkersCallback_;
52 std::function<void()> signalWaitersCallback_;
53 TaskTimeStatsBase *taskTimeStats_ = nullptr;
54 std::atomic_size_t selectionIndex_ {0};
55 std::array<std::atomic<TaskQueueInterface *>, MAX_COUNT_OF_QUEUE> queues_ {};
56 std::queue<std::function<void()>> deleterQueue_;
57 };
58
59 template <class Allocator>
60 // CC-OFFNXT(G.FUD.06) Splitting this function will degrade readability. Keyword "inline" needs to satisfy ODR rule.
CreateQueue(QueuePriority priority)61 inline TaskQueueInterface *TaskQueueSet::CreateQueue(QueuePriority priority)
62 {
63 size_t i = 0;
64 auto *queue = internal::TaskQueue<Allocator>::Create(priority, waitList_, taskTimeStats_);
65 while (i != MAX_COUNT_OF_QUEUE) {
66 for (i = 0; i < MAX_COUNT_OF_QUEUE; i++) {
67 // Atomic with relaxed order reason: no order dependency with another variables
68 if (queues_[i].load(std::memory_order_relaxed) != nullptr) {
69 continue;
70 }
71 TaskQueueInterface *nullp = nullptr;
72 // Atomic with relaxed order reason: no order dependency with another variables
73 if (!queues_[i].compare_exchange_weak(nullp, queue, std::memory_order_relaxed)) {
74 break;
75 }
76 queue->Register(i);
77 ASSERT(signalWorkersCallback_ != nullptr);
78 queue->SetCallbacks(signalWorkersCallback_);
79 return queue;
80 }
81 }
82 internal::TaskQueue<Allocator>::Destroy(queue);
83 return nullptr;
84 }
85
86 template <class Allocator>
DeleteQueue(TaskQueueInterface * queue)87 inline void TaskQueueSet::DeleteQueue(TaskQueueInterface *queue)
88 {
89 while (!queue->IsEmpty()) {
90 queue->ExecuteTask();
91 }
92 queue->WaitTasks();
93 auto id = queue->GetQueueId();
94 // Atomic with relaxed order reason: no order dependency with another variables
95 ASSERT(queues_[id].load(std::memory_order_relaxed) == queue);
96 // Atomic with relaxed order reason: no order dependency with another variables
97 queues_[id].store(nullptr, std::memory_order_relaxed);
98 deleterQueue_.push([queue] {
99 internal::TaskQueue<Allocator>::Destroy(static_cast<internal::SchedulableTaskQueueInterface *>(queue));
100 });
101 }
102
103 } // namespace ark::taskmanager::internal
104
105 #endif // LIBPANDABASE_TASKMANAGER_TASK_QUEUE_SET_H
106