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 }