std::thread 怎麼實作的?

本篇介紹一下一般各個作業系統的 C++ 編譯器是怎麼實作 std::thread 的,
在一番 trace code 的結果後,llvm 的 libc++ 實作是這樣的,
在 unix 平台下開 thread 就是轉換到 pthread 的 pthread_create。
在 windows 平台下開 thread 就是轉換到 win32 的 _beginthreadex。
gcc 的 libstdc++ 實作也是如此。

簡單介紹這兩種 c++ 庫差異:

  • libc++ (LLVM C++ standard library with C++ 11 support)
  • libstdc++ (GNU C++ standard library)

以下是 llvm 下 libc++ 怎麼實作的 code snippet,

1. std::thread::thread 的實作

建構子 thread 轉換成內部的 __libcpp_thread_create

libcxx/include/threadlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <class _Fp, class ..._Args,
class
>
thread::thread(_Fp&& __f, _Args&&... __args)
{
typedef unique_ptr<__thread_struct> _TSPtr;
_TSPtr __tsp(new __thread_struct);
typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
_VSTD::unique_ptr<_Gp> __p(
new _Gp(std::move(__tsp),
__decay_copy(_VSTD::forward<_Fp>(__f)),
__decay_copy(_VSTD::forward<_Args>(__args))...));
int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
if (__ec == 0)
__p.release();
else
__throw_system_error(__ec, "thread constructor failed");
}

1-1. std::thread::thread 在 unix 平台的實作內容

__libcpp_thread_create 在 unix 平台是呼叫 pthread_create

libcxx/include/__threading_supportlink
1
2
3
4
5
6
7
typedef pthread_t __libcpp_thread_t;
...
int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
void *__arg)
{
return pthread_create(__t, 0, __func, __arg);
}

1-2. std::thread::thread 在 windows 平台的實作內容

__libcpp_thread_create 在 windows 平台是呼叫 _beginthreadex

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
void *__arg)
{
auto *__data = new __libcpp_beginthreadex_thunk_data;
__data->__func = __func;
__data->__arg = __arg;

*__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
__libcpp_beginthreadex_thunk,
__data, 0, nullptr));

if (*__t)
return 0;
return GetLastError();
}

2. std::thread::join 的實作

join 轉換成內部的 __libcpp_thread_join

libcxx/src/thread.cpplink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void
thread::join()
{
int ec = EINVAL;
if (!__libcpp_thread_isnull(&__t_))
{
ec = __libcpp_thread_join(&__t_);
if (ec == 0)
__t_ = _LIBCPP_NULL_THREAD;
}

if (ec)
__throw_system_error(ec, "thread::join failed");
}

2-1. std::thread::join 在 unix 平台的實作內容

__libcpp_thread_join 在 unix 平台是呼叫 pthread_join

libcxx/include/__threading_supportlink
1
2
3
4
int __libcpp_thread_join(__libcpp_thread_t *__t)
{
return pthread_join(*__t, 0);
}

2-2. std::thread::join 在 windows 平台的實作內容

__libcpp_thread_join 在 windows 平台是呼叫 WaitForSingleObjectExCloseHandle

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
6
7
8
int __libcpp_thread_join(__libcpp_thread_t *__t)
{
if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
return GetLastError();
if (!CloseHandle(*__t))
return GetLastError();
return 0;
}

總結

在一番 trace code 的結果後,std::thread 在 llvm 的 libc++ 實作是這樣的,
在 unix 下
std::thread::thread 轉換成 pthread_create
std::thread::join 轉換成 pthread_join
在 windows 下
std::thread::thread 轉換成 _beginthreadex
std::thread::join 轉換成 WaitForSingleObjectExCloseHandle

線上 trace code 工具

介紹一下 Woboq 這個線上 trace code 網頁,可以點擊關鍵字跳至定義處,trace code 起來很方便,減少很多搜尋的時間。
thread::thread()
__libcpp_thread_create()

相關主題
C/C++ 新手入門教學懶人包
std::condition_variable 怎麼實作的?
std::mutex 怎麼實作的?
C++11 在各平台下如何實現?