/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "platform/threadpool/include/thread.h" #include <thread> #include "platform/time/include/time.h" #include "platform/time/include/time_elapser.h" #include "protocol/retcode_inner/aie_retcode_inner.h" namespace OHOS { namespace AI { IWorker::IWorker() : counter_(0), thread_(nullptr), status_(IDLE) { } IWorker::~IWorker() { thread_ = nullptr; } unsigned long IWorker::GetThreadId() { CHK_RET(thread_ == nullptr, RETCODE_FAILURE); return thread_->GetThreadId(); } Thread::Thread() : running_(false), status_(STOPPED), stackSize_(THREAD_DEFAULT_STACK_SIZE), worker_(nullptr) { InitThread(thread_); } Thread::~Thread() { CHK_RET_NONE(worker_ == nullptr); worker_->SetThread(nullptr); worker_ = nullptr; } void Thread::SetStackSize(const size_t size) { stackSize_ = size; } Thread::ThreadStatus Thread::Status() const { return status_; } const IWorker *Thread::GetWorker() const { return worker_; } void Thread::SetWorker(IWorker *pWorker) { if (worker_ != nullptr) { worker_->SetThread(nullptr); } worker_ = pWorker; if (pWorker != nullptr) { pWorker->SetThread(this); } } bool Thread::StartThread() { if (status_ == RUNNING) { return false; } size_t stackSize = stackSize_; if (worker_ != nullptr && worker_->GetStackSize() > 0) { stackSize = worker_->GetStackSize(); } PthreadAttr attr; PthreadAttr *pattr = nullptr; if ((stackSize >= THREAD_MIN_STACK_SIZE) && (stackSize < THREAD_MAX_STACK_SIZE)) { (void)InitThreadAttr(attr); (void)SetThreadAttrStackSize(attr, stackSize); pattr = &attr; } status_ = PREPARED; int retCode = CreateOneThread(thread_, pattr, Thread::ThreadProc, this); if (retCode != 0) { status_ = STOPPED; return false; } while (status_ == PREPARED) { (void)StepSleepMs(THREAD_SLEEP_MS); } return true; } bool Thread::StartThread(IWorker *pWorker) { if (status_ == RUNNING) { return false; } if (pWorker == nullptr) { return false; } worker_ = pWorker; (void)pWorker->SetThread(this); return StartThread(); } void Thread::StopThread() { if (!IsActive()) { return; } running_ = false; while (status_ == RUNNING) { (void)StepSleepMs(THREAD_SLEEP_MS); } WaitForEnd(); } bool Thread::StopThread(int timeOut) { if (!IsActive()) { return true; } running_ = false; // if timeOut==0 means just set stop flag if (timeOut == 0) { return true; } TimeElapser elapser; while ((status_ == RUNNING) && (static_cast<int32_t>(elapser.ElapseMilli()) < timeOut)) { (void)StepSleepMs(THREAD_SLEEP_MS); } if (status_ == RUNNING) { return false; } WaitForEnd(); return true; } void Thread::Run() { if (worker_ == nullptr) { return; } IWorker *pWorker = worker_; if (!pWorker->Initialize()) { pWorker->Uninitialize(); return; } while (running_) { if (!pWorker->OneAction()) { break; } ++worker_->counter_; } status_ = STOPPED; pWorker->Uninitialize(); } bool Thread::IsActive() const { if (status_ == RUNNING) { return IsThreadRunning(GetThreadId()); } return false; } bool Thread::IsHung(time_t now) const { if (worker_ != nullptr) { return worker_->isHung(now); } return false; } unsigned long Thread::GetThreadId() const { return GetThreadIdUnix(thread_); } bool Thread::IsRunning() const { return running_; } void Thread::Execute() { running_ = true; status_ = RUNNING; Run(); status_ = STOPPED; } void Thread::WaitForEnd() { (void)WaitThread(thread_); } void *Thread::ThreadProc(void *pObj) { auto *pThis = reinterpret_cast<Thread*>(pObj); pThis->Execute(); auto retCode = RETCODE_SUCCESS; return (void*)retCode; } } // namespace AI } // namespace OHOS