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