1 /* 2 This file is part of MADNESS. 3 4 Copyright (C) 2007,2010 Oak Ridge National Laboratory 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 20 For more information please contact: 21 22 Robert J. Harrison 23 Oak Ridge National Laboratory 24 One Bethel Valley Road 25 P.O. Box 2008, MS-6367 26 27 email: harrisonrj@ornl.gov 28 tel: 865-241-3937 29 fax: 865-572-0680 30 */ 31 32 /** 33 \file world_object.h 34 \brief Defines and implements \c WorldObject. 35 \ingroup world_object 36 */ 37 38 #ifndef MADNESS_WORLD_WORLD_OBJECT_H__INCLUDED 39 #define MADNESS_WORLD_WORLD_OBJECT_H__INCLUDED 40 41 #include <type_traits> 42 #include <madness/world/thread.h> 43 #include <madness/world/world_task_queue.h> 44 45 /// \addtogroup world_object 46 /// @{ 47 48 namespace madness { 49 50 template <typename> class WorldObject; 51 52 namespace detail { 53 54 /// Common base class for pending messages to ensure in-order processing. 55 56 /// To eliminate synchronization when a distributed object is first 57 /// constructed, we buffer pending messages for containers that 58 /// don't have their ID yet registered. 59 struct PendingMsg { 60 uniqueidT id; 61 am_handlerT handler; 62 AmArg* arg; 63 PendingMsgPendingMsg64 PendingMsg(uniqueidT id, am_handlerT handler, const AmArg& arg) 65 : id(id), handler(handler), arg(copy_am_arg(arg)) {} 66 invokehandlerPendingMsg67 void invokehandler() { 68 handler(*arg); 69 free_am_arg(arg); 70 } 71 }; 72 73 /// \todo Brief description needed. 74 75 /// We cannot use the normal task forwarding stuff here because pending 76 /// messages can creating tasks are must be correctly handled. The 77 /// following code does not easily merge with the send handlers since 78 /// the task layer is more restrictive on the copy capability of 79 /// arguments. 80 /// 81 /// It is also annoying that info needs to be broken into two parts so 82 /// that it \c id and \c ref are properly serialized. We need to have 83 /// \c id correctly aligned via \c opaque_wrap, but \c ref cannot be 84 /// serialized that way. Thus we break the class into two parts. 85 /// 86 /// Info stored for AM method forwarding. 87 /// \tparam memfunT Description needed. 88 /// \todo Verify & complete; what is AM? 89 template <typename memfunT> 90 struct info_base { 91 // id must be at front ... see peek. 92 uniqueidT id; ///< \todo Description needed. Context with the "see peek" comment above? 93 ProcessID requestor; ///< \todo Description needed. 94 memfunT memfun; ///< \todo Description needed. 95 TaskAttributes attr; ///< \todo Description needed. 96 97 protected: 98 info_baseinfo_base99 info_base() {} 100 101 /// \todo Constructor that [brief description needed]. 102 103 /// \todo Descriptions needed. 104 /// \param[in] id Description needed. 105 /// \param[in] requestor Description needed. 106 /// \param memfun Verify: The member function to be invoked for the task. 107 /// \param[in] attr Description needed. 108 info_base(const uniqueidT& id, ProcessID requestor, memfunT memfun, 109 const TaskAttributes& attr=TaskAttributes()) idinfo_base110 : id(id) 111 , requestor(requestor) 112 , memfun(memfun) 113 , attr(attr) {} 114 115 /// Serializes a \c info_base for I/O. 116 117 /// \tparam Archive The type of I/O archive. 118 /// \param[in,out] ar The I/O archive. 119 template <typename Archive> serializeinfo_base120 void serialize(const Archive& ar) { 121 ar & archive::wrap_opaque(*this); // Must be opaque ... see peek. 122 } 123 }; // struct info_base 124 125 /// \todo Brief description needed. 126 127 /// \todo Descriptions needed. 128 /// \tparam memfunT Verify: Signature of the member function in the derived class to be invoked for the task. 129 template <typename memfunT> 130 struct info : public info_base<memfunT> { 131 /// Future for a return value of the memory function. \todo Verify. 132 typedef Future< REMFUTURE(MEMFUN_RETURNT(memfunT)) > futureT; 133 /// \todo Description needed. 134 typedef RemoteReference< FutureImpl< REMFUTURE(MEMFUN_RETURNT(memfunT)) > > refT; 135 136 refT ref; ///< \todo Description needed. 137 infoinfo138 info() : info_base<memfunT>() {} 139 140 /// \todo Constructor that [brief description needed]. 141 142 /// \todo Descriptions needed. 143 /// \param[in] arg Description needed. infoinfo144 info(const AmArg& arg) : 145 info_base<memfunT>() 146 { 147 arg & *this; 148 } 149 150 /// \todo Constructor that [brief description needed]. 151 152 /// \todo Descriptions needed. 153 /// \param[in] id Description needed. 154 /// \param[in] requestor Description needed. 155 /// \param memfun Verify: The member function to be invoked for the task. 156 /// \param[in] ref Description needed. 157 /// \param[in] attr Description needed. 158 info(const uniqueidT& id, ProcessID requestor, memfunT memfun, 159 const refT& ref, const TaskAttributes& attr=TaskAttributes()) 160 : info_base<memfunT>(id, requestor, memfun, attr), ref(ref) 161 {} 162 163 /// Serializes a \c info for I/O. 164 165 /// \tparam Archive the type of I/O archive. 166 /// \param[in] ar The I/O archive. 167 template <typename Archive> serializeinfo168 void serialize(const Archive& ar) { 169 info_base<memfunT>::serialize(ar); 170 ar & ref; 171 } 172 }; // struct info 173 174 /// Extract the unique object ID from an incoming active message header. 175 176 /// We deserialize the header and all arguments at the same 177 /// time to simplify the code. However, it is common that 178 /// when sending a message to an item in a container to 179 /// include a pointer to the container itself. But this 180 /// breaks if the container is not initialized since the 181 /// deserialization throws if the object is not initialized 182 /// (which seems preferable to a hidden race condition). Hence, 183 /// we use this routine to extract the unique ID from the very 184 /// front of the \c info structure. For efficiency we here rely 185 /// upon the serialization of \c info being opaque and the 186 /// ID being at the front of \c info. 187 /// 188 /// \todo Verify parameter description. 189 /// \param[in] arg The active message header. peek(const AmArg & arg)190 static inline const uniqueidT& peek(const AmArg& arg) { 191 return *((uniqueidT*)(arg.buf())); 192 } 193 194 195 /// \todo Brief description needed. 196 197 /// \todo Descriptions needed. 198 /// \tparam objT Description needed. 199 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 200 /// \tparam Enabler Description needed. 201 template <typename objT, typename memfnT, typename Enabler = void> 202 struct WorldObjectTaskHelper { 203 /// \todo Description needed. 204 typedef typename std::conditional<memfunc_traits<memfnT>::constness, 205 const objT*, objT*>::type ptrT; 206 207 /// \todo Description needed. 208 typedef MemFuncWrapper<ptrT, memfnT, typename result_of<memfnT>::type> wrapperT; 209 210 211 /// \todo Brief description needed. 212 213 /// \todo Descriptions needed. 214 /// \param[in] obj Description needed. 215 /// \param memfn Verify: The member function to be invoked for the task. 216 /// \return Description needed. make_task_fnWorldObjectTaskHelper217 static wrapperT make_task_fn(const objT* obj, memfnT memfn) { 218 return wrapperT(const_cast<ptrT>(obj), memfn); 219 } 220 221 222 /// \todo Brief description needed. 223 224 /// \todo Descriptions needed. 225 /// \param[in] obj Description needed. 226 /// \param memfn Verify: The member function to be invoked for the task. 227 /// \return Description needed. make_task_fnWorldObjectTaskHelper228 static wrapperT make_task_fn(objT* obj, memfnT memfn) { 229 return wrapperT(const_cast<ptrT>(obj), memfn); 230 } 231 232 233 /// \todo Brief description needed. 234 235 /// \todo Descriptions needed. 236 /// \param[in] obj Description needed. 237 /// \param memfn Verify: The member function to be invoked for the task. 238 /// \return Description needed. make_task_fnWorldObjectTaskHelper239 static wrapperT make_task_fn(const WorldObject<objT>* obj, memfnT memfn) { 240 return make_task_fn(static_cast<const objT*>(obj), memfn); 241 } 242 243 /// \todo Brief description needed. 244 245 /// \todo Descriptions needed. 246 /// \param[in] obj Description needed. 247 /// \param memfn Verify: The member function to be invoked for the task. 248 /// \return Description needed. make_task_fnWorldObjectTaskHelper249 static wrapperT make_task_fn(WorldObject<objT>* obj, memfnT memfn) { 250 return make_task_fn(static_cast<objT*>(obj), memfn); 251 } 252 }; // struct WorldObjectTaskHelper 253 254 255 #ifndef MADNESS_DISABLE_SHARED_FROM_THIS 256 // Disable the use of std::enable_shared_from_this if we are using MADNESS's 257 // implementation since weak_ptr is not fully implemented. 258 259 260 /// \todo Brief description needed. 261 262 /// \todo Descriptions needed. 263 /// \tparam objT Description needed. 264 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 265 template <typename objT, typename memfnT> 266 struct WorldObjectTaskHelper<objT, memfnT, 267 typename std::enable_if< std::is_base_of<std::enable_shared_from_this<objT>, objT>::value >::type> 268 { 269 /// \todo Description needed. 270 typedef typename std::conditional<memfunc_traits<memfnT>::constness, 271 const objT*, objT*>::type ptrT; 272 273 /// \todo Description needed. 274 typedef typename std::conditional<memfunc_traits<memfnT>::constness, 275 std::shared_ptr<const objT>, std::shared_ptr<objT> >::type shared_ptrT; 276 277 /// \todo Description needed. 278 typedef MemFuncWrapper<shared_ptrT, memfnT, typename result_of<memfnT>::type> wrapperT; 279 280 281 /// \todo Brief description needed. 282 283 /// \todo Descriptions needed. 284 /// \param[in] obj Description needed. 285 /// \param memfn Verify: The member function to be invoked for the task. 286 /// \return Description needed. 287 static wrapperT make_task_fn(const objT* obj, memfnT memfn) { 288 return wrapperT(const_cast<ptrT>(obj)->shared_from_this(), memfn); 289 } 290 291 292 /// \todo Brief description needed. 293 294 /// \todo Descriptions needed. 295 /// \param[in] obj Description needed. 296 /// \param memfn Verify: The member function to be invoked for the task. 297 /// \return Description needed. 298 static wrapperT make_task_fn(objT* obj, memfnT memfn) { 299 return wrapperT(const_cast<ptrT>(obj)->shared_from_this(), memfn); 300 } 301 302 303 /// \todo Brief description needed. 304 305 /// \todo Descriptions needed. 306 /// \param[in] obj Description needed. 307 /// \param memfn Verify: The member function to be invoked for the task. 308 /// \return Description needed. 309 static wrapperT make_task_fn(const WorldObject<objT>* obj, memfnT memfn) { 310 return make_task_fn(static_cast<const objT*>(obj), memfn); 311 } 312 313 314 /// \todo Brief description needed. 315 316 /// \todo Descriptions needed. 317 /// \param[in] obj Description needed. 318 /// \param memfn Verify: The member function to be invoked for the task. 319 /// \return Description needed. 320 static wrapperT make_task_fn(WorldObject<objT>* obj, memfnT memfn) { 321 return make_task_fn(static_cast<objT*>(obj), memfn); 322 } 323 }; // struct WorldObjectTaskHelper 324 325 #endif // MADNESS_DISABLE_SHARED_FROM_THIS 326 327 } // namespace detail 328 329 330 /// Implements most parts of a globally addressable object (via unique ID). 331 332 /// This class is deliberately not default constructible and does 333 /// not support assignment or copying. This ensures that each instance 334 /// is unique. Have a look at \c madness::WorldContainer for an example 335 /// of wrapping this using the PIMPL idiom and a shared pointer. 336 /// 337 /// When deriving classes: 338 /// -# Derived class has `WorldObject<Derived>` as a public base class. 339 /// -# Derived constructor: 340 /// -# invokes `WorldObject<Derived>(world)` constructor. 341 /// -# invokes `process_pending()`. 342 /// -# Derived destructor must either be deferred or preceeded by `gop.fence()`. 343 /// -# Derived class must have at least one virtual function for serialization 344 /// of derived class pointers to be cast to the appropriate type. 345 /// 346 /// Note that \c world is exposed for convenience as a public data member. 347 /// \tparam Derived The derived class. \c WorldObject is a curiously 348 /// recurring template pattern. 349 template <class Derived> 350 class WorldObject { 351 public: 352 /// \todo Description needed. 353 typedef WorldObject<Derived> objT; 354 355 // copy ctor must be enabled to permit RVO; in C++17 will not need this 356 WorldObject(const WorldObject& other) : world(other.world) { abort(); } 357 // no copy 358 WorldObject& operator=(const WorldObject&) = delete; 359 360 private: 361 /// \todo Description needed. 362 typedef std::list<detail::PendingMsg> pendingT; 363 364 /// \todo Description needed. 365 typedef detail::voidT voidT; 366 367 World& world; ///< The \c World this object belongs to. (Think globally, act locally). 368 369 // The order here matters in a multi-threaded world 370 volatile bool ready; ///< True if ready to rock 'n roll. 371 ProcessID me; ///< Rank of self. 372 uniqueidT objid; ///< Sense of self. 373 374 375 static Spinlock pending_mutex; ///< \todo Description needed. 376 static volatile pendingT pending; ///< Buffer for pending messages. 377 378 379 /// \todo Complete: Determine if [unknown] is ready (for ...). 380 381 /// The slightly convoluted logic is to ensure ordering when 382 /// processing pending messages. If a new message arrives 383 /// while processing incoming messages it must be queued. 384 /// 385 /// - If the object does not exist ---> not ready. 386 /// - If the object exists and is ready ---> ready. 387 /// - If the object exists and is not ready then 388 /// - if we are doing a queued/pending message --> ready. 389 /// - else this is a new message --> not ready. 390 /// 391 /// \param[in] id Description needed. 392 /// \param[in,out] obj Description needed. 393 /// \param[in] arg Description needed. 394 /// \param[in,out] ptr Description needed. 395 /// \return Description needed. 396 /// \todo Parameter/return descriptions needed. 397 static bool is_ready(const uniqueidT& id, objT*& obj, const AmArg& arg, am_handlerT ptr) { 398 obj = static_cast<objT*>(arg.get_world()->template ptr_from_id<Derived>(id)); 399 400 if (obj) { 401 if (obj->ready || arg.is_pending()) return true; 402 } 403 404 MADNESS_PRAGMA_CLANG(diagnostic push) 405 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") 406 407 ScopedMutex<Spinlock> lock(pending_mutex); // BEGIN CRITICAL SECTION 408 409 if (!obj) obj = static_cast<objT*>(arg.get_world()->template ptr_from_id<Derived>(id)); 410 411 if (obj) { 412 if (obj->ready || arg.is_pending()) 413 return true; // END CRITICAL SECTION 414 } 415 const_cast<AmArg&>(arg).set_pending(); 416 const_cast<pendingT&>(pending).push_back(detail::PendingMsg(id, ptr, arg)); 417 418 MADNESS_PRAGMA_CLANG(diagnostic pop) 419 420 return false; // END CRITICAL SECTION 421 } 422 423 424 /// Handler for an incoming AM. 425 426 /// \todo Descriptions needed. 427 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 428 /// \tparam arg1T Type of argument 1. 429 /// \tparam arg2T Type of argument 2. 430 /// \tparam arg3T Type of argument 3. 431 /// \tparam arg4T Type of argument 4. 432 /// \tparam arg5T Type of argument 5. 433 /// \tparam arg6T Type of argument 6. 434 /// \tparam arg7T Type of argument 7. 435 /// \tparam arg8T Type of argument 8. 436 /// \tparam arg9T Type of argument 9. 437 /// \param[in] arg Description needed. 438 template <typename memfnT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, 439 typename arg5T, typename arg6T, typename arg7T, typename arg8T, typename arg9T> 440 static void handler(const AmArg& arg) { 441 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 442 443 const uniqueidT& id = detail::peek(arg); 444 am_handlerT ptr = handler<memfnT,arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T,arg8T,arg9T>; 445 objT* obj; 446 if (is_ready(id,obj,arg,ptr)) { 447 detail::info<memfnT> info; 448 typename detail::task_arg<arg1T>::type arg1; 449 typename detail::task_arg<arg2T>::type arg2; 450 typename detail::task_arg<arg3T>::type arg3; 451 typename detail::task_arg<arg4T>::type arg4; 452 typename detail::task_arg<arg5T>::type arg5; 453 typename detail::task_arg<arg6T>::type arg6; 454 typename detail::task_arg<arg7T>::type arg7; 455 typename detail::task_arg<arg8T>::type arg8; 456 typename detail::task_arg<arg9T>::type arg9; 457 arg & info & arg1 & arg2 & arg3 & arg4 & arg5 & arg6 & arg7 & arg8 & arg9; 458 typename detail::info<memfnT>::futureT result(info.ref); 459 detail::run_function(result, task_helper::make_task_fn(obj, info.memfun), 460 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); 461 } 462 } 463 464 465 /// Handler for remote arguments. 466 467 /// \todo Descriptions needed. 468 /// \tparam taskT Description needed. 469 /// \param[in] arg Description needed. 470 template <typename taskT> 471 static void spawn_remote_task_handler(const AmArg& arg) { 472 typedef detail::WorldObjectTaskHelper<Derived, 473 typename taskT::functionT::memfn_type> task_helper; 474 475 MADNESS_ASSERT(taskT::arity <= 9u); 476 477 const uniqueidT& id = detail::peek(arg); 478 am_handlerT ptr = & objT::template spawn_remote_task_handler<taskT>; 479 objT* obj; 480 if (is_ready(id,obj,arg,ptr)) { 481 detail::info<typename taskT::functionT::memfn_type> info; 482 483 archive::BufferInputArchive input_arch = arg & info; 484 485 // Construct task 486 taskT* task = new taskT(typename taskT::futureT(info.ref), 487 task_helper::make_task_fn(obj, info.memfun), info.attr, input_arch); 488 489 // Add task to queue 490 arg.get_world()->taskq.add(task); 491 } 492 } 493 494 495 /// \todo Brief description needed. 496 497 /// \todo Descriptions needed. 498 /// \tparam T Description needed. 499 /// \param[in] f Description needed. 500 /// \return Description needed. 501 template <typename T> 502 static inline const T& am_arg(const Future<T>& f) { 503 MADNESS_ASSERT(f.probe()); // Cannot serialize unassigned futures 504 return f.get(); 505 } 506 507 508 /// \todo Brief description needed. 509 510 /// \todo Descriptions needed. 511 /// \tparam T Description needed. 512 /// \param[in] t Description needed. 513 /// \return Description needed. 514 template <typename T> 515 static inline const T& am_arg(const T& t) { 516 return t; 517 } 518 519 520 /// \todo Brief description needed. 521 522 /// \todo Descriptions needed. 523 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 524 /// \tparam a1T Type of argument 1. 525 /// \tparam a2T Type of argument 2. 526 /// \tparam a3T Type of argument 3. 527 /// \tparam a4T Type of argument 4. 528 /// \tparam a5T Type of argument 5. 529 /// \tparam a6T Type of argument 6. 530 /// \tparam a7T Type of argument 7. 531 /// \tparam a8T Type of argument 8. 532 /// \tparam a9T Type of argument 9. 533 /// \param dest Description needed. 534 /// \param memfn Verify: The member function to be invoked for the task. 535 /// \param a1 Argument 1. 536 /// \param a2 Argument 2. 537 /// \param a3 Argument 3. 538 /// \param a4 Argument 4. 539 /// \param a5 Argument 5. 540 /// \param a6 Argument 6. 541 /// \param a7 Argument 7. 542 /// \param a8 Argument 8. 543 /// \param a9 Argument 9. 544 /// \return Description needed. 545 template <typename memfnT, typename a1T, typename a2T, typename a3T, 546 typename a4T, typename a5T, typename a6T, typename a7T, 547 typename a8T, typename a9T> 548 typename detail::task_result_type<memfnT>::futureT 549 send_am(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 550 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 551 const a7T& a7, const a8T& a8, const a9T& a9) const 552 { 553 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 554 typename detail::task_result_type<memfnT>::futureT result; 555 if (dest == me) 556 detail::run_function(result, task_helper::make_task_fn(this, memfn), 557 a1, a2, a3, a4, a5, a6, a7, a8, a9); 558 else { 559 detail::info<memfnT> info(objid, me, memfn, result.remote_ref(world)); 560 world.am.send(dest, & objT::template handler<memfnT, a1T, a2T, a3T, a4T, a5T, a6T, a7T, a8T, a9T>, 561 new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9)); 562 } 563 564 return result; 565 } 566 567 568 /// \todo Brief description needed. 569 570 /// \todo Descriptions needed. 571 /// \tparam taskT Description needed. 572 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 573 /// \tparam a1T Type of argument 1. 574 /// \tparam a2T Type of argument 2. 575 /// \tparam a3T Type of argument 3. 576 /// \tparam a4T Type of argument 4. 577 /// \tparam a5T Type of argument 5. 578 /// \tparam a6T Type of argument 6. 579 /// \tparam a7T Type of argument 7. 580 /// \tparam a8T Type of argument 8. 581 /// \tparam a9T Type of argument 9. 582 /// \param dest Description needed. 583 /// \param memfn Verify: The member function to be invoked for the task. 584 /// \param a1 Argument 1. 585 /// \param a2 Argument 2. 586 /// \param a3 Argument 3. 587 /// \param a4 Argument 4. 588 /// \param a5 Argument 5. 589 /// \param a6 Argument 6. 590 /// \param a7 Argument 7. 591 /// \param a8 Argument 8. 592 /// \param a9 Argument 9. 593 /// \param attr Description needed. 594 /// \return Description needed. 595 template <typename taskT, typename memfnT, typename a1T, typename a2T, typename a3T, 596 typename a4T, typename a5T, typename a6T, typename a7T, 597 typename a8T, typename a9T> 598 typename taskT::futureT 599 send_task(ProcessID dest, memfnT memfn, const a1T& a1, 600 const a2T& a2, const a3T& a3, const a4T& a4, const a5T& a5, 601 const a6T& a6, const a7T& a7, const a8T& a8, const a9T& a9, 602 const TaskAttributes& attr) const 603 { 604 typename taskT::futureT result; 605 detail::info<memfnT> info(objid, me, memfn, result.remote_ref(world), attr); 606 world.am.send(dest, & objT::template spawn_remote_task_handler<taskT>, 607 new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9)); 608 609 return result; 610 } 611 612 protected: 613 614 /// To be called from \em derived constructor to process pending messages. 615 616 /// Cannot call this from the \c WorldObject constructor since the 617 /// derived class would not yet be fully constructed. 618 /// 619 /// \attention No incoming messages are processed until this routine is 620 /// invoked; the derived class may rely upon a well defined state 621 /// until this routine is invoked. 622 void process_pending() { 623 // Messages may be arriving while we are processing the 624 // pending queue. To maximize concurrency copy messages 625 // out of queue before processing outside critical section. 626 //int ndone = 0; 627 while (!ready) { 628 pendingT tmp; 629 630 MADNESS_PRAGMA_CLANG(diagnostic push) 631 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") 632 633 pending_mutex.lock(); // BEGIN CRITICAL SECTION 634 pendingT& nv = const_cast<pendingT&>(pending); 635 for (pendingT::iterator it=nv.begin(); it!=nv.end();) { 636 detail::PendingMsg& p = *it; 637 if (p.id == objid) { 638 tmp.push_back(p); 639 it = nv.erase(it); 640 } 641 else { 642 ++it; 643 } 644 } 645 if (tmp.size() == 0) ready=true; 646 pending_mutex.unlock(); // END CRITICAL SECTION 647 648 MADNESS_PRAGMA_CLANG(diagnostic pop) 649 650 while (tmp.size()) { 651 tmp.front().invokehandler(); 652 tmp.pop_front(); 653 //++ndone; 654 } 655 } 656 //if (ndone) std::cout << world.rank() << ":pending:" << ndone << std::endl; 657 } 658 659 660 public: 661 /// \brief Constructor that associates an object (via the derived class) 662 /// with a globally unique ID. 663 664 /// \attention The derived class MUST call \c process_pending from 665 /// its constructor to both 666 /// -# process any messages that arrived prior to construction. 667 /// -# to enable processing of future messages. 668 /// \param[in,out] world The \c World encapsulating the \"global\" domain. 669 WorldObject(World& world) 670 : world(world) 671 , ready(false) 672 , me(world.rank()) 673 , objid(world.register_ptr(static_cast<Derived*>(this))) {}; 674 675 676 /// Returns the globally unique object ID. 677 const uniqueidT& id() const { 678 return objid; 679 } 680 681 682 /// Returns a reference to the \c world. 683 World& get_world() const { 684 return const_cast<WorldObject<Derived>*>(this)->world; 685 } 686 687 688 /// \todo Brief description needed. 689 690 /// \todo Descriptions needed. 691 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 692 /// \param dest Description needed. 693 /// \param memfn Verify: The member function to be invoked for the task. 694 /// \return Description needed. 695 template <typename memfnT> 696 typename detail::task_result_type<memfnT>::futureT 697 send(ProcessID dest, memfnT memfn) const { 698 return send_am(dest, memfn, voidT::value, voidT::value, voidT::value, 699 voidT::value, voidT::value, voidT::value, voidT::value, 700 voidT::value, voidT::value); 701 } 702 703 704 /// \todo Brief description needed. 705 706 /// \todo Descriptions needed. 707 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 708 /// \tparam a1T Type of argument 1. 709 /// \param dest Description needed. 710 /// \param memfn Verify: The member function to be invoked for the task. 711 /// \param a1 Argument 1. 712 /// \return Description needed. 713 template <typename memfnT, typename a1T> 714 typename detail::task_result_type<memfnT>::futureT 715 send(ProcessID dest, memfnT memfn, const a1T& a1) const { 716 return send_am(dest, memfn, am_arg(a1), voidT::value, voidT::value, 717 voidT::value, voidT::value, voidT::value, voidT::value, 718 voidT::value, voidT::value); 719 } 720 721 722 /// \todo Brief description needed. 723 724 /// \todo Descriptions needed. 725 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 726 /// \tparam a1T Type of argument 1. 727 /// \tparam a2T Type of argument 2. 728 /// \param dest Description needed. 729 /// \param memfn Verify: The member function to be invoked for the task. 730 /// \param a1 Argument 1. 731 /// \param a2 Argument 2. 732 /// \return Description needed. 733 template <typename memfnT, typename a1T, typename a2T> 734 typename detail::task_result_type<memfnT>::futureT 735 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2) const { 736 return send_am(dest, memfn, am_arg(a1), am_arg(a2), voidT::value, 737 voidT::value, voidT::value, voidT::value, voidT::value, 738 voidT::value, voidT::value); 739 } 740 741 742 /// \todo Brief description needed. 743 744 /// \todo Descriptions needed. 745 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 746 /// \tparam a1T Type of argument 1. 747 /// \tparam a2T Type of argument 2. 748 /// \tparam a3T Type of argument 3. 749 /// \param dest Description needed. 750 /// \param memfn Verify: The member function to be invoked for the task. 751 /// \param a1 Argument 1. 752 /// \param a2 Argument 2. 753 /// \param a3 Argument 3. 754 /// \return Description needed. 755 template <typename memfnT, typename a1T, typename a2T, typename a3T> 756 typename detail::task_result_type<memfnT>::futureT 757 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 758 const a3T& a3) const 759 { 760 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3), 761 voidT::value, voidT::value, voidT::value, voidT::value, 762 voidT::value, voidT::value); 763 } 764 765 766 /// \todo Brief description needed. 767 768 /// \todo Descriptions needed. 769 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 770 /// \tparam a1T Type of argument 1. 771 /// \tparam a2T Type of argument 2. 772 /// \tparam a3T Type of argument 3. 773 /// \tparam a4T Type of argument 4. 774 /// \param dest Description needed. 775 /// \param memfn Verify: The member function to be invoked for the task. 776 /// \param a1 Argument 1. 777 /// \param a2 Argument 2. 778 /// \param a3 Argument 3. 779 /// \param a4 Argument 4. 780 /// \return Description needed. 781 template <typename memfnT, typename a1T, typename a2T, typename a3T, 782 typename a4T> 783 typename detail::task_result_type<memfnT>::futureT 784 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 785 const a3T& a3, const a4T& a4) const 786 { 787 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3), 788 am_arg(a4), voidT::value, voidT::value, voidT::value, 789 voidT::value, voidT::value); 790 } 791 792 793 /// \todo Brief description needed. 794 795 /// \todo Descriptions needed. 796 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 797 /// \tparam a1T Type of argument 1. 798 /// \tparam a2T Type of argument 2. 799 /// \tparam a3T Type of argument 3. 800 /// \tparam a4T Type of argument 4. 801 /// \tparam a5T Type of argument 5. 802 /// \param dest Description needed. 803 /// \param memfn Verify: The member function to be invoked for the task. 804 /// \param a1 Argument 1. 805 /// \param a2 Argument 2. 806 /// \param a3 Argument 3. 807 /// \param a4 Argument 4. 808 /// \param a5 Argument 5. 809 /// \return Description needed. 810 template <typename memfnT, typename a1T, typename a2T, typename a3T, 811 typename a4T, typename a5T> 812 typename detail::task_result_type<memfnT>::futureT 813 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 814 const a3T& a3, const a4T& a4, const a5T& a5) const 815 { 816 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3), 817 am_arg(a4), am_arg(a5), voidT::value, voidT::value, 818 voidT::value, voidT::value); 819 } 820 821 822 /// \todo Brief description needed. 823 824 /// \todo Descriptions needed. 825 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 826 /// \tparam a1T Type of argument 1. 827 /// \tparam a2T Type of argument 2. 828 /// \tparam a3T Type of argument 3. 829 /// \tparam a4T Type of argument 4. 830 /// \tparam a5T Type of argument 5. 831 /// \tparam a6T Type of argument 6. 832 /// \param dest Description needed. 833 /// \param memfn Verify: The member function to be invoked for the task. 834 /// \param a1 Argument 1. 835 /// \param a2 Argument 2. 836 /// \param a3 Argument 3. 837 /// \param a4 Argument 4. 838 /// \param a5 Argument 5. 839 /// \param a6 Argument 6. 840 /// \return Description needed. 841 template <typename memfnT, typename a1T, typename a2T, typename a3T, 842 typename a4T, typename a5T, typename a6T> 843 typename detail::task_result_type<memfnT>::futureT 844 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 845 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6) const 846 { 847 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3), 848 am_arg(a4), am_arg(a5), am_arg(a6), voidT::value, voidT::value, 849 voidT::value); 850 } 851 852 853 /// \todo Brief description needed. 854 855 /// \todo Descriptions needed. 856 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 857 /// \tparam a1T Type of argument 1. 858 /// \tparam a2T Type of argument 2. 859 /// \tparam a3T Type of argument 3. 860 /// \tparam a4T Type of argument 4. 861 /// \tparam a5T Type of argument 5. 862 /// \tparam a6T Type of argument 6. 863 /// \tparam a7T Type of argument 7. 864 /// \param dest Description needed. 865 /// \param memfn Verify: The member function to be invoked for the task. 866 /// \param a1 Argument 1. 867 /// \param a2 Argument 2. 868 /// \param a3 Argument 3. 869 /// \param a4 Argument 4. 870 /// \param a5 Argument 5. 871 /// \param a6 Argument 6. 872 /// \param a7 Argument 7. 873 /// \return Description needed. 874 template <typename memfnT, typename a1T, typename a2T, typename a3T, 875 typename a4T, typename a5T, typename a6T, typename a7T> 876 typename detail::task_result_type<memfnT>::futureT 877 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 878 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 879 const a7T& a7) const 880 { 881 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3), 882 am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), voidT::value, 883 voidT::value); 884 } 885 886 887 /// \todo Brief description needed. 888 889 /// \todo Descriptions needed. 890 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 891 /// \tparam a1T Type of argument 1. 892 /// \tparam a2T Type of argument 2. 893 /// \tparam a3T Type of argument 3. 894 /// \tparam a4T Type of argument 4. 895 /// \tparam a5T Type of argument 5. 896 /// \tparam a6T Type of argument 6. 897 /// \tparam a7T Type of argument 7. 898 /// \tparam a8T Type of argument 8. 899 /// \param dest Description needed. 900 /// \param memfn Verify: The member function to be invoked for the task. 901 /// \param a1 Argument 1. 902 /// \param a2 Argument 2. 903 /// \param a3 Argument 3. 904 /// \param a4 Argument 4. 905 /// \param a5 Argument 5. 906 /// \param a6 Argument 6. 907 /// \param a7 Argument 7. 908 /// \param a8 Argument 8. 909 /// \return Description needed. 910 template <typename memfnT, typename a1T, typename a2T, typename a3T, 911 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T> 912 typename detail::task_result_type<memfnT>::futureT 913 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 914 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 915 const a7T& a7, const a8T& a8) const 916 { 917 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3), 918 am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8), 919 voidT::value); 920 } 921 922 923 /// \todo Brief description needed. 924 925 /// \todo Descriptions needed. 926 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 927 /// \tparam a1T Type of argument 1. 928 /// \tparam a2T Type of argument 2. 929 /// \tparam a3T Type of argument 3. 930 /// \tparam a4T Type of argument 4. 931 /// \tparam a5T Type of argument 5. 932 /// \tparam a6T Type of argument 6. 933 /// \tparam a7T Type of argument 7. 934 /// \tparam a8T Type of argument 8. 935 /// \tparam a9T Type of argument 9. 936 /// \param dest Description needed. 937 /// \param memfn Verify: The member function to be invoked for the task. 938 /// \param a1 Argument 1. 939 /// \param a2 Argument 2. 940 /// \param a3 Argument 3. 941 /// \param a4 Argument 4. 942 /// \param a5 Argument 5. 943 /// \param a6 Argument 6. 944 /// \param a7 Argument 7. 945 /// \param a8 Argument 8. 946 /// \param a9 Argument 9. 947 /// \return Description needed. 948 template <typename memfnT, typename a1T, typename a2T, typename a3T, 949 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T, 950 typename a9T> 951 typename detail::task_result_type<memfnT>::futureT 952 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 953 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 954 const a7T& a7, const a8T& a8, const a9T& a9) const 955 { 956 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3), 957 am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8), 958 am_arg(a9)); 959 } 960 961 /// Sends task to derived class method `returnT (this->*memfn)()`. 962 963 /// \todo Descriptions needed. 964 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 965 /// \param dest Description needed. 966 /// \param memfn Verify: The member function to be invoked for the task. 967 /// \param attr Description needed. 968 /// \return Description needed. 969 template <typename memfnT> 970 typename detail::task_result_type<memfnT>::futureT 971 task(ProcessID dest, memfnT memfn, const TaskAttributes& attr = TaskAttributes()) const { 972 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 973 typedef TaskFn<typename task_helper::wrapperT> taskT; 974 if (dest == me) 975 return world.taskq.add(task_helper::make_task_fn(this, memfn), attr); 976 else 977 return send_task<taskT>(dest, memfn, voidT::value, voidT::value, 978 voidT::value, voidT::value, voidT::value, voidT::value, 979 voidT::value, voidT::value, voidT::value, attr); 980 } 981 982 /// Sends task to derived class method `returnT (this->*memfn)(a1)`. 983 984 /// \todo Descriptions needed. 985 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 986 /// \tparam a1T Type of argument 1. 987 /// \param dest Description needed. 988 /// \param memfn Verify: The member function to be invoked for the task. 989 /// \param a1 Argument 1. 990 /// \param attr Description needed. 991 /// \return Description needed. 992 template <typename memfnT, typename a1T> 993 typename detail::task_result_type<memfnT>::futureT 994 task(ProcessID dest, memfnT memfn, const a1T& a1, 995 const TaskAttributes& attr = TaskAttributes()) const 996 { 997 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 998 typedef TaskFn<typename task_helper::wrapperT, 999 typename detail::task_arg<a1T>::type> taskT; 1000 if (dest == me) 1001 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1002 a1, attr); 1003 else 1004 return send_task<taskT>(dest, memfn, am_arg(a1), voidT::value, 1005 voidT::value, voidT::value, voidT::value, voidT::value, 1006 voidT::value, voidT::value, voidT::value, attr); 1007 } 1008 1009 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2)`. 1010 1011 /// \todo Descriptions needed. 1012 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1013 /// \tparam a1T Type of argument 1. 1014 /// \tparam a2T Type of argument 2. 1015 /// \param dest Description needed. 1016 /// \param memfn Verify: The member function to be invoked for the task. 1017 /// \param a1 Argument 1. 1018 /// \param a2 Argument 2. 1019 /// \param attr Description needed. 1020 /// \return Description needed. 1021 template <typename memfnT, typename a1T, typename a2T> 1022 typename detail::task_result_type<memfnT>::futureT 1023 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1024 const TaskAttributes& attr = TaskAttributes()) const 1025 { 1026 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1027 typedef TaskFn<typename task_helper::wrapperT, 1028 typename detail::task_arg<a1T>::type, 1029 typename detail::task_arg<a2T>::type> taskT; 1030 if (dest == me) 1031 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1032 a1, a2, attr); 1033 else 1034 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1035 voidT::value, voidT::value, voidT::value, voidT::value, 1036 voidT::value, voidT::value, voidT::value, attr); 1037 } 1038 1039 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3)`. 1040 1041 /// \todo Descriptions needed. 1042 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1043 /// \tparam a1T Type of argument 1. 1044 /// \tparam a2T Type of argument 2. 1045 /// \tparam a3T Type of argument 3. 1046 /// \param dest Description needed. 1047 /// \param memfn Verify: The member function to be invoked for the task. 1048 /// \param a1 Argument 1. 1049 /// \param a2 Argument 2. 1050 /// \param a3 Argument 3. 1051 /// \param attr Description needed. 1052 /// \return Description needed. 1053 template <typename memfnT, typename a1T, typename a2T, typename a3T> 1054 typename detail::task_result_type<memfnT>::futureT 1055 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1056 const a3T& a3, const TaskAttributes& attr = TaskAttributes()) const 1057 { 1058 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1059 typedef TaskFn<typename task_helper::wrapperT, 1060 typename detail::task_arg<a1T>::type, 1061 typename detail::task_arg<a2T>::type, 1062 typename detail::task_arg<a3T>::type> taskT; 1063 if (dest == me) 1064 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1065 a1, a2, a3, attr); 1066 else 1067 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1068 am_arg(a3), voidT::value, voidT::value, voidT::value, 1069 voidT::value, voidT::value, voidT::value, attr); 1070 } 1071 1072 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4)`. 1073 1074 /// \todo Descriptions needed. 1075 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1076 /// \tparam a1T Type of argument 1. 1077 /// \tparam a2T Type of argument 2. 1078 /// \tparam a3T Type of argument 3. 1079 /// \tparam a4T Type of argument 4. 1080 /// \param dest Description needed. 1081 /// \param memfn Verify: The member function to be invoked for the task. 1082 /// \param a1 Argument 1. 1083 /// \param a2 Argument 2. 1084 /// \param a3 Argument 3. 1085 /// \param a4 Argument 4. 1086 /// \param attr Description needed. 1087 /// \return Description needed. 1088 template <typename memfnT, typename a1T, typename a2T, typename a3T, 1089 typename a4T> 1090 typename detail::task_result_type<memfnT>::futureT 1091 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1092 const a3T& a3, const a4T& a4, const TaskAttributes& attr = TaskAttributes()) const 1093 { 1094 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1095 typedef TaskFn<typename task_helper::wrapperT, 1096 typename detail::task_arg<a1T>::type, 1097 typename detail::task_arg<a2T>::type, 1098 typename detail::task_arg<a3T>::type, 1099 typename detail::task_arg<a4T>::type> taskT; 1100 if (dest == me) 1101 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1102 a1, a2, a3, a4, attr); 1103 else 1104 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1105 am_arg(a3), am_arg(a4), voidT::value, voidT::value, 1106 voidT::value, voidT::value, voidT::value, attr); 1107 } 1108 1109 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5)`. 1110 1111 /// \todo Descriptions needed. 1112 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1113 /// \tparam a1T Type of argument 1. 1114 /// \tparam a2T Type of argument 2. 1115 /// \tparam a3T Type of argument 3. 1116 /// \tparam a4T Type of argument 4. 1117 /// \tparam a5T Type of argument 5. 1118 /// \param dest Description needed. 1119 /// \param memfn Verify: The member function to be invoked for the task. 1120 /// \param a1 Argument 1. 1121 /// \param a2 Argument 2. 1122 /// \param a3 Argument 3. 1123 /// \param a4 Argument 4. 1124 /// \param a5 Argument 5. 1125 /// \param attr Description needed. 1126 /// \return Description needed. 1127 template <typename memfnT, typename a1T, typename a2T, typename a3T, 1128 typename a4T, typename a5T> 1129 typename detail::task_result_type<memfnT>::futureT 1130 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1131 const a3T& a3, const a4T& a4, const a5T& a5, 1132 const TaskAttributes& attr = TaskAttributes()) const 1133 { 1134 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1135 typedef TaskFn<typename task_helper::wrapperT, 1136 typename detail::task_arg<a1T>::type, 1137 typename detail::task_arg<a2T>::type, 1138 typename detail::task_arg<a3T>::type, 1139 typename detail::task_arg<a4T>::type, 1140 typename detail::task_arg<a5T>::type> taskT; 1141 if (dest == me) 1142 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1143 a1, a2, a3, a4, a5, attr); 1144 else 1145 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1146 am_arg(a3), am_arg(a4), am_arg(a5), voidT::value, 1147 voidT::value, voidT::value, voidT::value, attr); 1148 } 1149 1150 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6)`. 1151 1152 /// \todo Descriptions needed. 1153 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1154 /// \tparam a1T Type of argument 1. 1155 /// \tparam a2T Type of argument 2. 1156 /// \tparam a3T Type of argument 3. 1157 /// \tparam a4T Type of argument 4. 1158 /// \tparam a5T Type of argument 5. 1159 /// \tparam a6T Type of argument 6. 1160 /// \param dest Description needed. 1161 /// \param memfn Verify: The member function to be invoked for the task. 1162 /// \param a1 Argument 1. 1163 /// \param a2 Argument 2. 1164 /// \param a3 Argument 3. 1165 /// \param a4 Argument 4. 1166 /// \param a5 Argument 5. 1167 /// \param a6 Argument 6. 1168 /// \param attr Description needed. 1169 /// \return Description needed. 1170 template <typename memfnT, typename a1T, typename a2T, typename a3T, 1171 typename a4T, typename a5T, typename a6T> 1172 typename detail::task_result_type<memfnT>::futureT 1173 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1174 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 1175 const TaskAttributes& attr = TaskAttributes()) const 1176 { 1177 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1178 typedef TaskFn<typename task_helper::wrapperT, 1179 typename detail::task_arg<a1T>::type, 1180 typename detail::task_arg<a2T>::type, 1181 typename detail::task_arg<a3T>::type, 1182 typename detail::task_arg<a4T>::type, 1183 typename detail::task_arg<a5T>::type, 1184 typename detail::task_arg<a6T>::type> taskT; 1185 if (dest == me) 1186 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1187 a1, a2, a3, a4, a5, a6, attr); 1188 else { 1189 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1190 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6), 1191 voidT::value, voidT::value, voidT::value, attr); 1192 } 1193 } 1194 1195 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7)`. 1196 1197 /// \todo Descriptions needed. 1198 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1199 /// \tparam a1T Type of argument 1. 1200 /// \tparam a2T Type of argument 2. 1201 /// \tparam a3T Type of argument 3. 1202 /// \tparam a4T Type of argument 4. 1203 /// \tparam a5T Type of argument 5. 1204 /// \tparam a6T Type of argument 6. 1205 /// \tparam a7T Type of argument 7. 1206 /// \param dest Description needed. 1207 /// \param memfn Verify: The member function to be invoked for the task. 1208 /// \param a1 Argument 1. 1209 /// \param a2 Argument 2. 1210 /// \param a3 Argument 3. 1211 /// \param a4 Argument 4. 1212 /// \param a5 Argument 5. 1213 /// \param a6 Argument 6. 1214 /// \param a7 Argument 7. 1215 /// \param attr Description needed. 1216 /// \return Description needed. 1217 template <typename memfnT, typename a1T, typename a2T, typename a3T, 1218 typename a4T, typename a5T, typename a6T, typename a7T> 1219 typename detail::task_result_type<memfnT>::futureT 1220 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1221 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 1222 const a7T& a7, const TaskAttributes& attr = TaskAttributes()) const 1223 { 1224 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1225 typedef TaskFn<typename task_helper::wrapperT, 1226 typename detail::task_arg<a1T>::type, 1227 typename detail::task_arg<a2T>::type, 1228 typename detail::task_arg<a3T>::type, 1229 typename detail::task_arg<a4T>::type, 1230 typename detail::task_arg<a5T>::type, 1231 typename detail::task_arg<a6T>::type, 1232 typename detail::task_arg<a7T>::type> taskT; 1233 if (dest == me) 1234 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1235 a1, a2, a3, a4, a5, a6, a7, attr); 1236 else 1237 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1238 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6), 1239 am_arg(a7), voidT::value, voidT::value, attr); 1240 } 1241 1242 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8)`. 1243 1244 /// \todo Descriptions needed. 1245 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1246 /// \tparam a1T Type of argument 1. 1247 /// \tparam a2T Type of argument 2. 1248 /// \tparam a3T Type of argument 3. 1249 /// \tparam a4T Type of argument 4. 1250 /// \tparam a5T Type of argument 5. 1251 /// \tparam a6T Type of argument 6. 1252 /// \tparam a7T Type of argument 7. 1253 /// \tparam a8T Type of argument 8. 1254 /// \param dest Description needed. 1255 /// \param memfn Verify: The member function to be invoked for the task. 1256 /// \param a1 Argument 1. 1257 /// \param a2 Argument 2. 1258 /// \param a3 Argument 3. 1259 /// \param a4 Argument 4. 1260 /// \param a5 Argument 5. 1261 /// \param a6 Argument 6. 1262 /// \param a7 Argument 7. 1263 /// \param a8 Argument 8. 1264 /// \param attr Description needed. 1265 /// \return Description needed. 1266 template <typename memfnT, typename a1T, typename a2T, typename a3T, 1267 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T> 1268 typename detail::task_result_type<memfnT>::futureT 1269 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1270 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 1271 const a7T& a7, const a8T& a8, 1272 const TaskAttributes& attr = TaskAttributes()) const 1273 { 1274 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1275 typedef TaskFn<typename task_helper::wrapperT, 1276 typename detail::task_arg<a1T>::type, 1277 typename detail::task_arg<a2T>::type, 1278 typename detail::task_arg<a3T>::type, 1279 typename detail::task_arg<a4T>::type, 1280 typename detail::task_arg<a5T>::type, 1281 typename detail::task_arg<a6T>::type, 1282 typename detail::task_arg<a7T>::type, 1283 typename detail::task_arg<a8T>::type> taskT; 1284 if (dest == me) 1285 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1286 a1, a2, a3, a4, a5, a6, a7, a8, attr); 1287 else { 1288 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1289 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6), 1290 am_arg(a7), am_arg(a8), voidT::value, attr); 1291 } 1292 } 1293 1294 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8,a9)`. 1295 1296 /// \todo Descriptions needed. 1297 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task. 1298 /// \tparam a1T Type of argument 1. 1299 /// \tparam a2T Type of argument 2. 1300 /// \tparam a3T Type of argument 3. 1301 /// \tparam a4T Type of argument 4. 1302 /// \tparam a5T Type of argument 5. 1303 /// \tparam a6T Type of argument 6. 1304 /// \tparam a7T Type of argument 7. 1305 /// \tparam a8T Type of argument 8. 1306 /// \tparam a9T Type of argument 9. 1307 /// \param dest Description needed. 1308 /// \param memfn Verify: The member function to be invoked for the task. 1309 /// \param a1 Argument 1. 1310 /// \param a2 Argument 2. 1311 /// \param a3 Argument 3. 1312 /// \param a4 Argument 4. 1313 /// \param a5 Argument 5. 1314 /// \param a6 Argument 6. 1315 /// \param a7 Argument 7. 1316 /// \param a8 Argument 8. 1317 /// \param a9 Argument 9. 1318 /// \param attr Description needed. 1319 /// \return Description needed. 1320 /// 1321 /// \todo Could we use variadic templates to eliminate a lot of this code duplication? 1322 template <typename memfnT, typename a1T, typename a2T, typename a3T, 1323 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T, 1324 typename a9T> 1325 typename detail::task_result_type<memfnT>::futureT 1326 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2, 1327 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6, 1328 const a7T& a7, const a8T& a8, const a9T& a9, 1329 const TaskAttributes& attr = TaskAttributes()) const 1330 { 1331 typedef detail::WorldObjectTaskHelper<Derived, memfnT> task_helper; 1332 typedef TaskFn<typename task_helper::wrapperT, 1333 typename detail::task_arg<a1T>::type, 1334 typename detail::task_arg<a2T>::type, 1335 typename detail::task_arg<a3T>::type, 1336 typename detail::task_arg<a4T>::type, 1337 typename detail::task_arg<a5T>::type, 1338 typename detail::task_arg<a6T>::type, 1339 typename detail::task_arg<a7T>::type, 1340 typename detail::task_arg<a8T>::type, 1341 typename detail::task_arg<a9T>::type> taskT; 1342 if (dest == me) 1343 return world.taskq.add(task_helper::make_task_fn(this, memfn), 1344 a1, a2, a3, a4, a5, a6, a7, a8, a9, attr); 1345 else 1346 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2), 1347 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6), 1348 am_arg(a7), am_arg(a8), am_arg(a9), attr); 1349 } 1350 1351 virtual ~WorldObject() { 1352 if(initialized()) 1353 world.unregister_ptr(static_cast<Derived*>(this)); 1354 } 1355 }; 1356 1357 namespace archive { 1358 1359 /// Specialization of \c ArchiveLoadImpl for globally-addressable objects. 1360 1361 /// \tparam Derived The derived class of \c WorldObject in a curiously 1362 /// repeating template pattern. 1363 template <class Derived> 1364 struct ArchiveLoadImpl<BufferInputArchive,WorldObject<Derived>*> { 1365 1366 /// Read a globally-addressable object from a \c BufferInputArchive. 1367 1368 /// \param[in,out] ar The archive. 1369 /// \param[out] ptr The read object. 1370 static inline void load(const BufferInputArchive& ar, WorldObject<Derived>*& ptr) { 1371 uniqueidT id; 1372 ar & id; 1373 World* world = World::world_from_id(id.get_world_id()); 1374 MADNESS_ASSERT(world); 1375 ptr = world->ptr_from_id< WorldObject<Derived> >(id); 1376 if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0); 1377 } 1378 }; 1379 1380 /// Specialization of \c ArchiveStoreImpl for globally-addressable objects. 1381 1382 /// \tparam Derived The derived class of \c WorldObject in a curiously 1383 /// repeating template pattern. 1384 template <class Derived> 1385 struct ArchiveStoreImpl<BufferOutputArchive,WorldObject<Derived>*> { 1386 1387 /// Write a globally-addressable object to a \c BufferOutputArchive. 1388 1389 /// \param[in,out] ar The archive. 1390 /// \param[in] ptr The object to store. 1391 static inline void store(const BufferOutputArchive& ar, WorldObject<Derived>* const& ptr) { 1392 ar & ptr->id(); 1393 } 1394 }; 1395 1396 /// Specialization of \c ArchiveLoadImpl for constant, globally-addressable objects. 1397 1398 /// \tparam Derived The derived class of \c WorldObject in a curiously 1399 /// repeating template pattern. 1400 template <class Derived> 1401 struct ArchiveLoadImpl<BufferInputArchive, const WorldObject<Derived>*> { 1402 1403 /// Read a globally-addressable object from a \c BufferInputArchive. 1404 1405 /// \param[in,out] ar The archive. 1406 /// \param[out] ptr The read object. 1407 static inline void load(const BufferInputArchive& ar, const WorldObject<Derived>*& ptr) { 1408 uniqueidT id; 1409 ar & id; 1410 World* world = World::world_from_id(id.get_world_id()); 1411 MADNESS_ASSERT(world); 1412 ptr = world->ptr_from_id< WorldObject<Derived> >(id); 1413 if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0); 1414 } 1415 }; 1416 1417 /// Specialization of \c ArchiveStoreImpl for constant, globally-addressable objects. 1418 1419 /// \tparam Derived The derived class of \c WorldObject in a curiously 1420 /// repeating template pattern. 1421 template <class Derived> 1422 struct ArchiveStoreImpl<BufferOutputArchive, const WorldObject<Derived>*> { 1423 1424 /// Write a globally-addressable object to a \c BufferOutputArchive. 1425 1426 /// \param[in,out] ar The archive. 1427 /// \param[in] ptr The object to store. 1428 static inline void store(const BufferOutputArchive& ar, const WorldObject<Derived>* const& ptr) { 1429 ar & ptr->id(); 1430 } 1431 }; 1432 } 1433 } 1434 1435 #ifdef WORLD_INSTANTIATE_STATIC_TEMPLATES 1436 template <typename Derived> 1437 volatile std::list<madness::detail::PendingMsg> madness::WorldObject<Derived>::pending; 1438 1439 template <typename Derived> 1440 madness::Spinlock madness::WorldObject<Derived>::pending_mutex; 1441 1442 #endif 1443 1444 #endif // MADNESS_WORLD_WORLD_OBJECT_H__INCLUDED 1445 1446 /// @} 1447