1 /*
2 * Copyright (c) 2021-2021 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 #define HST_LOG_TAG "Thread"
17
18 #include "thread.h"
19 #include <new>
20 #include <type_traits>
21 #include "foundation/log.h"
22
23 namespace OHOS {
24 namespace Media {
25 namespace OSAL {
Thread(ThreadPriority priority)26 Thread::Thread(ThreadPriority priority) noexcept : id_(), name_(), priority_(priority), state_()
27 {
28 }
29
Thread(Thread && other)30 Thread::Thread(Thread&& other) noexcept
31 {
32 *this = std::move(other);
33 }
34
operator =(Thread && other)35 Thread& Thread::operator=(Thread&& other) noexcept
36 {
37 if (this != &other) {
38 id_ = other.id_;
39 name_ = std::move(other.name_);
40 priority_ = other.priority_;
41 state_ = std::move(other.state_);
42 }
43 return *this;
44 }
45
~Thread()46 Thread::~Thread() noexcept
47 {
48 if (state_) {
49 pthread_join(id_, nullptr);
50 }
51 }
52
HasThread() const53 bool Thread::HasThread() const noexcept
54 {
55 return state_ != nullptr;
56 }
57
SetName(const std::string & name)58 void Thread::SetName(const std::string& name)
59 {
60 name_ = name;
61 }
62
CreateThread(const std::function<void ()> & func)63 bool Thread::CreateThread(const std::function<void()>& func)
64 {
65 state_ = std::unique_ptr<State>(new State);
66 state_->func = func;
67 state_->name = name_;
68 pthread_attr_t attr;
69 pthread_attr_init(&attr);
70 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
71 #ifdef OHOS_LITE
72 // Only OHOS_LITE can set inheritsched and schedpolicy.
73 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
74 pthread_attr_setschedpolicy(&attr, SCHED_RR);
75 #endif
76 struct sched_param sched = {static_cast<int>(priority_)};
77 pthread_attr_setschedparam(&attr, &sched);
78 #if defined(THREAD_STACK_SIZE) and THREAD_STACK_SIZE > 0
79 pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
80 MEDIA_LOG_I("thread stack size set to " PUBLIC_LOG_D32, THREAD_STACK_SIZE);
81 #endif
82 int rtv = pthread_create(&id_, &attr, Thread::Run, state_.get());
83 if (rtv == 0) {
84 MEDIA_LOG_I("thread " PUBLIC_LOG_S " create success", name_.c_str());
85 SetNameInternal();
86 } else {
87 state_.reset();
88 MEDIA_LOG_E("thread create failed, name: " PUBLIC_LOG_S ", rtv: " PUBLIC_LOG_D32, name_.c_str(), rtv);
89 }
90 return rtv == 0;
91 }
92
SetNameInternal()93 void Thread::SetNameInternal()
94 {
95 #ifdef SUPPORT_PTHREAD_NAME
96 if (state_ && !name_.empty()) {
97 constexpr int threadNameMaxSize = 15;
98 if (name_.size() > threadNameMaxSize) {
99 MEDIA_LOG_W("task name " PUBLIC_LOG_S " exceed max size: " PUBLIC_LOG_D32,
100 name_.c_str(), threadNameMaxSize);
101 name_ = name_.substr(0, threadNameMaxSize);
102 }
103 pthread_setname_np(id_, name_.c_str());
104 }
105 #endif
106 }
107
Run(void * arg)108 void* Thread::Run(void* arg) // NOLINT: void*
109 {
110 auto state = static_cast<State*>(arg);
111 if (state && state->func) {
112 const std::string name = state->name;
113 state->func();
114 MEDIA_LOG_W("Thread " PUBLIC_LOG_S " exited...", name.c_str());
115 }
116 return nullptr;
117 }
118 } // namespace OSAL
119 } // namespace Media
120 } // namespace OHOS
121