| 1 | /*============================================================================= |
| 2 | Copyright (c) 2001-2007 Joel de Guzman |
| 3 | |
| 4 | Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 5 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 6 | ==============================================================================*/ |
| 7 | |
| 8 | #include <boost/phoenix.hpp> |
| 9 | |
| 10 | struct omp_for_eval |
| 11 | { |
| 12 | typedef void result_type; |
| 13 | |
| 14 | template <typename Init, typename Cond, typename Step, typename Do, typename Context> |
| 15 | result_type |
| 16 | operator()( |
| 17 | Init const& init |
| 18 | , Cond const& cond |
| 19 | , Step const& step |
| 20 | , Do const& do_ |
| 21 | , Context & ctx |
| 22 | ) const |
| 23 | { |
| 24 | #pragma omp parallel |
| 25 | for( |
| 26 | boost::phoenix::eval(init, ctx); |
| 27 | boost::phoenix::eval(cond, ctx); |
| 28 | boost::phoenix::eval(step, ctx) |
| 29 | ) |
| 30 | { |
| 31 | boost::phoenix::eval(do_, ctx); |
| 32 | } |
| 33 | } |
| 34 | }; |
| 35 | |
| 36 | |
| 37 | //////////////////////////////////////////////////////////////////////////////// |
| 38 | // Define new custom expression |
| 39 | BOOST_PHOENIX_DEFINE_EXPRESSION( |
| 40 | (omp_for) |
| 41 | , (boost::phoenix::meta_grammar) // Cond |
| 42 | (boost::phoenix::meta_grammar) // Init |
| 43 | (boost::phoenix::meta_grammar) // Step |
| 44 | (boost::phoenix::meta_grammar) // Do |
| 45 | ) |
| 46 | |
| 47 | namespace boost { namespace phoenix |
| 48 | { |
| 49 | template <> |
| 50 | struct default_actions::when< ::rule::omp_for> |
| 51 | : boost::phoenix::call< ::omp_for_eval> |
| 52 | {}; |
| 53 | }} |
| 54 | |
| 55 | template <typename Init, typename Cond, typename Step> |
| 56 | struct omp_for_gen |
| 57 | { |
| 58 | omp_for_gen(Init const& init, Cond const& cond, Step const& step) |
| 59 | : init(init), cond(cond), step(step) {} |
| 60 | |
| 61 | template <typename Do> |
| 62 | typename result_of::make_omp_for<Init, Cond, Step, Do>::type const |
| 63 | operator[](Do const& do_) const |
| 64 | { |
| 65 | return make_omp_for(init, cond, step, do_); |
| 66 | } |
| 67 | |
| 68 | Init init; |
| 69 | Cond cond; |
| 70 | Step step; |
| 71 | }; |
| 72 | |
| 73 | template <typename Init, typename Cond, typename Step> |
| 74 | inline |
| 75 | omp_for_gen<Init, Cond, Step> const |
| 76 | omp_for(Init const& init, Cond const& cond, Step const& step) |
| 77 | { |
| 78 | return omp_for_gen<Init, Cond, Step>(init, cond, step); |
| 79 | } |
| 80 | //////////////////////////////////////////////////////////////////////////////// |
| 81 | |
| 82 | |
| 83 | //////////////////////////////////////////////////////////////////////////////// |
| 84 | // Define new evaluation scheme |
| 85 | |
| 86 | struct parallel_actions |
| 87 | { |
| 88 | template <typename Rule> |
| 89 | struct when |
| 90 | : boost::phoenix::default_actions::when<Rule> |
| 91 | {}; |
| 92 | }; |
| 93 | |
| 94 | template <> |
| 95 | struct parallel_actions::when<boost::phoenix::rule::for_> |
| 96 | : boost::phoenix::call<omp_for_eval> |
| 97 | {}; |
| 98 | |
| 99 | // Doing the same as actor<Expr>::operator |
| 100 | template <typename Expr, typename A0, typename A1, typename A2> |
| 101 | typename boost::phoenix::result_of::eval< |
| 102 | Expr const & |
| 103 | , typename boost::phoenix::result_of::make_context< |
| 104 | typename boost::phoenix::result_of::make_env< |
| 105 | Expr const * |
| 106 | , A0 & |
| 107 | , A1 & |
| 108 | , A2 & |
| 109 | >::type |
| 110 | , parallel_actions |
| 111 | >::type |
| 112 | >::type |
| 113 | parallel_eval(Expr & expr, A0 & a0, A1 & a1, A2 & a2) |
| 114 | { |
| 115 | Expr const * this_ = boost::addressof(expr); |
| 116 | return |
| 117 | boost::phoenix::eval( |
| 118 | expr |
| 119 | , boost::phoenix::make_context( |
| 120 | boost::phoenix::make_env(this_, a0, a1, a2) |
| 121 | , parallel_actions() |
| 122 | ) |
| 123 | ); |
| 124 | } |
| 125 | |
| 126 | // changing evaluation mechanism on the fly |
| 127 | BOOST_PHOENIX_DEFINE_EXPRESSION( |
| 128 | (parallel) |
| 129 | , (boost::phoenix::meta_grammar) |
| 130 | ) |
| 131 | |
| 132 | namespace boost { namespace phoenix |
| 133 | { |
| 134 | template <> |
| 135 | struct default_actions::when< ::rule::parallel> |
| 136 | : proto::call< |
| 137 | evaluator( |
| 138 | proto::_child0 |
| 139 | , functional::make_context( |
| 140 | _env |
| 141 | , parallel_actions() |
| 142 | ) |
| 143 | , unused()//mpl::void_() |
| 144 | ) |
| 145 | > |
| 146 | {}; |
| 147 | }} |
| 148 | |
| 149 | template <typename Expr> |
| 150 | typename result_of::make_parallel<Expr>::type |
| 151 | parallel(Expr const & expr) |
| 152 | { |
| 153 | return make_parallel(expr); |
| 154 | } |
| 155 | //////////////////////////////////////////////////////////////////////////////// |
| 156 | |
| 157 | |
| 158 | #include <vector> |
| 159 | #include <iostream> |
| 160 | |
| 161 | int main() |
| 162 | { |
| 163 | using boost::phoenix::arg_names::_1; |
| 164 | using boost::phoenix::arg_names::_2; |
| 165 | using boost::phoenix::arg_names::_3; |
| 166 | using boost::phoenix::local_names::_a; |
| 167 | using boost::phoenix::local_names::_b; |
| 168 | using boost::phoenix::local_names::_c; |
| 169 | using boost::phoenix::let; |
| 170 | using boost::phoenix::bind; |
| 171 | using boost::phoenix::lambda; |
| 172 | using boost::phoenix::nothing; |
| 173 | |
| 174 | const int NUM = 1; |
| 175 | |
| 176 | { |
| 177 | std::vector<int> a(NUM, 1); |
| 178 | std::vector<int> b(NUM, 2); |
| 179 | std::vector<int> c(NUM, 0); |
| 180 | |
| 181 | ( |
| 182 | let(_a = begin(_1), _b = begin(_2), _c = begin(_3)) |
| 183 | [ |
| 184 | for_(nothing, _a != end(_1), (++_a, ++_b, ++_c)) |
| 185 | [ |
| 186 | *_c = *_a + *_b |
| 187 | ] |
| 188 | ] |
| 189 | , std::cout << accumulate(a0: _3, a1: 0) << "\n" |
| 190 | )(a, b, c); |
| 191 | } |
| 192 | |
| 193 | { |
| 194 | std::vector<int> a(NUM, 1); |
| 195 | std::vector<int> b(NUM, 2); |
| 196 | std::vector<int> c(NUM, 0); |
| 197 | |
| 198 | ( |
| 199 | let(_a = begin(_1), _b = begin(_2), _c = begin(_3)) |
| 200 | [ |
| 201 | omp_for(nothing, _a != end(_1), (++_a, ++_b, ++_c)) |
| 202 | [ |
| 203 | *_c = *_a + *_b |
| 204 | ] |
| 205 | , std::cout << accumulate(a0: _3, a1: 0) << "\n" |
| 206 | ] |
| 207 | )(a, b, c); |
| 208 | } |
| 209 | |
| 210 | { |
| 211 | std::vector<int> a(NUM, 1); |
| 212 | std::vector<int> b(NUM, 2); |
| 213 | std::vector<int> c(NUM, 0); |
| 214 | |
| 215 | parallel_eval( |
| 216 | let(_a = begin(_1), _b = begin(_2), _c = begin(_3)) |
| 217 | [ |
| 218 | for_(nothing, _a != end(_1), (++_a, ++_b, ++_c)) |
| 219 | [ |
| 220 | *_c = *_a + *_b |
| 221 | ] |
| 222 | , std::cout << accumulate(a0: _3, a1: 0) << "\n" |
| 223 | ] |
| 224 | , a, b, c); |
| 225 | } |
| 226 | |
| 227 | { |
| 228 | std::vector<int> a(NUM, 1); |
| 229 | std::vector<int> b(NUM, 2); |
| 230 | std::vector<int> c(NUM, 0); |
| 231 | |
| 232 | ( |
| 233 | let(_a = begin(_1), _b = begin(_2), _c = begin(_3)) |
| 234 | [ |
| 235 | parallel( |
| 236 | for_(nothing, _a != end(_1), (++_a, ++_b, ++_c)) |
| 237 | [ |
| 238 | *_c = *_a + *_b |
| 239 | ] |
| 240 | ) |
| 241 | ] |
| 242 | , std::cout << accumulate(a0: _3, a1: 0) << "\n" |
| 243 | )(a, b, c); |
| 244 | } |
| 245 | } |
| 246 | |