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