本篇介紹一下一般各個作業系統的 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/thread link 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_support link 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.cpp link 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.cpp link 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_support link 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 平台是呼叫 WaitForSingleObjectEx
和 CloseHandle
libcxx/src/support/win32/thread_win32.cpp link 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
轉換成 WaitForSingleObjectEx
和 CloseHandle
線上 trace code 工具 介紹一下 Woboq 這個線上 trace code 網頁,可以點擊關鍵字跳至定義處,trace code 起來很方便,減少很多搜尋的時間。thread::thread() __libcpp_thread_create()
相關主題 C/C++ 新手入門教學懶人包 std::condition_variable 怎麼實作的? std::mutex 怎麼實作的? C++11 在各平台下如何實現?