C++11: std::packaged_task

class std::packaged_task被用來同時存儲callable object,以及該callable object的返回值(也多是個異常).ios

#include <iostream>
#include <thread>
#include <future>
#include <exception>

int main()
{
	std::packaged_task<int(const int&)> t1; //空的packaged_task即沒有shared state,也沒有callable object.
	std::packaged_task<int(const int&)> t2([](const int& number) { return 10; }); //構造函數,運行時候構建一個shared state,而且存儲一個callable object進去.
	t1 = std::move(t2); //移動賦值運算符.這樣一來t2中的shared state和callable object都轉移到了t1中,t2不可再使用.

	std::future<int> result = t1.get_future();
	std::thread t3(std::move(t1), 20); //此時t1處於無效狀態.

	t3.detach(); //t3成爲一個獨立的線程.

	int value = result.get(); //若是t3內的callable object尚未執行完成,那麼會阻塞調用result.get()的線程直到t3類的callable object調用完成.
	std::cout << "result: " << value << std::endl;

	return 0;

}

----------------------------我是分割線------------------------------函數

std::packaged_task構造函數:this

packaged_task() noexcept;

template <class Fn>
  explicit packaged_task (Fn&& fn);

template <class Fn, class Alloc>
  explicit packaged_task (allocator_arg_t aa, const Alloc& alloc, Fn&& fn);

packaged_task (const packaged_task&) = delete; //不支持拷貝.

packaged_task (packaged_task&& x) noexcept;

1,默認構造函數構建一個std::packaged_task對象,即沒有shared state,也沒有callable object.spa

2,顯式構造函數接受一個callable object初始化std::packaged_task。同時建立一個not ready的shared state.線程

3,被刪除了的copy-constructor.code

4,移動構造函數,被移動的對象再也不可用,且當前對象得到被移動對象的callable object和shared state.對象

std::packaged_task::get_futureci

該函數返回一個std::future對象且該std::future與當前std::packaged_task共同使用同一個shared state.這樣也就意味着,若是咱們對被返回出來的std::future調用get(),wait()等,若是std::packaged_task中的callable object未執行完成(也就是shared state還處於not ready狀態),這樣就會阻塞當前正在調用get()或者wait()的線程.get

future<Ret> get_future();
#include <iostream>
#include <thread>
#include <future>
#include <string>

int function(const int& number)
{
	return number * 3;
}

int main()
{
	std::packaged_task<int(const int&)> t1(function);
	std::future<int> result = t1.get_future(); //此時result 和 t1共享shared state.

	std::thread t2(std::move(t1), 20); //t1被移動變成不可用狀態.
	t2.detach();

	int value = result.get(); //這裏調用get(),若是t2未執行完成(也就是shared state處於not ready狀態),會block當前調用get()的線程(這裏是main線程).

	std::cout << "value: " << value << std::endl;


	return 0;


}

std::packaged_task::make_ready_at_thread_exitstring

調用當前std::packaged_task中的callable object以一個獨立的線程運行該callable object,並轉發參數進去callable object,可是callable object調用完成後並非當即把該std::packaged_task中的shared state設置爲ready,而是直到該線程徹底結束的時候才設爲ready.

void make_ready_at_thread_exit (args... args);

std::packaged_task::operator=

該std::packaged_task對象的拷貝賦值運算被刪除了,也就是說std::packaged_task對象不能被拷貝.

可是能夠被移動,被移動的std::packaged_task的shared state和callable object被移動當前std::packaged_task.被移動對象變成不可用的狀態.

packaged_task& operator= (packaged_task&& rhs) noexcept;

packaged_task& operator= (const packaged_task&) = delete;//拷貝構造函數被刪除了.

std::packaged_task::operator()

調用當前對象內的callable object,並轉發參數進去(不過須要注意的是若是咱們經過operator()調用callable object並非並行的):

1,若是當前std::packaged_task中的callable object執行完成,則callable object的返回值被存儲到當前std::packaged_task的shared state中,且將該shared state的狀態設置爲ready.

2,若是當前的std::packaged_task中的callable object在執行過程當中拋出了異常,那麼該異常會被捕獲,也被存儲在shared state中,而且該shared state被設置爲ready.

#include <iostream>
#include <thread>
#include <future>
#include <string>
#include <utility>

class Object {
private:
	int number;

public:
	Object();
	~Object() = default;
	int& operator()(const int& number)noexcept;
};

Object::Object()
	:number(1)
{
	//
}

int& Object::operator()(const int& number)noexcept
{
	this->number = 20 * number;

	std::this_thread::sleep_for(std::chrono::seconds(2));
	return (this->number);
}

class MyObject {
private:
	int number;

public:
	inline MyObject():number(1){}
	~MyObject() = default;
	int getNumber(const int& num)noexcept
	{
		return (this->number * num);
	}
};


int function(const int& number)
{
	return number * 3;
}

int main()
{
	//callable object case 1:
	std::packaged_task<int(const int&)> t1(function);
	std::future<int> result = t1.get_future(); //此時result 和 t1共享shared state.
	std::thread t2(std::move(t1), 20); //t1被移動變成不可用狀態.
	t2.detach();
	int value = result.get(); //這裏調用get(),若是t2未執行完成(也就是shared state處於not ready狀態),會block當前調用get()的線程(這裏是main線程).
	std::cout << "value: " << value << std::endl;

	//callable object case 2:
	try {
		Object object;
		std::packaged_task<int& (const int&)noexcept> t3(object);
		std::future<int&> result1 = t3.get_future();
		//t3(20); //調用callable object可是並不會並行調用.
		std::thread t4(std::move(t3), 20);
		t4.detach();
		std::cout << " test " << std::endl;
		int value1 = result1.get();
		std::cout << "value1: " << value1 << std::endl;

	}catch (const std::exception& e) {
		std::cerr << "exception!" << std::endl;
	}


	//callable object case 3:
	MyObject myObject;
	std::function<int(const int&)> memberFunction = std::bind(&MyObject::getNumber, &myObject, std::placeholders::_1);

	std::packaged_task<int(const int&)> t5(memberFunction);
	std::future<int> result2 = t5.get_future();
	std::thread t6(std::move(t5), 20);
	t6.detach();
	int value2 = result2.get();

	std::cout << "value2: " << value2 << std::endl;
	return 0;
}

std::packaged_task::reset

當咱們執行完了callable object(不管是經過當前std::packaged_task的operator(),仍是經過std::thread),當前std::packaged_task對象內的shared state都被設置爲了ready,這樣也就形成了咱們經過調用當前std::packaged_task對象的get_future()函數得到的std::future只能get()一次,

那麼咱們想要再次執行該callable object怎麼辦呢?這個時候就須要調用當前std::packaged_task對象的reset()函數了給當前std::packaged_task對象建立一個新的shared state且處於not ready狀態.

void reset();
#include <iostream>
#include <thread>
#include <future>
#include <string>

int getNumber(const int& number)
{
	return number * 20;
}

int main()
{
	std::packaged_task<int(const int&)> package(getNumber);

	std::future<int> result = package.get_future();
	package(20);
	int value = result.get();
	std::cout << "value(now shared state is ready): " << value << std::endl;

	std::cout << "reset the shared state." << std::endl;
	package.reset();
	std::future<int> result2 = package.get_future();
	std::thread t2(std::move(package), 40); //注意這裏用了std::move(),package對象會再也不可用.
	t2.detach();
	int value2 = result2.get();
	std::cout << " value2(now share state is again ready): " << value2 << std::endl;

	return 0;
}
相關文章
相關標籤/搜索