-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexperimental_future.cpp
More file actions
150 lines (139 loc) · 4.6 KB
/
Copy pathexperimental_future.cpp
File metadata and controls
150 lines (139 loc) · 4.6 KB
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// #include <experimental/future>
#include "../future/experimental/future"
/*下面的不明所以*/
// std::experimental::future<int> find_the_answer
// /*这里find_the_answer() 会返回int值*/
// auto fut = find_the_answer();
/*这里fut应该是个future 支持后续调用的*/
// auto fut2 = fut.then(find_the_question);
/*下述代码 返回future 对应的线程自行执行*/
template<typename Func>
/*declval 返回一个类型的右值引用*/
std::experimental::future<decltype(std::declval<Func>()())>
spawn_async(Func &&func)
{
std::experimental::promise<decltype(std::declval<Func>()())> p;
auto res = p.get_future();
std::thread t([p=std::move(p),f = std::decay_t<Func>(func)] () mutable
{
try
{
p.set_value_at_thread_exit(f());
}
catch (...)
{
p.set_exception_at_thread_exit(std::current_exception());
}
});
t.detach();
return res;
}
/*串行执行的登录操作*/
void process_login(std::string const &username,std::string const &password)
{
try
{
user_id const id = backend.authenticate_user(username,password);
user_data const info_to_display = backend.request_current_info(id);
update_display(info_to_display);
}
catch(std::exception &e)
{
display_error(e);
}
}
/*异步任务处理用户登录
但是下面任务因为承担过多的任务而发生阻塞
我们应该按照后续函数的方式,将任务接合
形成调用链,每完成一个任务就执行下一个任务
和之前的消息通知似的*/
std::future<void> process_login(std::string const &username,std::string const &password)
{
return std::async(std::launch::async,[=] ()
{
try
{
user_id const id = backend.authenticate_user(username,password);
user_data const info_to_display = backend.request_current_info(id);
update_display(info_to_display);
}
catch(std::exception &e)
{
display_error(e);
}
});
}
/*下面使用后续函数调用
这里的then函数会接受上一个函数的返回值作为
参数继续调用函数,then函数返回值也是future
对象 也就是async返回一个future对象,然后调用
then继续执行,然后再返回future对象
下面的调用链有一个函数阻塞了就会都阻塞住
因为如果下面两个函数和服务器通信过程中
发生阻塞,就阻塞住了,因为他要返回值后
才会有future变量供后面调用
authenticate_user 返回user_id
request_current_info 返回user_data
*/
std::experimental::future<void> process_login(std::string const &username,std::string const &password)
{
return std::async(std::launch::async,[=] ()
{
return backend.authenticate_user(username,password);
}).then([](std::experimental::future<user_id> id)
{
return backend.request_current_info(id.get());
}).then([](std::experimental::future<user_data> info_to_display)
{
try
{
update_display(info_to_display.get());
}
catch(std::exception &e)
{
display_error(e);
}
})
}
/*下面后续函数的调用不会出现future<future<some_value>>
的情况,因为有个future展开的操作(根折叠引用似的),
就是不用担心会多层future
这里就不用阻塞了,因为返回的不再是值,而是
future,可直接返回future由后续函数调用,
然后返回等待其future就绪即可
async_authenticate_user 返回future<user_id>
async_request_current_info 但会future<user_data>
下面的代码在异步函数调用链上不会发生阻塞 好神奇
*/
std::experimental::future<void> process_login(std::string const &username,std::string const &password)
{
return backend.async_authenticate_user(username,password)
.then([](std::experimental::future<user_id> id)
{
return backend.async_request_current_info(id.get());
}).then([](std::experimental::future<user_data> info_to_display)
{
try
{
update_display(info_to_display.get());
}
catch(std::exception &e)
{
display_error(e);
}
})
}
/*下面是experimental::shared_future
他支持多个then的调用,fut是shared
下面fut2和fut3就不是shared了
需要显示的加上.share()才行
后续的参数需要声明为shared才合法*/
auto fut = spawn_async(some_function).share();
auto fut2 = fut.then([](std::experimental::shared_future<some_data> data)
{
do_stuff(data);
});
auto fut3 = fut.then([](std::experimental::shared_future<some_data> data)
{
do_other_stuff(data);
});