diff --git a/port/win/win_thread.cc b/port/win/win_thread.cc index e55ca7450..749332032 100644 --- a/port/win/win_thread.cc +++ b/port/win/win_thread.cc @@ -39,12 +39,17 @@ struct WindowsThread::Data { void WindowsThread::Init(std::function&& func) { - data_.reset(new Data(std::move(func))); + data_ = std::make_shared(std::move(func)); + // We create another instance of shared_ptr to get an additional ref + // since we may detach and destroy this instance before the threadproc + // may start to run. We choose to allocate this additional ref on the heap + // so we do not need to synchronize and allow this thread to proceed + std::unique_ptr> th_data(new std::shared_ptr(data_)); data_->handle_ = _beginthreadex(NULL, 0, // stack size &Data::ThreadProc, - data_.get(), + th_data.get(), 0, // init flag &th_id_); @@ -53,6 +58,7 @@ void WindowsThread::Init(std::function&& func) { std::errc::resource_unavailable_try_again), "Unable to create a thread"); } + th_data.release(); } WindowsThread::WindowsThread() : @@ -129,7 +135,7 @@ void WindowsThread::join() { assert(false); throw std::system_error(static_cast(lastError), std::system_category(), - "WaitForSingleObjectFailed"); + "WaitForSingleObjectFailed: thread join"); } CloseHandle(reinterpret_cast(data_->handle_)); @@ -157,8 +163,9 @@ void WindowsThread::swap(WindowsThread& o) { } unsigned int __stdcall WindowsThread::Data::ThreadProc(void* arg) { - auto data = reinterpret_cast(arg); - data->func_(); + auto ptr = reinterpret_cast*>(arg); + std::unique_ptr> data(ptr); + (*data)->func_(); _endthreadex(0); return 0; } diff --git a/port/win/win_thread.h b/port/win/win_thread.h index 993cc0273..1d5b225e6 100644 --- a/port/win/win_thread.h +++ b/port/win/win_thread.h @@ -28,7 +28,7 @@ class WindowsThread { struct Data; - std::unique_ptr data_; + std::shared_ptr data_; unsigned int th_id_; void Init(std::function&&);