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