blob: 0dc0e4e2ffd4d690be12cc87e9bbdbf6bb7dd5ae [file] [log] [blame]
/*
* 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