[threading linux] Wait for thread start
This commit is contained in:
parent
b91203a0b5
commit
b2912e7891
|
@ -435,8 +435,18 @@ struct ThreadStartData {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class PosixCondition<Thread> : public PosixConditionBase {
|
class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
|
enum class State {
|
||||||
|
kUninitialized,
|
||||||
|
kRunning,
|
||||||
|
kFinished,
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PosixCondition() : thread_(0), signaled_(false), exit_code_(0) {}
|
PosixCondition()
|
||||||
|
: thread_(0),
|
||||||
|
signaled_(false),
|
||||||
|
exit_code_(0),
|
||||||
|
state_(State::kUninitialized) {}
|
||||||
bool Initialize(Thread::CreationParameters params,
|
bool Initialize(Thread::CreationParameters params,
|
||||||
ThreadStartData* start_data) {
|
ThreadStartData* start_data) {
|
||||||
assert_false(params.create_suspended);
|
assert_false(params.create_suspended);
|
||||||
|
@ -468,7 +478,10 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
/// Constructor for existing thread. This should only happen once called by
|
/// Constructor for existing thread. This should only happen once called by
|
||||||
/// Thread::GetCurrentThread() on the main thread
|
/// Thread::GetCurrentThread() on the main thread
|
||||||
explicit PosixCondition(pthread_t thread)
|
explicit PosixCondition(pthread_t thread)
|
||||||
: thread_(thread), signaled_(false), exit_code_(0) {}
|
: thread_(thread),
|
||||||
|
signaled_(false),
|
||||||
|
exit_code_(0),
|
||||||
|
state_(State::kRunning) {}
|
||||||
|
|
||||||
virtual ~PosixCondition() {
|
virtual ~PosixCondition() {
|
||||||
if (thread_ && !signaled_) {
|
if (thread_ && !signaled_) {
|
||||||
|
@ -482,20 +495,29 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name() const {
|
std::string name() const {
|
||||||
|
WaitStarted();
|
||||||
auto result = std::array<char, 17>{'\0'};
|
auto result = std::array<char, 17>{'\0'};
|
||||||
if (pthread_getname_np(thread_, result.data(), result.size() - 1) != 0)
|
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||||
assert_always();
|
if (state_ != State::kUninitialized && state_ != State::kFinished) {
|
||||||
|
if (pthread_getname_np(thread_, result.data(), result.size() - 1) != 0)
|
||||||
|
assert_always();
|
||||||
|
}
|
||||||
return std::string(result.data());
|
return std::string(result.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_name(const std::string& name) {
|
void set_name(const std::string& name) {
|
||||||
threading::set_name(static_cast<std::thread::native_handle_type>(thread_),
|
WaitStarted();
|
||||||
name);
|
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||||
|
if (state_ != State::kUninitialized && state_ != State::kFinished) {
|
||||||
|
threading::set_name(static_cast<std::thread::native_handle_type>(thread_),
|
||||||
|
name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t system_id() const { return static_cast<uint32_t>(thread_); }
|
uint32_t system_id() const { return static_cast<uint32_t>(thread_); }
|
||||||
|
|
||||||
uint64_t affinity_mask() {
|
uint64_t affinity_mask() {
|
||||||
|
WaitStarted();
|
||||||
cpu_set_t cpu_set;
|
cpu_set_t cpu_set;
|
||||||
if (pthread_getaffinity_np(thread_, sizeof(cpu_set_t), &cpu_set) != 0)
|
if (pthread_getaffinity_np(thread_, sizeof(cpu_set_t), &cpu_set) != 0)
|
||||||
assert_always();
|
assert_always();
|
||||||
|
@ -509,6 +531,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_affinity_mask(uint64_t mask) {
|
void set_affinity_mask(uint64_t mask) {
|
||||||
|
WaitStarted();
|
||||||
cpu_set_t cpu_set;
|
cpu_set_t cpu_set;
|
||||||
CPU_ZERO(&cpu_set);
|
CPU_ZERO(&cpu_set);
|
||||||
for (auto i = 0u; i < 64; i++) {
|
for (auto i = 0u; i < 64; i++) {
|
||||||
|
@ -522,6 +545,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
int priority() {
|
int priority() {
|
||||||
|
WaitStarted();
|
||||||
int policy;
|
int policy;
|
||||||
sched_param param{};
|
sched_param param{};
|
||||||
int ret = pthread_getschedparam(thread_, &policy, ¶m);
|
int ret = pthread_getschedparam(thread_, &policy, ¶m);
|
||||||
|
@ -533,6 +557,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_priority(int new_priority) {
|
void set_priority(int new_priority) {
|
||||||
|
WaitStarted();
|
||||||
sched_param param{};
|
sched_param param{};
|
||||||
param.sched_priority = new_priority;
|
param.sched_priority = new_priority;
|
||||||
if (pthread_setschedparam(thread_, SCHED_FIFO, ¶m) != 0)
|
if (pthread_setschedparam(thread_, SCHED_FIFO, ¶m) != 0)
|
||||||
|
@ -557,6 +582,11 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminate(int exit_code) {
|
void Terminate(int exit_code) {
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||||
|
state_ = State::kFinished;
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
// Sometimes the thread can call terminate twice before stopping
|
// Sometimes the thread can call terminate twice before stopping
|
||||||
|
@ -570,6 +600,12 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
if (pthread_cancel(thread) != 0) assert_always();
|
if (pthread_cancel(thread) != 0) assert_always();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaitStarted() const {
|
||||||
|
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||||
|
state_signal_.wait(lock,
|
||||||
|
[this] { return state_ != State::kUninitialized; });
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void* ThreadStartRoutine(void* parameter);
|
static void* ThreadStartRoutine(void* parameter);
|
||||||
inline bool signaled() const override { return signaled_; }
|
inline bool signaled() const override { return signaled_; }
|
||||||
|
@ -582,6 +618,9 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
pthread_t thread_;
|
pthread_t thread_;
|
||||||
bool signaled_;
|
bool signaled_;
|
||||||
int exit_code_;
|
int exit_code_;
|
||||||
|
State state_;
|
||||||
|
mutable std::mutex state_mutex_;
|
||||||
|
mutable std::condition_variable state_signal_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This wraps a condition object as our handle because posix has no single
|
// This wraps a condition object as our handle because posix has no single
|
||||||
|
@ -752,6 +791,7 @@ class PosixThread : public PosixConditionHandle<Thread> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_name(std::string name) override {
|
void set_name(std::string name) override {
|
||||||
|
handle_.WaitStarted();
|
||||||
Thread::set_name(name);
|
Thread::set_name(name);
|
||||||
if (name.length() > 15) {
|
if (name.length() > 15) {
|
||||||
name = name.substr(0, 15);
|
name = name.substr(0, 15);
|
||||||
|
@ -803,8 +843,19 @@ void* PosixCondition<Thread>::ThreadStartRoutine(void* parameter) {
|
||||||
delete start_data;
|
delete start_data;
|
||||||
|
|
||||||
current_thread_ = thread;
|
current_thread_ = thread;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(thread->handle_.state_mutex_);
|
||||||
|
thread->handle_.state_ = State::kRunning;
|
||||||
|
thread->handle_.state_signal_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
start_routine();
|
start_routine();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(thread->handle_.state_mutex_);
|
||||||
|
thread->handle_.state_ = State::kFinished;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(mutex_);
|
std::unique_lock<std::mutex> lock(mutex_);
|
||||||
thread->handle_.exit_code_ = 0;
|
thread->handle_.exit_code_ = 0;
|
||||||
thread->handle_.signaled_ = true;
|
thread->handle_.signaled_ = true;
|
||||||
|
|
Loading…
Reference in New Issue