1fa7767c5Sopenharmony_ci/*
2fa7767c5Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3fa7767c5Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fa7767c5Sopenharmony_ci * you may not use this file except in compliance with the License.
5fa7767c5Sopenharmony_ci * You may obtain a copy of the License at
6fa7767c5Sopenharmony_ci *
7fa7767c5Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fa7767c5Sopenharmony_ci *
9fa7767c5Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fa7767c5Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fa7767c5Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fa7767c5Sopenharmony_ci * See the License for the specific language governing permissions and
13fa7767c5Sopenharmony_ci * limitations under the License.
14fa7767c5Sopenharmony_ci */
15fa7767c5Sopenharmony_ci
16fa7767c5Sopenharmony_ci#define HST_LOG_TAG "Thread"
17fa7767c5Sopenharmony_ci
18fa7767c5Sopenharmony_ci#include "osal/task/thread.h"
19fa7767c5Sopenharmony_ci#include "common/log.h"
20fa7767c5Sopenharmony_ci#include "osal/task/autolock.h"
21fa7767c5Sopenharmony_ci
22fa7767c5Sopenharmony_cinamespace {
23fa7767c5Sopenharmony_ciconstexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "Thread" };
24fa7767c5Sopenharmony_ci}
25fa7767c5Sopenharmony_ci
26fa7767c5Sopenharmony_cinamespace OHOS {
27fa7767c5Sopenharmony_cinamespace Media {
28fa7767c5Sopenharmony_ciThread::Thread(ThreadPriority priority) noexcept : id_(), name_(), priority_(priority), state_()
29fa7767c5Sopenharmony_ci{
30fa7767c5Sopenharmony_ci}
31fa7767c5Sopenharmony_ci
32fa7767c5Sopenharmony_ciThread::Thread(Thread&& other) noexcept
33fa7767c5Sopenharmony_ci{
34fa7767c5Sopenharmony_ci    *this = std::move(other);
35fa7767c5Sopenharmony_ci}
36fa7767c5Sopenharmony_ci
37fa7767c5Sopenharmony_ciThread& Thread::operator=(Thread&& other) noexcept
38fa7767c5Sopenharmony_ci{
39fa7767c5Sopenharmony_ci    if (this != &other) {
40fa7767c5Sopenharmony_ci        AutoLock lock(mutex_);
41fa7767c5Sopenharmony_ci        id_ = other.id_;
42fa7767c5Sopenharmony_ci        name_ = std::move(other.name_);
43fa7767c5Sopenharmony_ci        priority_ = other.priority_;
44fa7767c5Sopenharmony_ci        state_ = std::move(other.state_);
45fa7767c5Sopenharmony_ci    }
46fa7767c5Sopenharmony_ci    return *this;
47fa7767c5Sopenharmony_ci}
48fa7767c5Sopenharmony_ci
49fa7767c5Sopenharmony_ciThread::~Thread() noexcept
50fa7767c5Sopenharmony_ci{
51fa7767c5Sopenharmony_ci    if (isExistThread_.load()) {
52fa7767c5Sopenharmony_ci        pthread_join(id_, nullptr);
53fa7767c5Sopenharmony_ci    }
54fa7767c5Sopenharmony_ci}
55fa7767c5Sopenharmony_ci
56fa7767c5Sopenharmony_cibool Thread::HasThread() const noexcept
57fa7767c5Sopenharmony_ci{
58fa7767c5Sopenharmony_ci    AutoLock lock(mutex_);
59fa7767c5Sopenharmony_ci    return state_ != nullptr;
60fa7767c5Sopenharmony_ci}
61fa7767c5Sopenharmony_ci
62fa7767c5Sopenharmony_civoid Thread::SetName(const std::string& name)
63fa7767c5Sopenharmony_ci{
64fa7767c5Sopenharmony_ci    name_ = name;
65fa7767c5Sopenharmony_ci}
66fa7767c5Sopenharmony_ci
67fa7767c5Sopenharmony_cibool Thread::CreateThread(const std::function<void()>& func)
68fa7767c5Sopenharmony_ci{
69fa7767c5Sopenharmony_ci    {
70fa7767c5Sopenharmony_ci        AutoLock lock(mutex_);
71fa7767c5Sopenharmony_ci        state_ = std::make_unique<State>();
72fa7767c5Sopenharmony_ci        state_->func = func;
73fa7767c5Sopenharmony_ci        state_->name = name_;
74fa7767c5Sopenharmony_ci    }
75fa7767c5Sopenharmony_ci    pthread_attr_t attr;
76fa7767c5Sopenharmony_ci    pthread_attr_init(&attr);
77fa7767c5Sopenharmony_ci    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
78fa7767c5Sopenharmony_ci#ifdef OHOS_LITE
79fa7767c5Sopenharmony_ci    // Only OHOS_LITE can set inheritsched and schedpolicy.
80fa7767c5Sopenharmony_ci    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
81fa7767c5Sopenharmony_ci    pthread_attr_setschedpolicy(&attr, SCHED_RR);
82fa7767c5Sopenharmony_ci#endif
83fa7767c5Sopenharmony_ci    struct sched_param sched = {static_cast<int>(priority_)};
84fa7767c5Sopenharmony_ci    pthread_attr_setschedparam(&attr, &sched);
85fa7767c5Sopenharmony_ci#if defined(THREAD_STACK_SIZE) and THREAD_STACK_SIZE > 0
86fa7767c5Sopenharmony_ci    pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
87fa7767c5Sopenharmony_ci    MEDIA_LOG_I("thread stack size set to " PUBLIC_LOG_D32, THREAD_STACK_SIZE);
88fa7767c5Sopenharmony_ci#endif
89fa7767c5Sopenharmony_ci    int rtv = pthread_create(&id_, &attr, Thread::Run, this);
90fa7767c5Sopenharmony_ci    if (rtv == 0) {
91fa7767c5Sopenharmony_ci        MEDIA_LOG_D("thread " PUBLIC_LOG_S " create success", name_.c_str());
92fa7767c5Sopenharmony_ci        isExistThread_.store(true);
93fa7767c5Sopenharmony_ci        SetNameInternal();
94fa7767c5Sopenharmony_ci    } else {
95fa7767c5Sopenharmony_ci        AutoLock lock(mutex_);
96fa7767c5Sopenharmony_ci        if (state_ != nullptr) {
97fa7767c5Sopenharmony_ci            state_.reset();
98fa7767c5Sopenharmony_ci        }
99fa7767c5Sopenharmony_ci        MEDIA_LOG_E("thread create failed, name: " PUBLIC_LOG_S ", rtv: " PUBLIC_LOG_D32, name_.c_str(), rtv);
100fa7767c5Sopenharmony_ci    }
101fa7767c5Sopenharmony_ci    return rtv == 0;
102fa7767c5Sopenharmony_ci}
103fa7767c5Sopenharmony_ci
104fa7767c5Sopenharmony_cibool Thread::IsRunningInSelf()
105fa7767c5Sopenharmony_ci{
106fa7767c5Sopenharmony_ci    pthread_t tid = pthread_self();
107fa7767c5Sopenharmony_ci    AutoLock lock(mutex_);
108fa7767c5Sopenharmony_ci    return tid == id_;
109fa7767c5Sopenharmony_ci}
110fa7767c5Sopenharmony_ci
111fa7767c5Sopenharmony_civoid Thread::SetNameInternal()
112fa7767c5Sopenharmony_ci{
113fa7767c5Sopenharmony_ci    AutoLock lock(mutex_);
114fa7767c5Sopenharmony_ci    if (state_ && !name_.empty()) {
115fa7767c5Sopenharmony_ci        constexpr int threadNameMaxSize = 15;
116fa7767c5Sopenharmony_ci        if (name_.size() > threadNameMaxSize) {
117fa7767c5Sopenharmony_ci            MEDIA_LOG_W("task name " PUBLIC_LOG_S " exceed max size: " PUBLIC_LOG_D32,
118fa7767c5Sopenharmony_ci                        name_.c_str(), threadNameMaxSize);
119fa7767c5Sopenharmony_ci            name_ = name_.substr(0, threadNameMaxSize);
120fa7767c5Sopenharmony_ci        }
121fa7767c5Sopenharmony_ci        pthread_setname_np(id_, name_.c_str());
122fa7767c5Sopenharmony_ci    }
123fa7767c5Sopenharmony_ci}
124fa7767c5Sopenharmony_ci
125fa7767c5Sopenharmony_civoid* Thread::Run(void* arg) // NOLINT: void*
126fa7767c5Sopenharmony_ci{
127fa7767c5Sopenharmony_ci    std::function<void()> func;
128fa7767c5Sopenharmony_ci    std::string name;
129fa7767c5Sopenharmony_ci    {
130fa7767c5Sopenharmony_ci        auto currentThread = static_cast<Thread *>(arg);
131fa7767c5Sopenharmony_ci        AutoLock lock(currentThread->mutex_);
132fa7767c5Sopenharmony_ci        auto state = currentThread->state_.get();
133fa7767c5Sopenharmony_ci        if (state == nullptr) {
134fa7767c5Sopenharmony_ci            return nullptr;
135fa7767c5Sopenharmony_ci        }
136fa7767c5Sopenharmony_ci        func = state->func;
137fa7767c5Sopenharmony_ci        name = state->name;
138fa7767c5Sopenharmony_ci    }
139fa7767c5Sopenharmony_ci    func();
140fa7767c5Sopenharmony_ci    {
141fa7767c5Sopenharmony_ci        auto currentThread = static_cast<Thread *>(arg);
142fa7767c5Sopenharmony_ci        AutoLock lock(currentThread->mutex_);
143fa7767c5Sopenharmony_ci        currentThread->state_ = nullptr;
144fa7767c5Sopenharmony_ci    }
145fa7767c5Sopenharmony_ci    MEDIA_LOG_W("Thread " PUBLIC_LOG_S " exited...", name.c_str());
146fa7767c5Sopenharmony_ci    return nullptr;
147fa7767c5Sopenharmony_ci}
148fa7767c5Sopenharmony_ci} // namespace Media
149fa7767c5Sopenharmony_ci} // namespace OHOS
150