src/​examples/​cpp03/​spawn/​parallel_grep.​cppsrc/​examples/​cpp11/​spawn/​parallel_grep.​cpp
⋮⋮
1 /​/​1 /​/​
2 /​/​·​parallel_grep.​cpp2 /​/​·​parallel_grep.​cpp
3 /​/​·​~~~~~~~~~~~~~~~~~3 /​/​·​~~~~~~~~~~~~~~~~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2023·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2023·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying
8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​
9 /​/​9 /​/​
10 10
11 #include·​<asio/​detached.​hpp>11 #include·​<asio/​detached.​hpp>
12 #include·​<asio/​dispatch.​hpp>12 #include·​<asio/​dispatch.​hpp>
13 #include·​<asio/​post.​hpp>13 #include·​<asio/​post.​hpp>
14 #include·​<asio/​spawn.​hpp>14 #include·​<asio/​spawn.​hpp>
15 #include·​<asio/​strand.​hpp>15 #include·​<asio/​strand.​hpp>
16 #include·​<asio/​thread_pool.​hpp>16 #include·​<asio/​thread_pool.​hpp>
17 #include·​<boost/​bind/​bind.​hpp>
18 #include·​<fstream>17 #include·​<fstream>
19 #include·​<iostream>18 #include·​<iostream>
20 #include·​<string>19 #include·​<string>
21 20
22 using·​asio:​:​detached_t;​21 using·​asio:​:​detached;​
23 using·​asio:​:​dispatch;​22 using·​asio:​:​dispatch;​
24 using·​asio:​:​spawn;​23 using·​asio:​:​spawn;​
25 using·​asio:​:​strand;​24 using·​asio:​:​strand;​
26 using·​asio:​:​thread_pool;​25 using·​asio:​:​thread_pool;​
27 using·​asio:​:​yield_context;​26 using·​asio:​:​yield_context;​
28 27
29 void·​print_match(std:​:​string·​input_file,​·​std:​:​string·​line)​
30 {
31 ·​·​std:​:​cout·​<<·​input_file·​<<·​':​'·​<<·​line·​<<·​std:​:​endl;​
32 }
33
34 void·​search_file(std:​:​string·​search_string,​·​std:​:​string·​input_file,​
35 ·​·​·​·​strand<thread_pool:​:​executor_type>·​output_strand,​·​yield_context·​yield)​
36 {
37 ·​·​std:​:​ifstream·​is(input_file.​c_str()​)​;​
38 ·​·​std:​:​string·​line;​
39 ·​·​std:​:​size_t·​line_num·​=·​0;​
40 ·​·​while·​(std:​:​getline(is,​·​line)​)​
41 ·​·​{
42 ·​·​·​·​/​/​·​If·​we·​find·​a·​match,​·​send·​a·​message·​to·​the·​output.​
43 ·​·​·​·​if·​(line.​find(search_string)​·​!=·​std:​:​string:​:​npos)​
44 ·​·​·​·​{
45 ·​·​·​·​·​·​dispatch(output_stran​d,​·​boost:​:​bind(&print_match,​·​input_file,​·​line)​)​;​
46 ·​·​·​·​}
47
48 ·​·​·​·​/​/​·​Every·​so·​often·​we·​yield·​control·​to·​another·​coroutine.​
49 ·​·​·​·​if·​(++line_num·​%·​10·​==·​0)​
50 ·​·​·​·​·​·​post(yield)​;​
51 ·​·​}
52 }
53
54 int·​main(int·​argc,​·​char*·​argv[])​28 int·​main(int·​argc,​·​char*·​argv[])​
55 {29 {
56 ·​·​try30 ·​·​try
57 ·​·​{31 ·​·​{
58 ·​·​·​·​if·​(argc·​<·​2)​32 ·​·​·​·​if·​(argc·​<·​2)​
59 ·​·​·​·​{33 ·​·​·​·​{
60 ·​·​·​·​·​·​std:​:​cerr·​<<·​"Usage:​·​parallel_grep·​<string>·​<files.​.​.​>\n";​34 ·​·​·​·​·​·​std:​:​cerr·​<<·​"Usage:​·​parallel_grep·​<string>·​<files.​.​.​>\n";​
61 ·​·​·​·​·​·​return·​1;​35 ·​·​·​·​·​·​return·​1;​
62 ·​·​·​·​}36 ·​·​·​·​}
63 37
64 ·​·​·​·​/​/​·​We·​use·​a·​fixed·​size·​pool·​of·​threads·​for·​reading·​the·​input·​files.​·​The38 ·​·​·​·​/​/​·​We·​use·​a·​fixed·​size·​pool·​of·​threads·​for·​reading·​the·​input·​files.​·​The
65 ·​·​·​·​/​/​·​number·​of·​threads·​is·​automatically·​determined·​based·​on·​the·​number·​of39 ·​·​·​·​/​/​·​number·​of·​threads·​is·​automatically·​determined·​based·​on·​the·​number·​of
66 ·​·​·​·​/​/​·​CPUs·​available·​in·​the·​system.​40 ·​·​·​·​/​/​·​CPUs·​available·​in·​the·​system.​
67 ·​·​·​·​thread_pool·​pool;​41 ·​·​·​·​thread_pool·​pool;​
68 42
69 ·​·​·​·​/​/​·​To·​prevent·​the·​output·​from·​being·​garbled,​·​we·​use·​a·​strand·​to·​synchronise43 ·​·​·​·​/​/​·​To·​prevent·​the·​output·​from·​being·​garbled,​·​we·​use·​a·​strand·​to·​synchronise
70 ·​·​·​·​/​/​·​printing.​44 ·​·​·​·​/​/​·​printing.​
71 ·​·​·​·​strand<thread_pool:​:​executor_type>·​output_strand(pool.​get_executor()​)​;​45 ·​·​·​·​strand<thread_pool:​:​executor_type>·​output_strand(pool.​get_executor()​)​;​
72 46
73 ·​·​·​·​/​/​·​Spawn·​a·​new·​coroutine·​for·​each·​file·​specified·​on·​the·​command·​line.​47 ·​·​·​·​/​/​·​Spawn·​a·​new·​coroutine·​for·​each·​file·​specified·​on·​the·​command·​line.​
74 ·​·​·​·​std:​:​string·​search_string·​=·​argv[1];​48 ·​·​·​·​std:​:​string·​search_string·​=·​argv[1];​
75 ·​·​·​·​for·​(int·​argn·​=·​2;​·​argn·​<·​argc;​·​++argn)​49 ·​·​·​·​for·​(int·​argn·​=·​2;​·​argn·​<·​argc;​·​++argn)​
76 ·​·​·​·​{50 ·​·​·​·​{
77 ·​·​·​·​·​·​std:​:​string·​input_file·​=·​argv[argn];​51 ·​·​·​·​·​·​std:​:​string·​input_file·​=·​argv[argn];​
78 ·​·​·​·​·​·​spawn(pool,​52 ·​·​·​·​·​·​spawn(pool,​
79 ·​·​·​·​·​·​·​·​·​·​boost:​:​bind(&search_file,​·​search_string,​53 ·​·​·​·​·​·​·​·​[=](yield_context·​yield)​
80 ·​·​·​·​·​·​·​·​·​·​·​·​input_file,​·​output_strand,​·​boost:​:​placeholders:​:​_1)​,​54 ·​·​·​·​·​·​·​·​{
81 ·​·​·​·​·​·​·​·​·​·​detached_t()​)​;​55 ·​·​·​·​·​·​·​·​·​·​std:​:​ifstream·​is(input_file.​c_str()​)​;​
56 ·​·​·​·​·​·​·​·​·​·​std:​:​string·​line;​
57 ·​·​·​·​·​·​·​·​·​·​std:​:​size_t·​line_num·​=·​0;​
58 ·​·​·​·​·​·​·​·​·​·​while·​(std:​:​getline(is,​·​line)​)​
59 ·​·​·​·​·​·​·​·​·​·​{
60 ·​·​·​·​·​·​·​·​·​·​·​·​/​/​·​If·​we·​find·​a·​match,​·​send·​a·​message·​to·​the·​output.​
61 ·​·​·​·​·​·​·​·​·​·​·​·​if·​(line.​find(search_string)​·​!=·​std:​:​string:​:​npos)​
62 ·​·​·​·​·​·​·​·​·​·​·​·​{
63 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​dispatch(output_stran​d,​
64 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​[=]
65 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​{
66 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​std:​:​cout·​<<·​input_file·​<<·​':​'·​<<·​line·​<<·​std:​:​endl;​
67 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​})​;​
68 ·​·​·​·​·​·​·​·​·​·​·​·​}
69
70 ·​·​·​·​·​·​·​·​·​·​·​·​/​/​·​Every·​so·​often·​we·​yield·​control·​to·​another·​coroutine.​
71 ·​·​·​·​·​·​·​·​·​·​·​·​if·​(++line_num·​%·​10·​==·​0)​
72 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​post(yield)​;​
73 ·​·​·​·​·​·​·​·​·​·​}
74 ·​·​·​·​·​·​·​·​},​·​detached)​;​
82 ·​·​·​·​}75 ·​·​·​·​}
83 76
84 ·​·​·​·​/​/​·​Join·​the·​thread·​pool·​to·​wait·​for·​all·​the·​spawned·​tasks·​to·​complete.​77 ·​·​·​·​/​/​·​Join·​the·​thread·​pool·​to·​wait·​for·​all·​the·​spawned·​tasks·​to·​complete.​
85 ·​·​·​·​pool.​join()​;​78 ·​·​·​·​pool.​join()​;​
86 ·​·​}79 ·​·​}
87 ·​·​catch·​(std:​:​exception&·​e)​80 ·​·​catch·​(std:​:​exception&·​e)​
88 ·​·​{81 ·​·​{
89 ·​·​·​·​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​82 ·​·​·​·​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
90 ·​·​}83 ·​·​}
91 84
92 ·​·​return·​0;​85 ·​·​return·​0;​
93 }86 }