C++11多线程编程 第九章: std::async 更更优雅的写多线程

C++11 Multithreading – Part 9: std::async Tutorial & Example

Varun May 5, 2017 C++11 Multithreading – Part 9: std::async Tutorial & Example2018-08-18T15:22:50+00:00C++C++ 11c++11 ThreadsMultithreading 4 Comments

In this article we will discuss how to execute tasks asynchronously with std::async in C++11.

std::async is introduced in c++11.

what is std::async()

std::async() is a function template that accepts a callback(i.e. function or function object) as an argument and potentially executes them asynchronously.

 

1

2

template <class Fn, class... Args>

future<typename result_of<Fn(Args...)>::type> async (launch policy, Fn&& fn, Args&&... args);

std::async returns a std::future<T>, that stores the value returned by function object executed by std::async(). Arguments expected by function can be passed to std::async() as arguments after the function pointer argument.

First argument in std::async is launch policy, it control the asynchronous behaviour of std::async. We can create std::async with 3 different launch policies i.e.

  • std::launch::async
    • It guarantees the asynchronous behaviour i.e. passed function will be executed in seperate thread.
  • std::launch::deferred
    • Non asynchronous behaviour i.e. Function will be called when other thread will call get() on future to access the shared state.
  • std::launch::async | std::launch::deferred
    • Its the default behaviour. With this launch policy it can run asynchronously or not depending on the load on system. But we have no control over it.

If we do not specify an launch policy. Its behaviour will be similar to std::launch::async | std::launch::deferred.

We are going to use std::launch::async launch policy in this article.

We can pass any callback in std::async i.e.

  • Function Pointer
  • Function Object
  • Lambda Function

Let’s understand the need of std::async by an example,

Need of std::async()

Suppose we have to fetch some data (string) from DB and some from files in file-system. Then I need to merge both the strings and print.

In a single thread we will do like this,

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

#include <iostream>

#include <string>

#include <chrono>

#include <thread>

 

using namespace std::chrono;

 

std::string fetchDataFromDB(std::string recvdData)

{

// Make sure that function takes 5 seconds to complete

std::this_thread::sleep_for(seconds(5));

 

//Do stuff like creating DB Connection and fetching Data

return "DB_" + recvdData;

}

 

std::string fetchDataFromFile(std::string recvdData)

{

// Make sure that function takes 5 seconds to complete

std::this_thread::sleep_for(seconds(5));

 

//Do stuff like fetching Data File

return "File_" + recvdData;

}

 

int main()

{

// Get Start Time

system_clock::time_point start = system_clock::now();

 

//Fetch Data from DB

std::string dbData = fetchDataFromDB("Data");

 

//Fetch Data from File

std::string fileData = fetchDataFromFile("Data");

 

// Get End Time

auto end = system_clock::now();

 

auto diff = duration_cast < std::chrono::seconds > (end - start).count();

std::cout << "Total Time Taken = " << diff << " Seconds" << std::endl;

 

//Combine The Data

std::string data = dbData + " :: " + fileData;

 

//Printing the combined Data

std::cout << "Data = " << data << std::endl;

 

return 0;

}

Output:

 

1

2

Total Time Taken = 10 Seconds

Data = DB_Data :: File_Data

As both the functions fetchDataFromDB() & fetchDataFromFile() takes 5 seconds each and are running in a single thread so, total time consumed will be 10 seconds.

Now as fetching data from DB and file are independent of each other and also time consuming. So, we can run them in parallel.
One way to do is create a new thread pass a promise as an argument to thread function and fetch data from associated std::future object in calling thread.

The other easy way is using std::async.

Calling std::async with function pointer as callback

Now let’s modify the above code and call fetchDataFromDB() asynchronously using std::async() i.e.

 

1

2

3

4

5

6

7

std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");

 

// Do Some Stuff

 

//Fetch Data from DB

// Will block till data is available in future<std::string> object.

std::string dbData = resultFromDB.get();

std::async() does following things,

  • It automatically creates a thread (Or picks from internal thread pool) and a promise object for us.
  • Then passes the std::promise object to thread function and returns the associated std::future object.
  • When our passed argument function exits then its value will be set in this promise object, so eventually return value will be available in std::future object.

Now change the above example and use std::async to read data from DB asyncronously i.e.

Checkout the compete example as follows,

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

#include <iostream>

#include <string>

#include <chrono>

#include <thread>

#include <future>

 

using namespace std::chrono;

 

std::string fetchDataFromDB(std::string recvdData)

{

// Make sure that function takes 5 seconds to complete

std::this_thread::sleep_for(seconds(5));

 

//Do stuff like creating DB Connection and fetching Data

return "DB_" + recvdData;

}

 

std::string fetchDataFromFile(std::string recvdData)

{

// Make sure that function takes 5 seconds to complete

std::this_thread::sleep_for(seconds(5));

 

//Do stuff like fetching Data File

return "File_" + recvdData;

}

 

int main()

{

// Get Start Time

system_clock::time_point start = system_clock::now();

 

std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");

 

//Fetch Data from File

std::string fileData = fetchDataFromFile("Data");

 

//Fetch Data from DB

// Will block till data is available in future<std::string> object.

std::string dbData = resultFromDB.get();

 

// Get End Time

auto end = system_clock::now();

 

auto diff = duration_cast < std::chrono::seconds > (end - start).count();

std::cout << "Total Time Taken = " << diff << " Seconds" << std::endl;

 

//Combine The Data

std::string data = dbData + " :: " + fileData;

 

//Printing the combined Data

std::cout << "Data = " << data << std::endl;

 

return 0;

}

Now it will take 5 seconds only.

Output:

 

1

2

Total Time Taken = 5 Seconds

Data = DB_Data :: File_Data

 

 Calling std::async with Function Object as callback

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

/*

* Function Object

*/

struct DataFetcher

{

std::string operator()(std::string recvdData)

{

// Make sure that function takes 5 seconds to complete

std::this_thread::sleep_for (seconds(5));

//Do stuff like fetching Data File

return "File_" + recvdData;

 

}

};

 

//Calling std::async with function object

std::future<std::string> fileResult = std::async(DataFetcher(), "Data");

 

Calling std::async with Lambda function as callback

 

 

1

2

3

4

5

6

7

8

//Calling std::async with lambda function

std::future<std::string> resultFromDB = std::async([](std::string recvdData){

 

std::this_thread::sleep_for (seconds(5));

//Do stuff like creating DB Connection and fetching Data

return "DB_" + recvdData;

 

}, "Data");

ps:

async 相当于又对promise/future封装了一层, 来让写代码/看代码更舒服.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值