Reputation: 23
In boost.thread's start function, the source code is something like that:
bool thread::start_thread_noexcept()
{
uintptr_t const new_thread = _beginthreadex(
0,
0,
&thread_start_function,
thread_info.get(),
CREATE_SUSPENDED,
&thread_info->id);
if (!new_thread)
{
return false;
}
// why call this line?
intrusive_ptr_add_ref(thread_info.get());
thread_info->thread_handle = (detail::win32::handle)(new_thread);
ResumeThread(thread_info->thread_handle);
return true;
}
thread_info is a intrusive smart pointer which points to the thread information data, before calling the intrusive_ptr_add_ref, the count is already 1, I don't know why call the intrusive_ptr_add_ref mannually here. I think Intrusive smart pointer's job should be calling the intrusive_ptr_add_ref and intrusive_ptr_release automatically.
I've tried to step through the source code but didn't find any clue.
Can anyone tell me 1. why call intrusive_ptr_add_ref manually here? 2. In what condition when using the intrusive_ptr, I should call intrusive_ptr_add_ref manually?
Thanks, Sincerely.
Upvotes: 2
Views: 249
Reputation: 474326
why call intrusive_ptr_add_ref manually here?
To represent the sharing of ownership of the pointer.
_beginthreadex
was passed thread_info.get()
as a parameter. This parameter will be passed to thread_start_function
when the thread starts. And this function expects the pointer to remain valid until that happens.
Now, _beginthreadex
is a simple function. It's not a variadic template that can take arbitrary parameters or anything. It takes exactly and only a naked pointer, and passes exactly that to the start function.
It is very possible for the person creating the boost::thread
to call thread::detach
before thread_start_function
ever gets called. And if that happened, then the thread_info
intrusive pointer would be destroyed, thus causing the destruction of its contained object.
And that leaves _beginthreadex
with a destroyed pointer. That's bad.
What _beginthreadex
needs to do is claim ownership of the intrusvie pointer. But since the API doesn't take a boost::intrusive_ptr
, how do you do that?
By bumping the reference count. The reference count increase is how _beginthreadex
claims ownership of the object.
Upvotes: 1