1/*
2 * Copyright (c) 2023 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#include "base_queue.h"
17#include "dfx/log/ffrt_log_api.h"
18#include "tm/queue_task.h"
19#include "serial_queue.h"
20#include "concurrent_queue.h"
21#include "eventhandler_adapter_queue.h"
22#include "eventhandler_interactive_queue.h"
23
24namespace {
25using CreateFunc = std::unique_ptr<ffrt::BaseQueue>(*)(const ffrt_queue_attr_t*);
26const std::unordered_map<int, CreateFunc> CREATE_FUNC_MAP = {
27    { ffrt_queue_serial, ffrt::CreateSerialQueue },
28    { ffrt_queue_concurrent, ffrt::CreateConcurrentQueue },
29    { ffrt_queue_eventhandler_interactive, ffrt::CreateEventHandlerInteractiveQueue },
30    { ffrt_queue_eventhandler_adapter, ffrt::CreateEventHandlerAdapterQueue },
31};
32}
33
34namespace ffrt {
35// 0预留为非法值
36std::atomic_uint32_t BaseQueue::queueId(1);
37void BaseQueue::Stop()
38{
39    std::unique_lock lock(mutex_);
40    isExit_ = true;
41
42    ClearWhenMap();
43
44    FFRT_LOGI("clear [queueId=%u] succ", queueId_);
45}
46
47void BaseQueue::Remove()
48{
49    std::unique_lock lock(mutex_);
50    FFRT_COND_DO_ERR(isExit_, return, "cannot remove task, [queueId=%u] is exiting", queueId_);
51
52    ClearWhenMap();
53
54    FFRT_LOGD("cancel [queueId=%u] all tasks succ", queueId_);
55}
56
57int BaseQueue::Remove(const char* name)
58{
59    std::unique_lock lock(mutex_);
60    FFRT_COND_DO_ERR(isExit_, return FAILED, "cannot remove task, [queueId=%u] is exiting", queueId_);
61
62    int removedCount = 0;
63    for (auto iter = whenMap_.begin(); iter != whenMap_.end();) {
64        if (iter->second->IsMatch(name)) {
65            FFRT_LOGD("cancel task[%llu] %s succ", iter->second->gid, iter->second->label.c_str());
66            iter->second->Notify();
67            iter->second->Destroy();
68            iter = whenMap_.erase(iter);
69            removedCount++;
70        } else {
71            ++iter;
72        }
73    }
74
75    return removedCount > 0 ? SUCC : FAILED;
76}
77
78int BaseQueue::Remove(const QueueTask* task)
79{
80    std::unique_lock lock(mutex_);
81    FFRT_COND_DO_ERR(isExit_, return FAILED, "cannot remove task, [queueId=%u] is exiting", queueId_);
82
83    auto range = whenMap_.equal_range(task->GetUptime());
84    for (auto it = range.first; it != range.second; it++) {
85        if (it->second == task) {
86            whenMap_.erase(it);
87            return SUCC;
88        }
89    }
90
91    return FAILED;
92}
93
94bool BaseQueue::HasTask(const char* name)
95{
96    std::unique_lock lock(mutex_);
97    auto iter = std::find_if(whenMap_.cbegin(), whenMap_.cend(),
98        [name](const auto& pair) { return pair.second->IsMatch(name); });
99    return iter != whenMap_.cend();
100}
101
102void BaseQueue::PrintMutexOwner()
103{
104    MutexOwnerType type = mutex_.GetOwnerType();
105    if (type == MutexOwnerType::MUTEX_OWNER_TYPE_TASK) {
106        FFRT_LOGI("In queue %u, task %llu owns the lock for %llu us.",
107            queueId_, mutex_.GetOwnerId(), mutex_.GetDuration());
108    } else {
109        FFRT_LOGI("In queue %u, thread %llu owns the lock for %llu us.",
110            queueId_, mutex_.GetOwnerId(), mutex_.GetDuration());
111    }
112}
113
114void BaseQueue::ClearWhenMap()
115{
116    for (auto it = whenMap_.begin(); it != whenMap_.end(); it++) {
117        if (it->second) {
118            it->second->Notify();
119            it->second->Destroy();
120            it->second = nullptr;
121        }
122    }
123    whenMap_.clear();
124    cond_.NotifyOne();
125}
126
127std::unique_ptr<BaseQueue> CreateQueue(int queueType, const ffrt_queue_attr_t* attr)
128{
129    const auto iter = CREATE_FUNC_MAP.find(queueType);
130    FFRT_COND_DO_ERR((iter == CREATE_FUNC_MAP.end()), return nullptr, "invalid queue type");
131
132    return iter->second(attr);
133}
134} // namespace ffrt
135