基于多线程并发-STL之thread构造函数浅析

一、标准库Thread内容(函数内部实现内容已摘去)

class thread
	{	// class for observing and managing threads
public:
	class id;
	typedef void *native_handle_type;
	thread() noexcept;
	template<class _Fn,
		class... _Args,
		class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
		explicit thread(_Fn&& _Fx, _Args&&... _Ax)
		{	// construct with _Fx(_Ax...)
		_Launch(&_Thr,
			_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
		}
	~thread() noexcept;
	thread(thread&& _Other) noexcept
		: _Thr(_Other._Thr);
	thread& operator=(thread&& _Other) noexcept;
	thread(const thread&) = delete;
	thread& operator=(const thread&) = delete;
	void swap(thread& _Other) noexcept;
	_NODISCARD bool joinable() const noexcept;
	void join();
	void detach();
	_NODISCARD id get_id() const noexcept;
	_NODISCARD static unsigned int hardware_concurrency() noexcept;

	_NODISCARD native_handle_type native_handle();

private:
	thread& _Move_thread(thread& _Other);
	_Thrd_t _Thr;
	};

二、Thread类简单介绍
在介绍那个很复杂的构造函数前我们大致了解一下该类。
1、以下含义为thread被创建出来后不能进行拷贝和拷贝赋值,但是有move语义(c++11重要特性)。

thread(thread&& _Other) noexcept
	: _Thr(_Other._Thr);
thread& operator=(thread&& _Other) noexcept;
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
void swap(thread& _Other) noexcept;

2、常用接口(不是本篇的主题,将在另外文章中讲到,请参考:《C++11标准库thread简介》

void join();
void detach();
_NODISCARD id get_id() const noexcept;
_NODISCARD static unsigned int hardware_concurrency() noexcept;

三、复杂而重要的构造函数(本文的主题)

template<class _Fn,
		class... _Args,
		class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
		explicit thread(_Fn&& _Fx, _Args&&... _Ax)
		{	// construct with _Fx(_Ax...)
		_Launch(&_Thr,
			_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
		}

1、模板参数部分

template<class _Fn,
		class... _Args,
		class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>

1)class _Fn是设想匹配的是可调用对象(函数、成员函数、函数对象、lambda表达式)等。
2)class… _Args,匹配可调用对象的参数列,为C++11的重要特性Variadic Templates(…)和元组tuple。
3)以下内容我们由内到外一层一层分析(对萃取机和元编程要稍作了解)

class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>

a、remove_reference_t<_Fn>为退化_Fn的引用和右值引用。
b、remove_cv_t<#a#>在a的基础上再退化_Fn的const和volatile
c、is_same_v<#b#, thread>在b的基础上判断_Fn和thread是否为同种类型。
d、enable_if_t若c的结果为false则该构造函数模板匹配成功,否则失败,编译不通过。
e、class=#d#为匿名模板参数(一般匿名模板参数来完成对部分参数条件的校验,此处就是经典应用),并且没有占位。
小结:这么一大串是为了不和其他构造发生二义性,使得“1)”中_Fn为可调用对象的设想为真,而不是线程对象。
不同版本VS源码稍有差别,核心思想不会变。

四、延伸探讨

// construct with _Fx(_Ax...)
		_Launch(&_Thr,
			_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));

该构造函数的实现部分有兴趣的也可以研究研究。

如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810

你可能感兴趣的:(并发编程,C++,Templates,多线程,并发编程,thread,高并发编程,C++11)