| /* |
| * Copyright 2018 The Cobalt Authors. All Rights Reserved. |
| * |
| * 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 "starboard/common/thread.h" |
| |
| #include "starboard/atomic.h" |
| #include "starboard/common/log.h" |
| #include "starboard/common/mutex.h" |
| #include "starboard/common/optional.h" |
| #include "starboard/common/semaphore.h" |
| |
| namespace starboard { |
| |
| struct Thread::Data { |
| std::string name_; |
| SbThread thread_ = kSbThreadInvalid; |
| atomic_bool started_; |
| atomic_bool join_called_; |
| Semaphore join_sema_; |
| optional<Thread::Options> options_; |
| }; |
| |
| Thread::Options::Options() |
| : stack_size(0), // Signal for default stack size. |
| priority_(kSbThreadNoPriority), |
| joinable(true) {} |
| |
| Thread::Thread(const std::string& name) { |
| d_.reset(new Thread::Data); |
| d_->name_ = name; |
| } |
| |
| Thread::~Thread() { |
| SB_DCHECK(d_->join_called_.load()) << "Join not called on thread."; |
| } |
| |
| void Thread::Start(const Options& options) { |
| SbThreadEntryPoint entry_point = ThreadEntryPoint; |
| |
| SB_DCHECK(!d_->started_.load()); |
| SB_DCHECK(!d_->options_.has_engaged()); |
| d_->started_.store(true); |
| d_->options_ = options; |
| |
| d_->thread_ = SbThreadCreate(options.stack_size, |
| options.priority_, |
| kSbThreadNoAffinity, // default affinity. |
| options.joinable, |
| d_->name_.c_str(), |
| entry_point, |
| this); |
| |
| // SbThreadCreate() above produced an invalid thread handle. |
| SB_DCHECK(d_->thread_ != kSbThreadInvalid); |
| } |
| |
| void Thread::Sleep(SbTime microseconds) { |
| SbThreadSleep(microseconds); |
| } |
| |
| void Thread::SleepMilliseconds(int value) { |
| return Sleep(value * kSbTimeMillisecond); |
| } |
| |
| bool Thread::WaitForJoin(SbTime timeout) { |
| bool joined = d_->join_sema_.TakeWait(timeout); |
| if (joined) { |
| SB_DCHECK(d_->join_called_.load()); |
| } |
| return joined; |
| } |
| |
| starboard::Semaphore* Thread::join_sema() { |
| return &d_->join_sema_; |
| } |
| |
| starboard::atomic_bool* Thread::joined_bool() { |
| return &d_->join_called_; |
| } |
| |
| void* Thread::ThreadEntryPoint(void* context) { |
| Thread* this_ptr = static_cast<Thread*>(context); |
| this_ptr->Run(); |
| return NULL; |
| } |
| |
| void Thread::Join() { |
| SB_DCHECK(d_->join_called_.load() == false); |
| SB_DCHECK(d_->options_->joinable) |
| << "Detached thread should not be joined."; |
| |
| d_->join_called_.store(true); |
| d_->join_sema_.Put(); |
| |
| if (!SbThreadJoin(d_->thread_, NULL)) { |
| SB_DCHECK(false) << "Could not join thread."; |
| } |
| } |
| |
| bool Thread::join_called() const { |
| return d_->join_called_.load(); |
| } |
| |
| } // namespace starboard |