1 // Copyright (c) 2013-2014 Thomas Heller 2 // Copyright (c) 2013-2017 Hartmut Kaiser 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 /// \file broadcast.hpp 8 9 #if defined(DOXYGEN) 10 namespace hpx { namespace lcos 11 { 12 /// \brief Perform a distributed broadcast operation 13 /// 14 /// The function hpx::lcos::broadcast performs a distributed broadcast 15 /// operation resulting in action invocations on a given set 16 /// of global identifiers. The action can be either a plain action (in 17 /// which case the global identifiers have to refer to localities) or a 18 /// component action (in which case the global identifiers have to refer 19 /// to instances of a component type which exposes the action. 20 /// 21 /// The given action is invoked asynchronously on all given identifiers, 22 /// and the arguments ArgN are passed along to those invocations. 23 /// 24 /// \param ids [in] A list of global identifiers identifying the 25 /// target objects for which the given action will be 26 /// invoked. 27 /// \param argN [in] Any number of arbitrary arguments (passed 28 /// by const reference) which will be forwarded to the 29 /// action invocation. 30 /// 31 /// \returns This function returns a future representing the result 32 /// of the overall reduction operation. 33 /// 34 /// \note If decltype(Action(...)) is void, then the result of 35 /// this function is future<void>. 36 /// 37 template <typename Action, typename ArgN, ...> 38 hpx::future<std::vector<decltype(Action(hpx::id_type, ArgN, ...))> > 39 broadcast( 40 std::vector<hpx::id_type> const & ids 41 , ArgN argN, ...); 42 43 /// \brief Perform an asynchronous (fire&forget) distributed broadcast operation 44 /// 45 /// The function hpx::lcos::broadcast_apply performs an asynchronous 46 /// (fire&forget) distributed broadcast operation resulting in action 47 /// invocations on a given set of global identifiers. The action can be 48 /// either a plain action (in which case the global identifiers have to 49 /// refer to localities) or a component action (in which case the global 50 /// identifiers have to refer to instances of a component type which 51 /// exposes the action. 52 /// 53 /// The given action is invoked asynchronously on all given identifiers, 54 /// and the arguments ArgN are passed along to those invocations. 55 /// 56 /// \param ids [in] A list of global identifiers identifying the 57 /// target objects for which the given action will be 58 /// invoked. 59 /// \param argN [in] Any number of arbitrary arguments (passed 60 /// by const reference) which will be forwarded to the 61 /// action invocation. 62 /// 63 template <typename Action, typename ArgN, ...> 64 void 65 broadcast_apply( 66 std::vector<hpx::id_type> const & ids 67 , ArgN argN, ...); 68 69 /// \brief Perform a distributed broadcast operation 70 /// 71 /// The function hpx::lcos::broadcast_with_index performs a distributed broadcast 72 /// operation resulting in action invocations on a given set 73 /// of global identifiers. The action can be either a plain action (in 74 /// which case the global identifiers have to refer to localities) or a 75 /// component action (in which case the global identifiers have to refer 76 /// to instances of a component type which exposes the action. 77 /// 78 /// The given action is invoked asynchronously on all given identifiers, 79 /// and the arguments ArgN are passed along to those invocations. 80 /// 81 /// The function passes the index of the global identifier in the given 82 /// list of identifiers as the last argument to the action. 83 /// 84 /// \param ids [in] A list of global identifiers identifying the 85 /// target objects for which the given action will be 86 /// invoked. 87 /// \param argN [in] Any number of arbitrary arguments (passed 88 /// by const reference) which will be forwarded to the 89 /// action invocation. 90 /// 91 /// \returns This function returns a future representing the result 92 /// of the overall reduction operation. 93 /// 94 /// \note If decltype(Action(...)) is void, then the result of 95 /// this function is future<void>. 96 /// 97 template <typename Action, typename ArgN, ...> 98 hpx::future<std::vector<decltype(Action(hpx::id_type, ArgN, ..., std::size_t))> > 99 broadcast_with_index( 100 std::vector<hpx::id_type> const & ids 101 , ArgN argN, ...); 102 103 /// \brief Perform an asynchronous (fire&forget) distributed broadcast operation 104 /// 105 /// The function hpx::lcos::broadcast_apply_with_index performs an asynchronous 106 /// (fire&forget) distributed broadcast operation resulting in action 107 /// invocations on a given set of global identifiers. The action can be 108 /// either a plain action (in which case the global identifiers have to 109 /// refer to localities) or a component action (in which case the global 110 /// identifiers have to refer to instances of a component type which 111 /// exposes the action. 112 /// 113 /// The given action is invoked asynchronously on all given identifiers, 114 /// and the arguments ArgN are passed along to those invocations. 115 /// 116 /// The function passes the index of the global identifier in the given 117 /// list of identifiers as the last argument to the action. 118 /// 119 /// \param ids [in] A list of global identifiers identifying the 120 /// target objects for which the given action will be 121 /// invoked. 122 /// \param argN [in] Any number of arbitrary arguments (passed 123 /// by const reference) which will be forwarded to the 124 /// action invocation. 125 /// 126 template <typename Action, typename ArgN, ...> 127 void 128 broadcast_apply_with_index( 129 std::vector<hpx::id_type> const & ids 130 , ArgN argN, ...); 131 }} 132 #else 133 134 #ifndef HPX_LCOS_BROADCAST_HPP 135 #define HPX_LCOS_BROADCAST_HPP 136 137 #include <hpx/config.hpp> 138 #include <hpx/apply.hpp> 139 #include <hpx/lcos/detail/async_colocated.hpp> 140 #include <hpx/lcos/future.hpp> 141 #include <hpx/lcos/when_all.hpp> 142 #include <hpx/runtime/actions/plain_action.hpp> 143 #include <hpx/runtime/applier/detail/apply_colocated.hpp> 144 #include <hpx/runtime/naming/name.hpp> 145 #include <hpx/runtime/serialization/vector.hpp> 146 #include <hpx/throw_exception.hpp> 147 #include <hpx/traits/extract_action.hpp> 148 #include <hpx/traits/promise_local_result.hpp> 149 #include <hpx/util/assert.hpp> 150 #include <hpx/util/calculate_fanout.hpp> 151 #include <hpx/util/detail/pack.hpp> 152 #include <hpx/util/detail/pp/cat.hpp> 153 #include <hpx/util/detail/pp/expand.hpp> 154 #include <hpx/util/detail/pp/nargs.hpp> 155 #include <hpx/util/tuple.hpp> 156 157 #include <cstddef> 158 #include <type_traits> 159 #include <utility> 160 #include <vector> 161 162 #if !defined(HPX_BROADCAST_FANOUT) 163 #define HPX_BROADCAST_FANOUT 16 164 #endif 165 166 namespace hpx { namespace lcos 167 { 168 namespace detail 169 { 170 /////////////////////////////////////////////////////////////////////// 171 template <typename Action> 172 struct broadcast_with_index 173 { 174 typedef typename Action::arguments_type arguments_type; 175 }; 176 177 /////////////////////////////////////////////////////////////////////// 178 template <typename Action> 179 struct broadcast_result 180 { 181 typedef 182 typename traits::promise_local_result< 183 typename hpx::traits::extract_action< 184 Action 185 >::remote_result_type 186 >::type 187 action_result; 188 typedef 189 typename std::conditional< 190 std::is_same<void, action_result>::value 191 , void 192 , std::vector<action_result> 193 >::type 194 type; 195 }; 196 197 template <typename Action> 198 struct broadcast_result<broadcast_with_index<Action> > 199 : broadcast_result<Action> 200 {}; 201 202 /////////////////////////////////////////////////////////////////////// 203 template < 204 typename Action 205 , typename ...Ts 206 > 207 //hpx::future<typename broadcast_result<Action>::type> 208 typename broadcast_result<Action>::type 209 broadcast_impl( 210 Action const & act 211 , std::vector<hpx::id_type> const & ids 212 , std::size_t global_idx 213 , std::false_type 214 , Ts const&... vs 215 ); 216 217 template < 218 typename Action 219 , typename ...Ts 220 > 221 //hpx::future<void> 222 void 223 broadcast_impl( 224 Action const & act 225 , std::vector<hpx::id_type> const & ids 226 , std::size_t global_idx 227 , std::true_type 228 , Ts const&... vs 229 ); 230 231 template < 232 typename Action 233 , typename ...Ts 234 > 235 void 236 broadcast_apply_impl( 237 Action const & act 238 , std::vector<hpx::id_type> const & ids 239 , std::size_t global_idx 240 , Ts const&... vs 241 ); 242 243 /////////////////////////////////////////////////////////////////////// 244 template < 245 typename Action 246 , typename Futures 247 , typename ...Ts 248 > 249 void broadcast_invoke(Action act,Futures & futures,hpx::id_type const & id,std::size_t,Ts const &...vs)250 broadcast_invoke(Action act, Futures& futures, hpx::id_type const& id 251 , std::size_t 252 , Ts const&... vs) 253 { 254 futures.push_back( 255 hpx::async( 256 act 257 , id 258 , vs... 259 ) 260 ); 261 } 262 263 template < 264 typename Action 265 , typename Futures 266 , typename ...Ts 267 > 268 void broadcast_invoke(broadcast_with_index<Action>,Futures & futures,hpx::id_type const & id,std::size_t global_idx,Ts const &...vs)269 broadcast_invoke(broadcast_with_index<Action>, 270 Futures& futures, hpx::id_type const& id 271 , std::size_t global_idx 272 , Ts const&... vs) 273 { 274 futures.push_back( 275 hpx::async( 276 Action() 277 , id 278 , vs... 279 , global_idx 280 ) 281 ); 282 } 283 284 template < 285 typename Action 286 , typename Futures 287 , typename Cont 288 , typename ...Ts 289 > 290 void broadcast_invoke(Action act,Futures & futures,Cont && cont,hpx::id_type const & id,std::size_t,Ts const &...vs)291 broadcast_invoke(Action act, Futures& futures, Cont && cont 292 , hpx::id_type const& id 293 , std::size_t 294 , Ts const&... vs) 295 { 296 futures.push_back( 297 hpx::async( 298 act 299 , id 300 , vs... 301 ).then(std::forward<Cont>(cont)) 302 ); 303 } 304 305 template < 306 typename Action 307 , typename Futures 308 , typename Cont 309 , typename ...Ts 310 > 311 void broadcast_invoke(broadcast_with_index<Action>,Futures & futures,Cont && cont,hpx::id_type const & id,std::size_t global_idx,Ts const &...vs)312 broadcast_invoke(broadcast_with_index<Action>, Futures& futures 313 , Cont && cont 314 , hpx::id_type const& id 315 , std::size_t global_idx 316 , Ts const&... vs) 317 { 318 futures.push_back( 319 hpx::async( 320 Action() 321 , id 322 , vs... 323 , global_idx 324 ).then(std::forward<Cont>(cont)) 325 ); 326 } 327 328 template < 329 typename Action 330 , typename ...Ts 331 > 332 void broadcast_invoke_apply(Action act,hpx::id_type const & id,std::size_t,Ts const &...vs)333 broadcast_invoke_apply(Action act 334 , hpx::id_type const& id 335 , std::size_t 336 , Ts const&... vs) 337 { 338 hpx::apply( 339 act 340 , id 341 , vs... 342 ); 343 } 344 345 template < 346 typename Action 347 , typename ...Ts 348 > 349 void broadcast_invoke_apply(broadcast_with_index<Action>,hpx::id_type const & id,std::size_t global_idx,Ts const &...vs)350 broadcast_invoke_apply(broadcast_with_index<Action> 351 , hpx::id_type const& id 352 , std::size_t global_idx 353 , Ts const&... vs) 354 { 355 hpx::apply( 356 Action() 357 , id 358 , vs... 359 , global_idx 360 ); 361 } 362 363 /////////////////////////////////////////////////////////////////////// 364 template < 365 typename Action 366 , typename IsVoid 367 , typename ...Ts 368 > 369 struct broadcast_invoker 370 { 371 //static hpx::future<typename broadcast_result<Action>::type> 372 static typename broadcast_result<Action>::type callhpx::lcos::detail::broadcast_invoker373 call( 374 Action const & act 375 , std::vector<hpx::id_type> const & ids 376 , std::size_t global_idx 377 , IsVoid 378 , Ts const&... vs 379 ) 380 { 381 return 382 broadcast_impl( 383 act 384 , ids 385 , global_idx 386 , IsVoid() 387 , vs... 388 ); 389 } 390 }; 391 392 template < 393 typename Action 394 , typename ...Ts 395 > 396 struct broadcast_apply_invoker 397 { 398 static void callhpx::lcos::detail::broadcast_apply_invoker399 call( 400 Action const & act 401 , std::vector<hpx::id_type> const & ids 402 , std::size_t global_idx 403 , Ts const&... vs 404 ) 405 { 406 return 407 broadcast_apply_impl( 408 act 409 , ids 410 , global_idx 411 , vs... 412 ); 413 } 414 }; 415 416 /////////////////////////////////////////////////////////////////////// 417 template <typename Action, typename Is> 418 struct make_broadcast_action_impl; 419 420 template <typename Action, std::size_t ...Is> 421 struct make_broadcast_action_impl<Action, 422 util::detail::pack_c<std::size_t, Is...> > 423 { 424 typedef 425 typename broadcast_result<Action>::action_result 426 action_result; 427 428 typedef detail::broadcast_invoker< 429 Action 430 , typename std::is_void<action_result>::type 431 , typename util::tuple_element< 432 Is, typename Action::arguments_type 433 >::type... 434 > 435 broadcast_invoker_type; 436 437 typedef 438 typename HPX_MAKE_ACTION(broadcast_invoker_type::call)::type 439 type; 440 }; 441 442 template <typename Action> 443 struct make_broadcast_action 444 : make_broadcast_action_impl< 445 Action 446 , typename util::detail::make_index_pack<Action::arity>::type 447 > 448 {}; 449 450 template <typename Action> 451 struct make_broadcast_action<broadcast_with_index<Action> > 452 : make_broadcast_action_impl< 453 broadcast_with_index<Action> 454 , typename util::detail::make_index_pack<Action::arity - 1>::type 455 > 456 {}; 457 458 template <typename Action, typename Is> 459 struct make_broadcast_apply_action_impl; 460 461 template <typename Action, std::size_t ...Is> 462 struct make_broadcast_apply_action_impl<Action, 463 util::detail::pack_c<std::size_t, Is...> > 464 { 465 typedef 466 typename broadcast_result<Action>::action_result 467 action_result; 468 469 typedef detail::broadcast_apply_invoker< 470 Action 471 , typename util::tuple_element< 472 Is, typename Action::arguments_type 473 >::type... 474 > 475 broadcast_invoker_type; 476 477 typedef 478 typename HPX_MAKE_ACTION(broadcast_invoker_type::call)::type 479 type; 480 }; 481 482 template <typename Action> 483 struct make_broadcast_apply_action 484 : make_broadcast_apply_action_impl< 485 Action 486 , typename util::detail::make_index_pack<Action::arity>::type 487 > 488 {}; 489 490 template <typename Action> 491 struct make_broadcast_apply_action<broadcast_with_index<Action> > 492 : make_broadcast_apply_action_impl< 493 broadcast_with_index<Action> 494 , typename util::detail::make_index_pack<Action::arity - 1>::type 495 > 496 {}; 497 498 /////////////////////////////////////////////////////////////////////// return_void(hpx::future<std::vector<hpx::future<void>>>)499 inline void return_void( 500 hpx::future<std::vector<hpx::future<void> > >) 501 { 502 // todo: verify validity of all futures in the vector 503 } 504 505 template < 506 typename Result 507 > 508 std::vector<Result> wrap_into_vector(hpx::future<Result> r)509 wrap_into_vector(hpx::future<Result> r) 510 { 511 std::vector<Result> result; 512 result.push_back(r.get()); 513 return result; 514 } 515 516 template < 517 typename Result 518 > 519 std::vector<Result> return_result_type(hpx::future<std::vector<hpx::future<std::vector<Result>>>> r)520 return_result_type( 521 hpx::future<std::vector<hpx::future<std::vector<Result> > > > r) 522 { 523 std::vector<Result> res; 524 std::vector<hpx::future<std::vector<Result> > > fres = std::move(r.get()); 525 526 for (hpx::future<std::vector<Result> >& f : fres) 527 { 528 std::vector<Result> t = std::move(f.get()); 529 res.reserve(res.capacity() + t.size()); 530 std::move(t.begin(), t.end(), std::back_inserter(res)); 531 } 532 533 return res; 534 } 535 536 /////////////////////////////////////////////////////////////////////// 537 template < 538 typename Action 539 , typename ...Ts 540 > 541 //hpx::future<void> 542 void broadcast_impl(Action const & act,std::vector<hpx::id_type> const & ids,std::size_t global_idx,std::true_type,Ts const &...vs)543 broadcast_impl( 544 Action const & act 545 , std::vector<hpx::id_type> const & ids 546 , std::size_t global_idx 547 , std::true_type 548 , Ts const&... vs 549 ) 550 { 551 if(ids.empty()) return;// hpx::lcos::make_ready_future(); 552 553 std::size_t const local_fanout = HPX_BROADCAST_FANOUT; 554 std::size_t local_size = (std::min)(ids.size(), local_fanout); 555 std::size_t fanout = util::calculate_fanout(ids.size(), local_fanout); 556 557 std::vector<hpx::future<void> > broadcast_futures; 558 broadcast_futures.reserve(local_size + (ids.size()/fanout) + 1); 559 for(std::size_t i = 0; i != local_size; ++i) 560 { 561 broadcast_invoke( 562 act 563 , broadcast_futures 564 , ids[i] 565 , global_idx + i 566 , vs... 567 ); 568 } 569 570 if(ids.size() > local_fanout) 571 { 572 std::size_t applied = local_fanout; 573 std::vector<hpx::id_type>::const_iterator it = 574 ids.begin() + local_fanout; 575 576 typedef 577 typename detail::make_broadcast_action< 578 Action 579 >::type 580 broadcast_impl_action; 581 582 while(it != ids.end()) 583 { 584 HPX_ASSERT(ids.size() >= applied); 585 586 std::size_t next_fan = (std::min)(fanout, ids.size() - applied); 587 std::vector<hpx::id_type> ids_next(it, it + next_fan); 588 589 hpx::id_type id(ids_next[0]); 590 broadcast_futures.push_back( 591 hpx::detail::async_colocated<broadcast_impl_action>( 592 id 593 , act 594 , std::move(ids_next) 595 , global_idx + applied 596 , std::true_type() 597 , vs... 598 ) 599 ); 600 601 applied += next_fan; 602 it += next_fan; 603 } 604 } 605 606 //return hpx::when_all(broadcast_futures).then(&return_void); 607 hpx::when_all(broadcast_futures).then(&return_void).get(); 608 } 609 610 template < 611 typename Action 612 , typename ...Ts 613 > 614 //hpx::future<typename broadcast_result<Action>::type> 615 typename broadcast_result<Action>::type broadcast_impl(Action const & act,std::vector<hpx::id_type> const & ids,std::size_t global_idx,std::false_type,Ts const &...vs)616 broadcast_impl( 617 Action const & act 618 , std::vector<hpx::id_type> const & ids 619 , std::size_t global_idx 620 , std::false_type 621 , Ts const&... vs 622 ) 623 { 624 typedef 625 typename broadcast_result<Action>::action_result 626 action_result; 627 typedef 628 typename broadcast_result<Action>::type 629 result_type; 630 631 //if(ids.empty()) return hpx::lcos::make_ready_future(result_type()); 632 if(ids.empty()) return result_type(); 633 634 std::size_t const local_fanout = HPX_BROADCAST_FANOUT; 635 std::size_t local_size = (std::min)(ids.size(), local_fanout); 636 std::size_t fanout = util::calculate_fanout(ids.size(), local_fanout); 637 638 std::vector<hpx::future<result_type> > broadcast_futures; 639 broadcast_futures.reserve(local_size + (ids.size()/fanout) + 1); 640 for(std::size_t i = 0; i != local_size; ++i) 641 { 642 broadcast_invoke( 643 act 644 , broadcast_futures 645 , &wrap_into_vector<action_result> 646 , ids[i] 647 , global_idx + i 648 , vs... 649 ); 650 } 651 652 if(ids.size() > local_fanout) 653 { 654 std::size_t applied = local_fanout; 655 std::vector<hpx::id_type>::const_iterator it = 656 ids.begin() + local_fanout; 657 658 typedef 659 typename detail::make_broadcast_action< 660 Action 661 >::type 662 broadcast_impl_action; 663 664 while(it != ids.end()) 665 { 666 HPX_ASSERT(ids.size() >= applied); 667 668 std::size_t next_fan = (std::min)(fanout, ids.size() - applied); 669 std::vector<hpx::id_type> ids_next(it, it + next_fan); 670 671 hpx::id_type id(ids_next[0]); 672 broadcast_futures.push_back( 673 hpx::detail::async_colocated<broadcast_impl_action>( 674 id 675 , act 676 , std::move(ids_next) 677 , global_idx + applied 678 , std::false_type() 679 , vs... 680 ) 681 ); 682 683 applied += next_fan; 684 it += next_fan; 685 } 686 } 687 688 return hpx::when_all(broadcast_futures). 689 then(&return_result_type<action_result>).get(); 690 } 691 692 /////////////////////////////////////////////////////////////////////// 693 template < 694 typename Action 695 , typename ...Ts 696 > 697 void broadcast_apply_impl(Action const & act,std::vector<hpx::id_type> const & ids,std::size_t global_idx,Ts const &...vs)698 broadcast_apply_impl( 699 Action const & act 700 , std::vector<hpx::id_type> const & ids 701 , std::size_t global_idx 702 , Ts const&... vs 703 ) 704 { 705 if(ids.empty()) return; 706 707 std::size_t const local_fanout = HPX_BROADCAST_FANOUT; 708 std::size_t local_size = (std::min)(ids.size(), local_fanout); 709 710 for(std::size_t i = 0; i != local_size; ++i) 711 { 712 broadcast_invoke_apply( 713 act 714 , ids[i] 715 , global_idx + i 716 , vs... 717 ); 718 } 719 720 if(ids.size() > local_fanout) 721 { 722 std::size_t applied = local_fanout; 723 std::vector<hpx::id_type>::const_iterator it = 724 ids.begin() + local_fanout; 725 726 typedef 727 typename detail::make_broadcast_apply_action< 728 Action 729 >::type 730 broadcast_impl_action; 731 732 std::size_t fanout = util::calculate_fanout(ids.size(), local_fanout); 733 while(it != ids.end()) 734 { 735 HPX_ASSERT(ids.size() >= applied); 736 737 std::size_t next_fan = (std::min)(fanout, ids.size() - applied); 738 std::vector<hpx::id_type> ids_next(it, it + next_fan); 739 740 hpx::id_type id(ids_next[0]); 741 hpx::detail::apply_colocated<broadcast_impl_action>( 742 id 743 , act 744 , std::move(ids_next) 745 , global_idx + applied 746 , vs... 747 ); 748 749 applied += next_fan; 750 it += next_fan; 751 } 752 } 753 } 754 } 755 756 /////////////////////////////////////////////////////////////////////////// 757 template < 758 typename Action 759 , typename ...Ts 760 > 761 hpx::future< 762 typename detail::broadcast_result<Action>::type 763 > broadcast(std::vector<hpx::id_type> const & ids,Ts const &...vs)764 broadcast( 765 std::vector<hpx::id_type> const & ids 766 , Ts const&... vs) 767 { 768 typedef 769 typename detail::make_broadcast_action<Action>::type 770 broadcast_impl_action; 771 typedef 772 typename detail::broadcast_result<Action>::action_result 773 action_result; 774 775 if (ids.empty()) 776 { 777 typedef typename detail::broadcast_result<Action>::type 778 result_type; 779 780 return hpx::make_exceptional_future<result_type>( 781 HPX_GET_EXCEPTION(bad_parameter, 782 "hpx::lcos::broadcast", 783 "empty list of targets for broadcast operation") 784 ); 785 } 786 787 return 788 hpx::detail::async_colocated<broadcast_impl_action>( 789 ids[0] 790 , Action() 791 , ids 792 , std::size_t(0) 793 , std::is_void<action_result>() 794 , vs... 795 ); 796 } 797 798 template < 799 typename Component, typename Signature, typename Derived 800 , typename ...Ts 801 > 802 hpx::future< 803 typename detail::broadcast_result<Derived>::type 804 > broadcast(hpx::actions::basic_action<Component,Signature,Derived>,std::vector<hpx::id_type> const & ids,Ts const &...vs)805 broadcast( 806 hpx::actions::basic_action<Component, Signature, Derived> /* act */ 807 , std::vector<hpx::id_type> const & ids 808 , Ts const&... vs) 809 { 810 return broadcast<Derived>( 811 ids 812 , vs... 813 ); 814 } 815 816 /////////////////////////////////////////////////////////////////////////// 817 template < 818 typename Action 819 , typename ...Ts 820 > 821 void broadcast_apply(std::vector<hpx::id_type> const & ids,Ts const &...vs)822 broadcast_apply( 823 std::vector<hpx::id_type> const & ids 824 , Ts const&... vs) 825 { 826 typedef 827 typename detail::make_broadcast_apply_action<Action>::type 828 broadcast_impl_action; 829 830 if (ids.empty()) 831 { 832 HPX_THROW_EXCEPTION(hpx::bad_parameter, 833 "hpx::lcos::broadcast_apply", 834 "empty list of targets for broadcast operation"); 835 return; 836 } 837 838 hpx::detail::apply_colocated<broadcast_impl_action>( 839 ids[0] 840 , Action() 841 , ids 842 , 0 843 , vs... 844 ); 845 } 846 847 template < 848 typename Component, typename Signature, typename Derived 849 , typename ...Ts 850 > 851 void broadcast_apply(hpx::actions::basic_action<Component,Signature,Derived>,std::vector<hpx::id_type> const & ids,Ts const &...vs)852 broadcast_apply( 853 hpx::actions::basic_action<Component, Signature, Derived> /* act */ 854 , std::vector<hpx::id_type> const & ids 855 , Ts const&... vs) 856 { 857 broadcast_apply<Derived>( 858 ids 859 , vs... 860 ); 861 } 862 863 /////////////////////////////////////////////////////////////////////////// 864 template < 865 typename Action 866 , typename ...Ts 867 > 868 hpx::future< 869 typename detail::broadcast_result<Action>::type 870 > broadcast_with_index(std::vector<hpx::id_type> const & ids,Ts const &...vs)871 broadcast_with_index( 872 std::vector<hpx::id_type> const & ids 873 , Ts const&... vs) 874 { 875 return broadcast<detail::broadcast_with_index<Action> >( 876 ids 877 , vs... 878 ); 879 } 880 881 template < 882 typename Component, typename Signature, typename Derived 883 , typename ...Ts 884 > 885 hpx::future< 886 typename detail::broadcast_result<Derived>::type 887 > broadcast_with_index(hpx::actions::basic_action<Component,Signature,Derived>,std::vector<hpx::id_type> const & ids,Ts const &...vs)888 broadcast_with_index( 889 hpx::actions::basic_action<Component, Signature, Derived> /* act */ 890 , std::vector<hpx::id_type> const & ids 891 , Ts const&... vs) 892 { 893 return broadcast<detail::broadcast_with_index<Derived> >( 894 ids 895 , vs... 896 ); 897 } 898 899 /////////////////////////////////////////////////////////////////////////// 900 template < 901 typename Action 902 , typename ...Ts 903 > 904 void broadcast_apply_with_index(std::vector<hpx::id_type> const & ids,Ts const &...vs)905 broadcast_apply_with_index( 906 std::vector<hpx::id_type> const & ids 907 , Ts const&... vs) 908 { 909 broadcast_apply<detail::broadcast_with_index<Action> >( 910 ids 911 , vs... 912 ); 913 } 914 915 template < 916 typename Component, typename Signature, typename Derived 917 , typename ...Ts 918 > 919 void broadcast_apply_with_index(hpx::actions::basic_action<Component,Signature,Derived>,std::vector<hpx::id_type> const & ids,Ts const &...vs)920 broadcast_apply_with_index( 921 hpx::actions::basic_action<Component, Signature, Derived> /* act */ 922 , std::vector<hpx::id_type> const & ids 923 , Ts const&... vs) 924 { 925 broadcast_apply<detail::broadcast_with_index<Derived> >( 926 ids 927 , vs... 928 ); 929 } 930 }} 931 932 /////////////////////////////////////////////////////////////////////////////// 933 #define HPX_REGISTER_BROADCAST_APPLY_ACTION_DECLARATION(...) \ 934 HPX_REGISTER_BROADCAST_APPLY_ACTION_DECLARATION_(__VA_ARGS__) \ 935 /**/ 936 #define HPX_REGISTER_BROADCAST_APPLY_ACTION_DECLARATION_(...) \ 937 HPX_PP_EXPAND(HPX_PP_CAT( \ 938 HPX_REGISTER_BROADCAST_APPLY_ACTION_DECLARATION_, \ 939 HPX_PP_NARGS(__VA_ARGS__) \ 940 )(__VA_ARGS__)) \ 941 /**/ 942 943 #define HPX_REGISTER_BROADCAST_APPLY_ACTION_DECLARATION_1(Action) \ 944 HPX_REGISTER_BROADCAST_APPLY_ACTION_DECLARATION_2(Action, Action) \ 945 /**/ 946 #define HPX_REGISTER_BROADCAST_APPLY_ACTION_DECLARATION_2(Action, Name) \ 947 HPX_REGISTER_ACTION_DECLARATION( \ 948 ::hpx::lcos::detail::make_broadcast_apply_action<Action>::type \ 949 , HPX_PP_CAT(broadcast_apply_, Name) \ 950 ) \ 951 HPX_REGISTER_APPLY_COLOCATED_DECLARATION( \ 952 ::hpx::lcos::detail::make_broadcast_apply_action<Action>::type \ 953 , HPX_PP_CAT(apply_colocated_broadcast_, Name) \ 954 ) \ 955 /**/ 956 957 /////////////////////////////////////////////////////////////////////////////// 958 #define HPX_REGISTER_BROADCAST_APPLY_ACTION(...) \ 959 HPX_REGISTER_BROADCAST_APPLY_ACTION_(__VA_ARGS__) \ 960 /**/ 961 #define HPX_REGISTER_BROADCAST_APPLY_ACTION_(...) \ 962 HPX_PP_EXPAND(HPX_PP_CAT( \ 963 HPX_REGISTER_BROADCAST_APPLY_ACTION_, HPX_PP_NARGS(__VA_ARGS__) \ 964 )(__VA_ARGS__)) \ 965 /**/ 966 967 #define HPX_REGISTER_BROADCAST_APPLY_ACTION_1(Action) \ 968 HPX_REGISTER_BROADCAST_APPLY_ACTION_2(Action, Action) \ 969 /**/ 970 #define HPX_REGISTER_BROADCAST_APPLY_ACTION_2(Action, Name) \ 971 HPX_REGISTER_ACTION( \ 972 ::hpx::lcos::detail::make_broadcast_apply_action<Action>::type \ 973 , HPX_PP_CAT(broadcast_apply_, Name) \ 974 ) \ 975 HPX_REGISTER_APPLY_COLOCATED( \ 976 ::hpx::lcos::detail::make_broadcast_apply_action<Action>::type \ 977 , HPX_PP_CAT(apply_colocated_broadcast_, Name) \ 978 ) \ 979 /**/ 980 981 /////////////////////////////////////////////////////////////////////////////// 982 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_DECLARATION(...) \ 983 HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_DECLARATION_(__VA_ARGS__) \ 984 /**/ 985 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_DECLARATION_(...) \ 986 HPX_PP_EXPAND(HPX_PP_CAT( \ 987 HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_DECLARATION_, \ 988 HPX_PP_NARGS(__VA_ARGS__) \ 989 )(__VA_ARGS__)) \ 990 /**/ 991 992 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_DECLARATION_1(Action) \ 993 HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_DECLARATION_2( \ 994 Action, Action) \ 995 /**/ 996 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_DECLARATION_2( \ 997 Action, Name) \ 998 HPX_REGISTER_ACTION_DECLARATION( \ 999 ::hpx::lcos::detail::make_broadcast_apply_action< \ 1000 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1001 >::type \ 1002 , HPX_PP_CAT(broadcast_apply_with_index_, Name) \ 1003 ) \ 1004 HPX_REGISTER_APPLY_COLOCATED_DECLARATION( \ 1005 ::hpx::lcos::detail::make_broadcast_apply_action< \ 1006 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1007 >::type \ 1008 , HPX_PP_CAT(apply_colocated_broadcast_with_index_, Name) \ 1009 ) \ 1010 /**/ 1011 1012 /////////////////////////////////////////////////////////////////////////////// 1013 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION(...) \ 1014 HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_(__VA_ARGS__) \ 1015 /**/ 1016 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_(...) \ 1017 HPX_PP_EXPAND(HPX_PP_CAT( \ 1018 HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_, \ 1019 HPX_PP_NARGS(__VA_ARGS__) \ 1020 )(__VA_ARGS__)) \ 1021 /**/ 1022 1023 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_1(Action) \ 1024 HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_2(Action, Action) \ 1025 /**/ 1026 #define HPX_REGISTER_BROADCAST_APPLY_WITH_INDEX_ACTION_2(Action, Name) \ 1027 HPX_REGISTER_ACTION( \ 1028 ::hpx::lcos::detail::make_broadcast_apply_action< \ 1029 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1030 >::type \ 1031 , HPX_PP_CAT(broadcast_apply_with_index_, Name) \ 1032 ) \ 1033 HPX_REGISTER_APPLY_COLOCATED( \ 1034 ::hpx::lcos::detail::make_broadcast_apply_action< \ 1035 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1036 >::type \ 1037 , HPX_PP_CAT(apply_colocated_broadcast_with_index_, Name) \ 1038 ) \ 1039 /**/ 1040 1041 /////////////////////////////////////////////////////////////////////////////// 1042 #define HPX_REGISTER_BROADCAST_ACTION_DECLARATION(...) \ 1043 HPX_REGISTER_BROADCAST_ACTION_DECLARATION_(__VA_ARGS__) \ 1044 /**/ 1045 #define HPX_REGISTER_BROADCAST_ACTION_DECLARATION_(...) \ 1046 HPX_PP_EXPAND(HPX_PP_CAT( \ 1047 HPX_REGISTER_BROADCAST_ACTION_DECLARATION_, \ 1048 HPX_PP_NARGS(__VA_ARGS__) \ 1049 )(__VA_ARGS__)) \ 1050 /**/ 1051 1052 #define HPX_REGISTER_BROADCAST_ACTION_DECLARATION_1(Action) \ 1053 HPX_REGISTER_BROADCAST_ACTION_DECLARATION_2(Action, Action) \ 1054 /**/ 1055 #define HPX_REGISTER_BROADCAST_ACTION_DECLARATION_2(Action, Name) \ 1056 HPX_REGISTER_ACTION_DECLARATION( \ 1057 ::hpx::lcos::detail::make_broadcast_action<Action>::type \ 1058 , HPX_PP_CAT(broadcast_, Name) \ 1059 ) \ 1060 HPX_REGISTER_ASYNC_COLOCATED_DECLARATION( \ 1061 ::hpx::lcos::detail::make_broadcast_action<Action>::type \ 1062 , HPX_PP_CAT(async_colocated_broadcast_, Name) \ 1063 ) \ 1064 /**/ 1065 1066 /////////////////////////////////////////////////////////////////////////////// 1067 #define HPX_REGISTER_BROADCAST_ACTION(...) \ 1068 HPX_REGISTER_BROADCAST_ACTION_(__VA_ARGS__) \ 1069 /**/ 1070 #define HPX_REGISTER_BROADCAST_ACTION_(...) \ 1071 HPX_PP_EXPAND(HPX_PP_CAT( \ 1072 HPX_REGISTER_BROADCAST_ACTION_, HPX_PP_NARGS(__VA_ARGS__) \ 1073 )(__VA_ARGS__)) \ 1074 /**/ 1075 1076 #define HPX_REGISTER_BROADCAST_ACTION_1(Action) \ 1077 HPX_REGISTER_BROADCAST_ACTION_2(Action, Action) \ 1078 /**/ 1079 #define HPX_REGISTER_BROADCAST_ACTION_2(Action, Name) \ 1080 HPX_REGISTER_ACTION( \ 1081 ::hpx::lcos::detail::make_broadcast_action<Action>::type \ 1082 , HPX_PP_CAT(broadcast_, Name) \ 1083 ) \ 1084 HPX_REGISTER_ASYNC_COLOCATED( \ 1085 ::hpx::lcos::detail::make_broadcast_action<Action>::type \ 1086 , HPX_PP_CAT(async_colocated_broadcast_, Name) \ 1087 ) \ 1088 /**/ 1089 #define HPX_REGISTER_BROADCAST_ACTION_ID(Action, Name, Id) \ 1090 HPX_REGISTER_ACTION_ID( \ 1091 ::hpx::lcos::detail::make_broadcast_action<Action>::type \ 1092 , HPX_PP_CAT(broadcast_, Name) \ 1093 , Id \ 1094 ) \ 1095 HPX_REGISTER_ASYNC_COLOCATED( \ 1096 ::hpx::lcos::detail::make_broadcast_action<Action>::type \ 1097 , HPX_PP_CAT(async_colocated_broadcast_, Name) \ 1098 ) \ 1099 /**/ 1100 1101 /////////////////////////////////////////////////////////////////////////////// 1102 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_DECLARATION(...) \ 1103 HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_DECLARATION_(__VA_ARGS__) \ 1104 /**/ 1105 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_DECLARATION_(...) \ 1106 HPX_PP_EXPAND(HPX_PP_CAT( \ 1107 HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_DECLARATION_, \ 1108 HPX_PP_NARGS(__VA_ARGS__) \ 1109 )(__VA_ARGS__)) \ 1110 /**/ 1111 1112 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_DECLARATION_1(Action) \ 1113 HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_DECLARATION_2(Action, Action) \ 1114 /**/ 1115 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_DECLARATION_2(Action, Name) \ 1116 HPX_REGISTER_ACTION_DECLARATION( \ 1117 ::hpx::lcos::detail::make_broadcast_action< \ 1118 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1119 >::type \ 1120 , HPX_PP_CAT(broadcast_with_index_, Name) \ 1121 ) \ 1122 HPX_REGISTER_ASYNC_COLOCATED_DECLARATION( \ 1123 ::hpx::lcos::detail::make_broadcast_action< \ 1124 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1125 >::type \ 1126 , HPX_PP_CAT(async_colocated_broadcast_with_index_, Name) \ 1127 ) \ 1128 /**/ 1129 1130 /////////////////////////////////////////////////////////////////////////////// 1131 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION(...) \ 1132 HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_(__VA_ARGS__) \ 1133 /**/ 1134 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_(...) \ 1135 HPX_PP_EXPAND(HPX_PP_CAT( \ 1136 HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_, \ 1137 HPX_PP_NARGS(__VA_ARGS__) \ 1138 )(__VA_ARGS__)) \ 1139 /**/ 1140 1141 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_1(Action) \ 1142 HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_2(Action, Action) \ 1143 /**/ 1144 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_2(Action, Name) \ 1145 HPX_REGISTER_ACTION( \ 1146 ::hpx::lcos::detail::make_broadcast_action< \ 1147 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1148 >::type \ 1149 , HPX_PP_CAT(broadcast_with_index_, Name) \ 1150 ) \ 1151 HPX_REGISTER_ASYNC_COLOCATED( \ 1152 ::hpx::lcos::detail::make_broadcast_action< \ 1153 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1154 >::type \ 1155 , HPX_PP_CAT(async_colocated_broadcast_with_index_, Name) \ 1156 ) \ 1157 /**/ 1158 #define HPX_REGISTER_BROADCAST_WITH_INDEX_ACTION_ID(Action, Name, Id) \ 1159 HPX_REGISTER_ACTION_ID( \ 1160 ::hpx::lcos::detail::make_broadcast_action< \ 1161 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1162 >::type \ 1163 , HPX_PP_CAT(broadcast_with_index_, Name) \ 1164 , Id \ 1165 ) \ 1166 HPX_REGISTER_ASYNC_COLOCATED( \ 1167 ::hpx::lcos::detail::make_broadcast_action< \ 1168 ::hpx::lcos::detail::broadcast_with_index<Action> \ 1169 >::type \ 1170 , HPX_PP_CAT(async_colocated_broadcast_with_index_, Name) \ 1171 ) \ 1172 /**/ 1173 1174 #endif 1175 1176 #endif // DOXYGEN 1177