MADNESS  0.10.1
world_object.h
Go to the documentation of this file.
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 <madness/world/thread.h>
43 
44 #include <array>
45 #include <atomic>
46 #include <cstddef>
47 #include <type_traits>
48 
49 /// \addtogroup world_object
50 /// @{
51 
52 namespace madness {
53 
54  template <typename> class WorldObject;
55 
56  namespace detail {
57 
58  /// Common base class for pending messages to ensure in-order processing.
59 
60  /// To eliminate synchronization when a distributed object is first
61  /// constructed, we buffer pending messages for containers that
62  /// don't have their ID yet registered.
63  struct PendingMsg {
67 
70 
71  void invokehandler() {
72  handler(*arg);
74  }
75  };
76 
77  /// \todo Brief description needed.
78 
79  /// We cannot use the normal task forwarding stuff here because pending
80  /// messages can creating tasks are must be correctly handled. The
81  /// following code does not easily merge with the send handlers since
82  /// the task layer is more restrictive on the copy capability of
83  /// arguments.
84  ///
85  /// It is also annoying that info needs to be broken into two parts so
86  /// that it \c id and \c ref are properly serialized. We need to have
87  /// \c id correctly aligned via \c opaque_wrap, but \c ref cannot be
88  /// serialized that way. Thus we break the class into two parts.
89  ///
90  /// Info stored for AM method forwarding.
91  /// \tparam memfunT Description needed.
92  /// \todo Verify & complete; what is AM?
93  template <typename memfunT>
94  struct info_base {
95  using memfunT_rel_ptr = decltype(archive::to_rel_memfn_ptr(std::declval<memfunT>()));
96  // id must be at front ... see peek.
97  uniqueidT id; ///< \todo Description needed. Context with the "see peek" comment above?
98  ProcessID requestor; ///< \todo Description needed.
99  memfunT_rel_ptr memfun_rel_ptr; ///< \todo Description needed.
100  TaskAttributes attr; ///< \todo Description needed.
101 
102  /// \return the (absolute) member function pointer
103  memfunT memfun() const {
104  return archive::to_abs_memfn_ptr<memfunT>(memfun_rel_ptr);
105  }
106 
107  protected:
108 
110 
111  /// \todo Constructor that [brief description needed].
112 
113  /// \todo Descriptions needed.
114  /// \param[in] id Description needed.
115  /// \param[in] requestor Description needed.
116  /// \param memfun Verify: The member function to be invoked for the task.
117  /// \param[in] attr Description needed.
120  : id(id)
123  , attr(attr) {}
124 
125  /// Serializes a \c info_base for I/O.
126 
127  /// \tparam Archive The type of I/O archive.
128  /// \param[in,out] ar The I/O archive.
129  template <typename Archive>
130  void serialize(const Archive& ar) {
131  ar & archive::wrap_opaque(*this); // Must be opaque ... see peek.
132  }
133  }; // struct info_base
134 
135  /// \todo Brief description needed.
136 
137  /// \todo Descriptions needed.
138  /// \tparam memfunT Verify: Signature of the member function in the derived class to be invoked for the task.
139  template <typename memfunT>
140  struct info : public info_base<memfunT> {
141  /// Future for a return value of the memory function. \todo Verify.
142  typedef Future< REMFUTURE(MEMFUN_RETURNT(memfunT)) > futureT;
143  /// \todo Description needed.
145 
146  refT ref; ///< \todo Description needed.
147 
148  info() : info_base<memfunT>() {}
149 
150  /// \todo Constructor that [brief description needed].
151 
152  /// \todo Descriptions needed.
153  /// \param[in] arg Description needed.
154  info(const AmArg& arg) :
155  info_base<memfunT>()
156  {
157  arg & *this;
158  }
159 
160  /// \todo Constructor that [brief description needed].
161 
162  /// \todo Descriptions needed.
163  /// \param[in] id Description needed.
164  /// \param[in] requestor Description needed.
165  /// \param memfun Verify: The member function to be invoked for the task.
166  /// \param[in] ref Description needed.
167  /// \param[in] attr Description needed.
168  info(const uniqueidT& id, ProcessID requestor, memfunT memfun,
169  const refT& ref, const TaskAttributes& attr=TaskAttributes())
170  : info_base<memfunT>(id, requestor, memfun, attr), ref(ref)
171  {}
172 
173  /// Serializes a \c info for I/O.
174 
175  /// \tparam Archive the type of I/O archive.
176  /// \param[in] ar The I/O archive.
177  template <typename Archive>
178  void serialize(const Archive& ar) {
180  ar & ref;
181  }
182  }; // struct info
183 
184  /// Extract the unique object ID from an incoming active message header.
185 
186  /// We deserialize the header and all arguments at the same
187  /// time to simplify the code. However, it is common that
188  /// when sending a message to an item in a container to
189  /// include a pointer to the container itself. But this
190  /// breaks if the container is not initialized since the
191  /// deserialization throws if the object is not initialized
192  /// (which seems preferable to a hidden race condition). Hence,
193  /// we use this routine to extract the unique ID from the very
194  /// front of the \c info structure. For efficiency we here rely
195  /// upon the serialization of \c info being opaque and the
196  /// ID being at the front of \c info.
197  ///
198  /// \todo Verify parameter description.
199  /// \param[in] arg The active message header.
200  static inline const uniqueidT& peek(const AmArg& arg) {
201  return *((uniqueidT*)(arg.buf()));
202  }
203 
204 
205  /// \todo Brief description needed.
206 
207  /// \todo Descriptions needed.
208  /// \tparam objT Description needed.
209  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
210  /// \tparam Enabler Description needed.
211  template <typename objT, typename memfnT, typename Enabler = void>
213  /// \todo Description needed.
214  typedef typename std::conditional<memfunc_traits<memfnT>::constness,
215  const objT*, objT*>::type ptrT;
216 
217  /// \todo Description needed.
219 
220 
221  /// \todo Brief description needed.
222 
223  /// \todo Descriptions needed.
224  /// \param[in] obj Description needed.
225  /// \param memfn Verify: The member function to be invoked for the task.
226  /// \return Description needed.
227  static wrapperT make_task_fn(const objT* obj, memfnT memfn) {
228  return wrapperT(const_cast<ptrT>(obj), memfn);
229  }
230 
231 
232  /// \todo Brief description needed.
233 
234  /// \todo Descriptions needed.
235  /// \param[in] obj Description needed.
236  /// \param memfn Verify: The member function to be invoked for the task.
237  /// \return Description needed.
238  static wrapperT make_task_fn(objT* obj, memfnT memfn) {
239  return wrapperT(const_cast<ptrT>(obj), memfn);
240  }
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.
249  static wrapperT make_task_fn(const WorldObject<objT>* obj, memfnT memfn) {
250  return make_task_fn(static_cast<const objT*>(obj), memfn);
251  }
252 
253  /// \todo Brief description needed.
254 
255  /// \todo Descriptions needed.
256  /// \param[in] obj Description needed.
257  /// \param memfn Verify: The member function to be invoked for the task.
258  /// \return Description needed.
259  static wrapperT make_task_fn(WorldObject<objT>* obj, memfnT memfn) {
260  return make_task_fn(static_cast<objT*>(obj), memfn);
261  }
262  }; // struct WorldObjectTaskHelper
263 
264 
265 #ifndef MADNESS_DISABLE_SHARED_FROM_THIS
266  // Disable the use of std::enable_shared_from_this if we are using MADNESS's
267  // implementation since weak_ptr is not fully implemented.
268 
269 
270  /// \todo Brief description needed.
271 
272  /// \todo Descriptions needed.
273  /// \tparam objT Description needed.
274  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
275  template <typename objT, typename memfnT>
276  struct WorldObjectTaskHelper<objT, memfnT,
277  typename std::enable_if< std::is_base_of<std::enable_shared_from_this<objT>, objT>::value >::type>
278  {
279  /// \todo Description needed.
280  typedef typename std::conditional<memfunc_traits<memfnT>::constness,
281  const objT*, objT*>::type ptrT;
282 
283  /// \todo Description needed.
284  typedef typename std::conditional<memfunc_traits<memfnT>::constness,
285  std::shared_ptr<const objT>, std::shared_ptr<objT> >::type shared_ptrT;
286 
287  /// \todo Description needed.
289 
290 
291  /// \todo Brief description needed.
292 
293  /// \todo Descriptions needed.
294  /// \param[in] obj Description needed.
295  /// \param memfn Verify: The member function to be invoked for the task.
296  /// \return Description needed.
297  static wrapperT make_task_fn(const objT* obj, memfnT memfn) {
298  return wrapperT(const_cast<ptrT>(obj)->shared_from_this(), memfn);
299  }
300 
301 
302  /// \todo Brief description needed.
303 
304  /// \todo Descriptions needed.
305  /// \param[in] obj Description needed.
306  /// \param memfn Verify: The member function to be invoked for the task.
307  /// \return Description needed.
308  static wrapperT make_task_fn(objT* obj, memfnT memfn) {
309  return wrapperT(const_cast<ptrT>(obj)->shared_from_this(), memfn);
310  }
311 
312 
313  /// \todo Brief description needed.
314 
315  /// \todo Descriptions needed.
316  /// \param[in] obj Description needed.
317  /// \param memfn Verify: The member function to be invoked for the task.
318  /// \return Description needed.
319  static wrapperT make_task_fn(const WorldObject<objT>* obj, memfnT memfn) {
320  return make_task_fn(static_cast<const objT*>(obj), memfn);
321  }
322 
323 
324  /// \todo Brief description needed.
325 
326  /// \todo Descriptions needed.
327  /// \param[in] obj Description needed.
328  /// \param memfn Verify: The member function to be invoked for the task.
329  /// \return Description needed.
330  static wrapperT make_task_fn(WorldObject<objT>* obj, memfnT memfn) {
331  return make_task_fn(static_cast<objT*>(obj), memfn);
332  }
333  }; // struct WorldObjectTaskHelper
334 
335 #endif // MADNESS_DISABLE_SHARED_FROM_THIS
336 
337  } // namespace detail
338 
339  /// Base class for WorldObject, useful for introspection
341  virtual ~WorldObjectBase() = default;
342  };
343 
344  /// Implements most parts of a globally addressable object (via unique ID).
345 
346  /// This class is deliberately not default constructible and does
347  /// not support assignment or copying. This ensures that each instance
348  /// is unique. Have a look at \c madness::WorldContainer for an example
349  /// of wrapping this using the PIMPL idiom and a shared pointer.
350  ///
351  /// When deriving classes:
352  /// -# Derived class has `WorldObject<Derived>` as a public base class.
353  /// -# Derived constructor:
354  /// -# invokes `WorldObject<Derived>(world)` constructor.
355  /// -# invokes `process_pending()`.
356  /// -# Derived destructor must either be deferred or preceeded by `gop.fence()`.
357  /// -# Derived class must have at least one virtual function for serialization
358  /// of derived class pointers to be cast to the appropriate type.
359  ///
360  /// Note that \c world is exposed for convenience as a public data member.
361  /// \tparam Derived The derived class. \c WorldObject is a curiously
362  /// recurring template pattern.
363  template <class Derived>
364  class WorldObject : public WorldObjectBase {
365  public:
366  /// \todo Description needed.
368 
369  // copy ctor must be enabled to permit RVO; in C++17 will not need this
370  WorldObject(const WorldObject& other) : world(other.world) { abort(); }
371  // no copy
372  WorldObject& operator=(const WorldObject&) = delete;
373 
374  private:
375  /// \todo Description needed.
376  typedef std::list<detail::PendingMsg> pendingT;
377 
378  /// \todo Description needed.
380 
381  World& world; ///< The \c World this object belongs to. (Think globally, act locally).
382 
383  // The order here matters in a multi-threaded world
384  volatile bool ready; ///< True if ready to rock 'n roll.
385  ProcessID me; ///< Rank of self.
386  uniqueidT objid; ///< Sense of self.
387 
388 
389  inline static Spinlock pending_mutex; ///< \todo Description needed.
390  inline static volatile pendingT pending; ///< Buffer for pending messages.
391 
392 
393  /// \todo Complete: Determine if [unknown] is ready (for ...).
394 
395  /// The slightly convoluted logic is to ensure ordering when
396  /// processing pending messages. If a new message arrives
397  /// while processing incoming messages it must be queued.
398  ///
399  /// - If the object does not exist ---> not ready.
400  /// - If the object exists and is ready ---> ready.
401  /// - If the object exists and is not ready then
402  /// - if we are doing a queued/pending message --> ready.
403  /// - else this is a new message --> not ready.
404  ///
405  /// \param[in] id Description needed.
406  /// \param[in,out] obj Description needed.
407  /// \param[in] arg Description needed.
408  /// \param[in,out] ptr Description needed.
409  /// \return Description needed.
410  /// \todo Parameter/return descriptions needed.
411  static bool is_ready(const uniqueidT& id, objT*& obj, const AmArg& arg, am_handlerT ptr) {
412  std::optional<Derived *> opt_obj =
413  arg.get_world()->template ptr_from_id<Derived>(id);
414  if (opt_obj) {
415  // if opt_obj == nullptr, then this ID has already been deregistered
416  MADNESS_ASSERT(*opt_obj != nullptr);
417  obj = static_cast<objT *>(*opt_obj);
418  } else
419  obj = nullptr;
420 
421  if (obj) {
422  if (obj->ready || arg.is_pending())
423  return true;
424  }
425 
426  MADNESS_PRAGMA_CLANG(diagnostic push)
427  MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template")
428 
429  ScopedMutex<Spinlock> lock(pending_mutex); // BEGIN CRITICAL SECTION
430 
431  if (!obj) {
432  std::optional<Derived *> opt_obj =
433  arg.get_world()->template ptr_from_id<Derived>(id);
434  if (opt_obj) {
435  // if opt_obj == nullptr, then this ID has already been deregistered
436  MADNESS_ASSERT(*opt_obj != nullptr);
437  obj = static_cast<objT *>(*opt_obj);
438  } else
439  obj = nullptr;
440  }
441 
442  if (obj) {
443  if (obj->ready || arg.is_pending())
444  return true; // END CRITICAL SECTION
445  }
446  const_cast<AmArg &>(arg).set_pending();
447  const_cast<pendingT &>(pending).push_back(
448  detail::PendingMsg(id, ptr, arg));
449 
450  MADNESS_PRAGMA_CLANG(diagnostic pop)
451 
452  return false; // END CRITICAL SECTION
453  }
454 
455  /// Handler for an incoming AM.
456 
457  /// \todo Descriptions needed.
458  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
459  /// \tparam arg1T Type of argument 1.
460  /// \tparam arg2T Type of argument 2.
461  /// \tparam arg3T Type of argument 3.
462  /// \tparam arg4T Type of argument 4.
463  /// \tparam arg5T Type of argument 5.
464  /// \tparam arg6T Type of argument 6.
465  /// \tparam arg7T Type of argument 7.
466  /// \tparam arg8T Type of argument 8.
467  /// \tparam arg9T Type of argument 9.
468  /// \param[in] arg Description needed.
469  template <typename memfnT, typename arg1T, typename arg2T, typename arg3T, typename arg4T,
470  typename arg5T, typename arg6T, typename arg7T, typename arg8T, typename arg9T>
471  static void handler(const AmArg& arg) {
473 
474  const uniqueidT& id = detail::peek(arg);
475  am_handlerT ptr = handler<memfnT,arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T,arg8T,arg9T>;
476  objT* obj;
477  if (is_ready(id,obj,arg,ptr)) {
479  typename detail::task_arg<arg1T>::type arg1;
480  typename detail::task_arg<arg2T>::type arg2;
481  typename detail::task_arg<arg3T>::type arg3;
482  typename detail::task_arg<arg4T>::type arg4;
483  typename detail::task_arg<arg5T>::type arg5;
484  typename detail::task_arg<arg6T>::type arg6;
485  typename detail::task_arg<arg7T>::type arg7;
486  typename detail::task_arg<arg8T>::type arg8;
487  typename detail::task_arg<arg9T>::type arg9;
488  MADNESS_PRAGMA_CLANG(diagnostic push)
489  MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wuninitialized-const-reference")
490  arg & info & arg1 & arg2 & arg3 & arg4 & arg5 & arg6 & arg7 & arg8 & arg9;
491  MADNESS_PRAGMA_CLANG(diagnostic pop)
492  typename detail::info<memfnT>::futureT result(info.ref);
493  detail::run_function(result, task_helper::make_task_fn(obj, info.memfun()),
494  arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
495  }
496  }
497 
498 
499  /// Handler for remote arguments.
500 
501  /// \todo Descriptions needed.
502  /// \tparam taskT Description needed.
503  /// \param[in] arg Description needed.
504  template <typename taskT>
505  static void spawn_remote_task_handler(const AmArg& arg) {
506  typedef detail::WorldObjectTaskHelper<Derived,
507  typename taskT::functionT::memfn_type> task_helper;
508 
509  MADNESS_ASSERT(taskT::arity <= 9u);
510 
511  const uniqueidT& id = detail::peek(arg);
512  am_handlerT ptr = & objT::template spawn_remote_task_handler<taskT>;
513  objT* obj;
514  if (is_ready(id,obj,arg,ptr)) {
516 
517  archive::BufferInputArchive input_arch = arg & info;
518 
519  // Construct task
520  taskT* task = new taskT(typename taskT::futureT(info.ref),
521  task_helper::make_task_fn(obj, info.memfun()), info.attr, input_arch);
522 
523  // Add task to queue
524  arg.get_world()->taskq.add(task);
525  }
526  }
527 
528 
529  /// \todo Brief description needed.
530 
531  /// \todo Descriptions needed.
532  /// \tparam T Description needed.
533  /// \param[in] f Description needed.
534  /// \return Description needed.
535  template <typename T>
536  static inline const T& am_arg(const Future<T>& f) {
537  MADNESS_ASSERT(f.probe()); // Cannot serialize unassigned futures
538  return f.get();
539  }
540 
541 
542  /// \todo Brief description needed.
543 
544  /// \todo Descriptions needed.
545  /// \tparam T Description needed.
546  /// \param[in] t Description needed.
547  /// \return Description needed.
548  template <typename T>
549  static inline const T& am_arg(const T& t) {
550  return t;
551  }
552 
553 
554  /// \todo Brief description needed.
555 
556  /// \todo Descriptions needed.
557  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
558  /// \tparam a1T Type of argument 1.
559  /// \tparam a2T Type of argument 2.
560  /// \tparam a3T Type of argument 3.
561  /// \tparam a4T Type of argument 4.
562  /// \tparam a5T Type of argument 5.
563  /// \tparam a6T Type of argument 6.
564  /// \tparam a7T Type of argument 7.
565  /// \tparam a8T Type of argument 8.
566  /// \tparam a9T Type of argument 9.
567  /// \param dest Description needed.
568  /// \param memfn Verify: The member function to be invoked for the task.
569  /// \param a1 Argument 1.
570  /// \param a2 Argument 2.
571  /// \param a3 Argument 3.
572  /// \param a4 Argument 4.
573  /// \param a5 Argument 5.
574  /// \param a6 Argument 6.
575  /// \param a7 Argument 7.
576  /// \param a8 Argument 8.
577  /// \param a9 Argument 9.
578  /// \return Description needed.
579  template <typename memfnT, typename a1T, typename a2T, typename a3T,
580  typename a4T, typename a5T, typename a6T, typename a7T,
581  typename a8T, typename a9T>
583  send_am(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
584  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
585  const a7T& a7, const a8T& a8, const a9T& a9) const
586  {
589  if (dest == me)
590  detail::run_function(result, task_helper::make_task_fn(this, memfn),
591  a1, a2, a3, a4, a5, a6, a7, a8, a9);
592  else {
593  detail::info<memfnT> info(objid, me, memfn, result.remote_ref(world));
594  world.am.send(dest, & objT::template handler<memfnT, a1T, a2T, a3T, a4T, a5T, a6T, a7T, a8T, a9T>,
595  new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9));
596  }
597 
598  return result;
599  }
600 
601 
602  /// \todo Brief description needed.
603 
604  /// \todo Descriptions needed.
605  /// \tparam taskT Description needed.
606  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
607  /// \tparam a1T Type of argument 1.
608  /// \tparam a2T Type of argument 2.
609  /// \tparam a3T Type of argument 3.
610  /// \tparam a4T Type of argument 4.
611  /// \tparam a5T Type of argument 5.
612  /// \tparam a6T Type of argument 6.
613  /// \tparam a7T Type of argument 7.
614  /// \tparam a8T Type of argument 8.
615  /// \tparam a9T Type of argument 9.
616  /// \param dest Description needed.
617  /// \param memfn Verify: The member function to be invoked for the task.
618  /// \param a1 Argument 1.
619  /// \param a2 Argument 2.
620  /// \param a3 Argument 3.
621  /// \param a4 Argument 4.
622  /// \param a5 Argument 5.
623  /// \param a6 Argument 6.
624  /// \param a7 Argument 7.
625  /// \param a8 Argument 8.
626  /// \param a9 Argument 9.
627  /// \param attr Description needed.
628  /// \return Description needed.
629  template <typename taskT, typename memfnT, typename a1T, typename a2T, typename a3T,
630  typename a4T, typename a5T, typename a6T, typename a7T,
631  typename a8T, typename a9T>
632  typename taskT::futureT
633  send_task(ProcessID dest, memfnT memfn, const a1T& a1,
634  const a2T& a2, const a3T& a3, const a4T& a4, const a5T& a5,
635  const a6T& a6, const a7T& a7, const a8T& a8, const a9T& a9,
636  const TaskAttributes& attr) const
637  {
638  typename taskT::futureT result;
639  detail::info<memfnT> info(objid, me, memfn, result.remote_ref(world), attr);
640  world.am.send(dest, & objT::template spawn_remote_task_handler<taskT>,
641  new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9), RMI::ATTR_UNORDERED);
642 
643  return result;
644  }
645 
646  protected:
647 
648  /// To be called from \em derived constructor to process pending messages.
649 
650  /// Cannot call this from the \c WorldObject constructor since the
651  /// derived class would not yet be fully constructed.
652  ///
653  /// \attention No incoming messages are processed until this routine is
654  /// invoked; the derived class may rely upon a well defined state
655  /// until this routine is invoked.
657  // Messages may be arriving while we are processing the
658  // pending queue. To maximize concurrency copy messages
659  // out of queue before processing outside critical section.
660  //int ndone = 0;
661  while (!ready) {
662  pendingT tmp;
663 
664  MADNESS_PRAGMA_CLANG(diagnostic push)
665  MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template")
666 
667  pending_mutex.lock(); // BEGIN CRITICAL SECTION
668  pendingT& nv = const_cast<pendingT&>(pending);
669  for (pendingT::iterator it=nv.begin(); it!=nv.end();) {
670  detail::PendingMsg& p = *it;
671  if (p.id == objid) {
672  tmp.push_back(p);
673  it = nv.erase(it);
674  }
675  else {
676  ++it;
677  }
678  }
679  if (tmp.size() == 0) ready=true;
680  pending_mutex.unlock(); // END CRITICAL SECTION
681 
682  MADNESS_PRAGMA_CLANG(diagnostic pop)
683 
684  while (tmp.size()) {
685  tmp.front().invokehandler();
686  tmp.pop_front();
687  //++ndone;
688  }
689  }
690  //if (ndone) std::cout << world.rank() << ":pending:" << ndone << std::endl;
691  }
692 
693 
694  public:
695  /// \brief Constructor that associates an object (via the derived class)
696  /// with a globally unique ID.
697 
698  /// \attention The derived class MUST call \c process_pending from
699  /// its constructor to both
700  /// -# process any messages that arrived prior to construction.
701  /// -# to enable processing of future messages.
702  /// \param[in,out] world The \c World encapsulating the \"global\" domain.
704  : world(world)
705  , ready(false)
706  , me(world.rank())
707  , objid(world.register_ptr(static_cast<Derived*>(this))) {};
708 
709 
710  /// Returns the globally unique object ID.
711  const uniqueidT& id() const {
712  return objid;
713  }
714 
715 
716  /// Returns a reference to the \c world.
717  World& get_world() const {
718  return const_cast<WorldObject<Derived>*>(this)->world;
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  /// \param dest Description needed.
727  /// \param memfn Verify: The member function to be invoked for the task.
728  /// \return Description needed.
729  template <typename memfnT>
731  send(ProcessID dest, memfnT memfn) const {
732  return send_am(dest, memfn, voidT::value, voidT::value, voidT::value,
735  }
736 
737 
738  /// \todo Brief description needed.
739 
740  /// \todo Descriptions needed.
741  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
742  /// \tparam a1T Type of argument 1.
743  /// \param dest Description needed.
744  /// \param memfn Verify: The member function to be invoked for the task.
745  /// \param a1 Argument 1.
746  /// \return Description needed.
747  template <typename memfnT, typename a1T>
749  send(ProcessID dest, memfnT memfn, const a1T& a1) const {
750  return send_am(dest, memfn, am_arg(a1), voidT::value, voidT::value,
753  }
754 
755 
756  /// \todo Brief description needed.
757 
758  /// \todo Descriptions needed.
759  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
760  /// \tparam a1T Type of argument 1.
761  /// \tparam a2T Type of argument 2.
762  /// \param dest Description needed.
763  /// \param memfn Verify: The member function to be invoked for the task.
764  /// \param a1 Argument 1.
765  /// \param a2 Argument 2.
766  /// \return Description needed.
767  template <typename memfnT, typename a1T, typename a2T>
769  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2) const {
770  return send_am(dest, memfn, am_arg(a1), am_arg(a2), voidT::value,
773  }
774 
775 
776  /// \todo Brief description needed.
777 
778  /// \todo Descriptions needed.
779  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
780  /// \tparam a1T Type of argument 1.
781  /// \tparam a2T Type of argument 2.
782  /// \tparam a3T Type of argument 3.
783  /// \param dest Description needed.
784  /// \param memfn Verify: The member function to be invoked for the task.
785  /// \param a1 Argument 1.
786  /// \param a2 Argument 2.
787  /// \param a3 Argument 3.
788  /// \return Description needed.
789  template <typename memfnT, typename a1T, typename a2T, typename a3T>
791  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
792  const a3T& a3) const
793  {
794  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
797  }
798 
799 
800  /// \todo Brief description needed.
801 
802  /// \todo Descriptions needed.
803  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
804  /// \tparam a1T Type of argument 1.
805  /// \tparam a2T Type of argument 2.
806  /// \tparam a3T Type of argument 3.
807  /// \tparam a4T Type of argument 4.
808  /// \param dest Description needed.
809  /// \param memfn Verify: The member function to be invoked for the task.
810  /// \param a1 Argument 1.
811  /// \param a2 Argument 2.
812  /// \param a3 Argument 3.
813  /// \param a4 Argument 4.
814  /// \return Description needed.
815  template <typename memfnT, typename a1T, typename a2T, typename a3T,
816  typename a4T>
818  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
819  const a3T& a3, const a4T& a4) const
820  {
821  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
824  }
825 
826 
827  /// \todo Brief description needed.
828 
829  /// \todo Descriptions needed.
830  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
831  /// \tparam a1T Type of argument 1.
832  /// \tparam a2T Type of argument 2.
833  /// \tparam a3T Type of argument 3.
834  /// \tparam a4T Type of argument 4.
835  /// \tparam a5T Type of argument 5.
836  /// \param dest Description needed.
837  /// \param memfn Verify: The member function to be invoked for the task.
838  /// \param a1 Argument 1.
839  /// \param a2 Argument 2.
840  /// \param a3 Argument 3.
841  /// \param a4 Argument 4.
842  /// \param a5 Argument 5.
843  /// \return Description needed.
844  template <typename memfnT, typename a1T, typename a2T, typename a3T,
845  typename a4T, typename a5T>
847  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
848  const a3T& a3, const a4T& a4, const a5T& a5) const
849  {
850  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
853  }
854 
855 
856  /// \todo Brief description needed.
857 
858  /// \todo Descriptions needed.
859  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
860  /// \tparam a1T Type of argument 1.
861  /// \tparam a2T Type of argument 2.
862  /// \tparam a3T Type of argument 3.
863  /// \tparam a4T Type of argument 4.
864  /// \tparam a5T Type of argument 5.
865  /// \tparam a6T Type of argument 6.
866  /// \param dest Description needed.
867  /// \param memfn Verify: The member function to be invoked for the task.
868  /// \param a1 Argument 1.
869  /// \param a2 Argument 2.
870  /// \param a3 Argument 3.
871  /// \param a4 Argument 4.
872  /// \param a5 Argument 5.
873  /// \param a6 Argument 6.
874  /// \return Description needed.
875  template <typename memfnT, typename a1T, typename a2T, typename a3T,
876  typename a4T, typename a5T, typename a6T>
878  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
879  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6) 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), voidT::value, 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  /// \param dest Description needed.
899  /// \param memfn Verify: The member function to be invoked for the task.
900  /// \param a1 Argument 1.
901  /// \param a2 Argument 2.
902  /// \param a3 Argument 3.
903  /// \param a4 Argument 4.
904  /// \param a5 Argument 5.
905  /// \param a6 Argument 6.
906  /// \param a7 Argument 7.
907  /// \return Description needed.
908  template <typename memfnT, typename a1T, typename a2T, typename a3T,
909  typename a4T, typename a5T, typename a6T, typename a7T>
911  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
912  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
913  const a7T& a7) const
914  {
915  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
916  am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), voidT::value,
917  voidT::value);
918  }
919 
920 
921  /// \todo Brief description needed.
922 
923  /// \todo Descriptions needed.
924  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
925  /// \tparam a1T Type of argument 1.
926  /// \tparam a2T Type of argument 2.
927  /// \tparam a3T Type of argument 3.
928  /// \tparam a4T Type of argument 4.
929  /// \tparam a5T Type of argument 5.
930  /// \tparam a6T Type of argument 6.
931  /// \tparam a7T Type of argument 7.
932  /// \tparam a8T Type of argument 8.
933  /// \param dest Description needed.
934  /// \param memfn Verify: The member function to be invoked for the task.
935  /// \param a1 Argument 1.
936  /// \param a2 Argument 2.
937  /// \param a3 Argument 3.
938  /// \param a4 Argument 4.
939  /// \param a5 Argument 5.
940  /// \param a6 Argument 6.
941  /// \param a7 Argument 7.
942  /// \param a8 Argument 8.
943  /// \return Description needed.
944  template <typename memfnT, typename a1T, typename a2T, typename a3T,
945  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T>
947  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
948  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
949  const a7T& a7, const a8T& a8) const
950  {
951  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
952  am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8),
953  voidT::value);
954  }
955 
956 
957  /// \todo Brief description needed.
958 
959  /// \todo Descriptions needed.
960  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
961  /// \tparam a1T Type of argument 1.
962  /// \tparam a2T Type of argument 2.
963  /// \tparam a3T Type of argument 3.
964  /// \tparam a4T Type of argument 4.
965  /// \tparam a5T Type of argument 5.
966  /// \tparam a6T Type of argument 6.
967  /// \tparam a7T Type of argument 7.
968  /// \tparam a8T Type of argument 8.
969  /// \tparam a9T Type of argument 9.
970  /// \param dest Description needed.
971  /// \param memfn Verify: The member function to be invoked for the task.
972  /// \param a1 Argument 1.
973  /// \param a2 Argument 2.
974  /// \param a3 Argument 3.
975  /// \param a4 Argument 4.
976  /// \param a5 Argument 5.
977  /// \param a6 Argument 6.
978  /// \param a7 Argument 7.
979  /// \param a8 Argument 8.
980  /// \param a9 Argument 9.
981  /// \return Description needed.
982  template <typename memfnT, typename a1T, typename a2T, typename a3T,
983  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T,
984  typename a9T>
986  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
987  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
988  const a7T& a7, const a8T& a8, const a9T& a9) const
989  {
990  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
991  am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8),
992  am_arg(a9));
993  }
994 
995  /// Sends task to derived class method `returnT (this->*memfn)()`.
996 
997  /// \todo Descriptions needed.
998  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
999  /// \param dest Description needed.
1000  /// \param memfn Verify: The member function to be invoked for the task.
1001  /// \param attr Description needed.
1002  /// \return Description needed.
1003  template <typename memfnT>
1005  task(ProcessID dest, memfnT memfn, const TaskAttributes& attr = TaskAttributes()) const {
1008  if (dest == me)
1009  return world.taskq.add(task_helper::make_task_fn(this, memfn), attr);
1010  else
1011  return send_task<taskT>(dest, memfn, voidT::value, voidT::value,
1014  }
1015 
1016  /// Sends task to derived class method `returnT (this->*memfn)(a1)`.
1017 
1018  /// \todo Descriptions needed.
1019  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1020  /// \tparam a1T Type of argument 1.
1021  /// \param dest Description needed.
1022  /// \param memfn Verify: The member function to be invoked for the task.
1023  /// \param a1 Argument 1.
1024  /// \param attr Description needed.
1025  /// \return Description needed.
1026  template <typename memfnT, typename a1T>
1028  task(ProcessID dest, memfnT memfn, const a1T& a1,
1029  const TaskAttributes& attr = TaskAttributes()) const
1030  {
1032  typedef TaskFn<typename task_helper::wrapperT,
1033  typename detail::task_arg<a1T>::type> taskT;
1034  if (dest == me)
1035  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1036  a1, attr);
1037  else
1038  return send_task<taskT>(dest, memfn, am_arg(a1), voidT::value,
1041  }
1042 
1043  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2)`.
1044 
1045  /// \todo Descriptions needed.
1046  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1047  /// \tparam a1T Type of argument 1.
1048  /// \tparam a2T Type of argument 2.
1049  /// \param dest Description needed.
1050  /// \param memfn Verify: The member function to be invoked for the task.
1051  /// \param a1 Argument 1.
1052  /// \param a2 Argument 2.
1053  /// \param attr Description needed.
1054  /// \return Description needed.
1055  template <typename memfnT, typename a1T, typename a2T>
1057  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1058  const TaskAttributes& attr = TaskAttributes()) const
1059  {
1061  typedef TaskFn<typename task_helper::wrapperT,
1062  typename detail::task_arg<a1T>::type,
1063  typename detail::task_arg<a2T>::type> taskT;
1064  if (dest == me)
1065  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1066  a1, a2, attr);
1067  else
1068  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1071  }
1072 
1073  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3)`.
1074 
1075  /// \todo Descriptions needed.
1076  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1077  /// \tparam a1T Type of argument 1.
1078  /// \tparam a2T Type of argument 2.
1079  /// \tparam a3T Type of argument 3.
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 attr Description needed.
1086  /// \return Description needed.
1087  template <typename memfnT, typename a1T, typename a2T, typename a3T>
1089  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1090  const a3T& a3, const TaskAttributes& attr = TaskAttributes()) const
1091  {
1093  typedef TaskFn<typename task_helper::wrapperT,
1094  typename detail::task_arg<a1T>::type,
1095  typename detail::task_arg<a2T>::type,
1096  typename detail::task_arg<a3T>::type> taskT;
1097  if (dest == me)
1098  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1099  a1, a2, a3, attr);
1100  else
1101  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1104  }
1105 
1106  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4)`.
1107 
1108  /// \todo Descriptions needed.
1109  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1110  /// \tparam a1T Type of argument 1.
1111  /// \tparam a2T Type of argument 2.
1112  /// \tparam a3T Type of argument 3.
1113  /// \tparam a4T Type of argument 4.
1114  /// \param dest Description needed.
1115  /// \param memfn Verify: The member function to be invoked for the task.
1116  /// \param a1 Argument 1.
1117  /// \param a2 Argument 2.
1118  /// \param a3 Argument 3.
1119  /// \param a4 Argument 4.
1120  /// \param attr Description needed.
1121  /// \return Description needed.
1122  template <typename memfnT, typename a1T, typename a2T, typename a3T,
1123  typename a4T>
1125  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1126  const a3T& a3, const a4T& a4, const TaskAttributes& attr = TaskAttributes()) const
1127  {
1129  typedef TaskFn<typename task_helper::wrapperT,
1130  typename detail::task_arg<a1T>::type,
1131  typename detail::task_arg<a2T>::type,
1132  typename detail::task_arg<a3T>::type,
1133  typename detail::task_arg<a4T>::type> taskT;
1134  if (dest == me)
1135  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1136  a1, a2, a3, a4, attr);
1137  else
1138  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1141  }
1142 
1143  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5)`.
1144 
1145  /// \todo Descriptions needed.
1146  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1147  /// \tparam a1T Type of argument 1.
1148  /// \tparam a2T Type of argument 2.
1149  /// \tparam a3T Type of argument 3.
1150  /// \tparam a4T Type of argument 4.
1151  /// \tparam a5T Type of argument 5.
1152  /// \param dest Description needed.
1153  /// \param memfn Verify: The member function to be invoked for the task.
1154  /// \param a1 Argument 1.
1155  /// \param a2 Argument 2.
1156  /// \param a3 Argument 3.
1157  /// \param a4 Argument 4.
1158  /// \param a5 Argument 5.
1159  /// \param attr Description needed.
1160  /// \return Description needed.
1161  template <typename memfnT, typename a1T, typename a2T, typename a3T,
1162  typename a4T, typename a5T>
1164  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1165  const a3T& a3, const a4T& a4, const a5T& a5,
1166  const TaskAttributes& attr = TaskAttributes()) const
1167  {
1169  typedef TaskFn<typename task_helper::wrapperT,
1170  typename detail::task_arg<a1T>::type,
1171  typename detail::task_arg<a2T>::type,
1172  typename detail::task_arg<a3T>::type,
1173  typename detail::task_arg<a4T>::type,
1174  typename detail::task_arg<a5T>::type> taskT;
1175  if (dest == me)
1176  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1177  a1, a2, a3, a4, a5, attr);
1178  else
1179  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1180  am_arg(a3), am_arg(a4), am_arg(a5), voidT::value,
1182  }
1183 
1184  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6)`.
1185 
1186  /// \todo Descriptions needed.
1187  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1188  /// \tparam a1T Type of argument 1.
1189  /// \tparam a2T Type of argument 2.
1190  /// \tparam a3T Type of argument 3.
1191  /// \tparam a4T Type of argument 4.
1192  /// \tparam a5T Type of argument 5.
1193  /// \tparam a6T Type of argument 6.
1194  /// \param dest Description needed.
1195  /// \param memfn Verify: The member function to be invoked for the task.
1196  /// \param a1 Argument 1.
1197  /// \param a2 Argument 2.
1198  /// \param a3 Argument 3.
1199  /// \param a4 Argument 4.
1200  /// \param a5 Argument 5.
1201  /// \param a6 Argument 6.
1202  /// \param attr Description needed.
1203  /// \return Description needed.
1204  template <typename memfnT, typename a1T, typename a2T, typename a3T,
1205  typename a4T, typename a5T, typename a6T>
1207  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1208  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1209  const TaskAttributes& attr = TaskAttributes()) const
1210  {
1212  typedef TaskFn<typename task_helper::wrapperT,
1213  typename detail::task_arg<a1T>::type,
1214  typename detail::task_arg<a2T>::type,
1215  typename detail::task_arg<a3T>::type,
1216  typename detail::task_arg<a4T>::type,
1217  typename detail::task_arg<a5T>::type,
1218  typename detail::task_arg<a6T>::type> taskT;
1219  if (dest == me)
1220  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1221  a1, a2, a3, a4, a5, a6, attr);
1222  else {
1223  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1224  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1226  }
1227  }
1228 
1229  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7)`.
1230 
1231  /// \todo Descriptions needed.
1232  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1233  /// \tparam a1T Type of argument 1.
1234  /// \tparam a2T Type of argument 2.
1235  /// \tparam a3T Type of argument 3.
1236  /// \tparam a4T Type of argument 4.
1237  /// \tparam a5T Type of argument 5.
1238  /// \tparam a6T Type of argument 6.
1239  /// \tparam a7T Type of argument 7.
1240  /// \param dest Description needed.
1241  /// \param memfn Verify: The member function to be invoked for the task.
1242  /// \param a1 Argument 1.
1243  /// \param a2 Argument 2.
1244  /// \param a3 Argument 3.
1245  /// \param a4 Argument 4.
1246  /// \param a5 Argument 5.
1247  /// \param a6 Argument 6.
1248  /// \param a7 Argument 7.
1249  /// \param attr Description needed.
1250  /// \return Description needed.
1251  template <typename memfnT, typename a1T, typename a2T, typename a3T,
1252  typename a4T, typename a5T, typename a6T, typename a7T>
1254  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1255  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1256  const a7T& a7, const TaskAttributes& attr = TaskAttributes()) const
1257  {
1259  typedef TaskFn<typename task_helper::wrapperT,
1260  typename detail::task_arg<a1T>::type,
1261  typename detail::task_arg<a2T>::type,
1262  typename detail::task_arg<a3T>::type,
1263  typename detail::task_arg<a4T>::type,
1264  typename detail::task_arg<a5T>::type,
1265  typename detail::task_arg<a6T>::type,
1266  typename detail::task_arg<a7T>::type> taskT;
1267  if (dest == me)
1268  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1269  a1, a2, a3, a4, a5, a6, a7, attr);
1270  else
1271  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1272  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1273  am_arg(a7), voidT::value, voidT::value, attr);
1274  }
1275 
1276  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8)`.
1277 
1278  /// \todo Descriptions needed.
1279  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1280  /// \tparam a1T Type of argument 1.
1281  /// \tparam a2T Type of argument 2.
1282  /// \tparam a3T Type of argument 3.
1283  /// \tparam a4T Type of argument 4.
1284  /// \tparam a5T Type of argument 5.
1285  /// \tparam a6T Type of argument 6.
1286  /// \tparam a7T Type of argument 7.
1287  /// \tparam a8T Type of argument 8.
1288  /// \param dest Description needed.
1289  /// \param memfn Verify: The member function to be invoked for the task.
1290  /// \param a1 Argument 1.
1291  /// \param a2 Argument 2.
1292  /// \param a3 Argument 3.
1293  /// \param a4 Argument 4.
1294  /// \param a5 Argument 5.
1295  /// \param a6 Argument 6.
1296  /// \param a7 Argument 7.
1297  /// \param a8 Argument 8.
1298  /// \param attr Description needed.
1299  /// \return Description needed.
1300  template <typename memfnT, typename a1T, typename a2T, typename a3T,
1301  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T>
1303  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1304  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1305  const a7T& a7, const a8T& a8,
1306  const TaskAttributes& attr = TaskAttributes()) const
1307  {
1309  typedef TaskFn<typename task_helper::wrapperT,
1310  typename detail::task_arg<a1T>::type,
1311  typename detail::task_arg<a2T>::type,
1312  typename detail::task_arg<a3T>::type,
1313  typename detail::task_arg<a4T>::type,
1314  typename detail::task_arg<a5T>::type,
1315  typename detail::task_arg<a6T>::type,
1316  typename detail::task_arg<a7T>::type,
1317  typename detail::task_arg<a8T>::type> taskT;
1318  if (dest == me)
1319  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1320  a1, a2, a3, a4, a5, a6, a7, a8, attr);
1321  else {
1322  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1323  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1324  am_arg(a7), am_arg(a8), voidT::value, attr);
1325  }
1326  }
1327 
1328  /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8,a9)`.
1329 
1330  /// \todo Descriptions needed.
1331  /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1332  /// \tparam a1T Type of argument 1.
1333  /// \tparam a2T Type of argument 2.
1334  /// \tparam a3T Type of argument 3.
1335  /// \tparam a4T Type of argument 4.
1336  /// \tparam a5T Type of argument 5.
1337  /// \tparam a6T Type of argument 6.
1338  /// \tparam a7T Type of argument 7.
1339  /// \tparam a8T Type of argument 8.
1340  /// \tparam a9T Type of argument 9.
1341  /// \param dest Description needed.
1342  /// \param memfn Verify: The member function to be invoked for the task.
1343  /// \param a1 Argument 1.
1344  /// \param a2 Argument 2.
1345  /// \param a3 Argument 3.
1346  /// \param a4 Argument 4.
1347  /// \param a5 Argument 5.
1348  /// \param a6 Argument 6.
1349  /// \param a7 Argument 7.
1350  /// \param a8 Argument 8.
1351  /// \param a9 Argument 9.
1352  /// \param attr Description needed.
1353  /// \return Description needed.
1354  ///
1355  /// \todo Could we use variadic templates to eliminate a lot of this code duplication?
1356  template <typename memfnT, typename a1T, typename a2T, typename a3T,
1357  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T,
1358  typename a9T>
1360  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1361  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1362  const a7T& a7, const a8T& a8, const a9T& a9,
1363  const TaskAttributes& attr = TaskAttributes()) const
1364  {
1366  typedef TaskFn<typename task_helper::wrapperT,
1367  typename detail::task_arg<a1T>::type,
1368  typename detail::task_arg<a2T>::type,
1369  typename detail::task_arg<a3T>::type,
1370  typename detail::task_arg<a4T>::type,
1371  typename detail::task_arg<a5T>::type,
1372  typename detail::task_arg<a6T>::type,
1373  typename detail::task_arg<a7T>::type,
1374  typename detail::task_arg<a8T>::type,
1375  typename detail::task_arg<a9T>::type> taskT;
1376  if (dest == me)
1377  return world.taskq.add(task_helper::make_task_fn(this, memfn),
1378  a1, a2, a3, a4, a5, a6, a7, a8, a9, attr);
1379  else
1380  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1381  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1382  am_arg(a7), am_arg(a8), am_arg(a9), attr);
1383  }
1384 
1385  virtual ~WorldObject() {
1386  if(initialized()) {
1387  MADNESS_ASSERT_NOEXCEPT(World::exists(&world) && world.ptr_from_id<Derived>(id()) && *world.ptr_from_id<Derived>(id()) == this);
1388  world.unregister_ptr(this->id());
1389  }
1390  }
1391 
1392 #ifdef MADNESS_WORLDOBJECT_FUTURE_TRACE
1393  /// "traces" future evaluation by counting their assignments in a static table
1394 
1395  /// Counts future assignments in a a statically-sized table to make this as lightweight/lock-free as possible
1396  /// with minimal effort. Can only trace objects of a single World.
1397  /// \param[in,out] f the future to be traced; if ready, will be unchanged (but contribute to the trace
1398  /// statistics of this object), or have a callback registered that will update the tracing statistics on
1399  /// assignment
1400  /// \warning this function will trace futures for WorldObjects associated with default world (id=0) only;
1401  /// use CMake variable `MADNESS_WORLDOBJECT_FUTURE_TRACE_WORLD_ID` to adjust the target World ID.
1402  /// \warning this function will trace futures for WorldObjects with IDs < 1000000 only;
1403  /// use CMake variable `MADNESS_WORLDOBJECT_FUTURE_TRACE_MAX_NOBJECTS` to adjust the limit.
1404  template <typename T>
1405  std::enable_if_t<!std::is_same_v<T,void>,void> trace(Future<T>& f) const;
1406 
1407  /// \param[in] id a WorldObject ID
1408  /// \return true if futures associated with \p id are traced
1409  static bool trace_futures(const uniqueidT &id);
1410 
1411  /// \return true if futures associated with this object are traced
1412  bool trace_futures() const {
1413  return trace_futures(this->id());
1414  }
1415 
1416  /// \param[in] id report tracing stats for this WorldObject
1417  /// \return number of futures given to trace() of the WorldObject with ID \p id
1418  static std::size_t trace_status_nfuture_registered(const uniqueidT& id);
1419 
1420  /// \return number of futures given to trace() of this object
1421  std::size_t trace_status_nfuture_registered() const {
1422  return trace_status_nfuture_registered(this->id());
1423  }
1424 
1425  /// \param[in] id report tracing stats for this WorldObject
1426  /// \return number of assigned futures given to trace() of the WorldObject with ID \p id
1427  static std::size_t trace_status_nfuture_assigned(const uniqueidT& id);
1428 
1429  /// \return number of assigned futures registered via `this->trace()`
1430  std::size_t trace_status_nfuture_assigned() const {
1431  return trace_status_nfuture_assigned(this->id());
1432  }
1433 #endif
1434  };
1435 
1436 #ifdef MADNESS_WORLDOBJECT_FUTURE_TRACE
1437  namespace detail {
1438  template <typename Derived> struct WorldObjectFutureTracer {
1439  // this value is the world ID to trace
1440  constexpr static std::size_t world_id =
1441 #ifndef MADNESS_WORLDOBJECT_FUTURE_TRACE_WORLD_ID
1442  0
1443 #else
1444  MADNESS_WORLDOBJECT_FUTURE_TRACE_WORLD_ID
1445 #endif
1446  ;
1447  // this value is 1 greater than is the highest ID of WorldObjects to trace
1448  constexpr static std::size_t max_object_id =
1449 #ifndef MADNESS_WORLDOBJECT_FUTURE_TRACE_MAX_NOBJECTS
1450  1000000
1451 #else
1452  MADNESS_WORLDOBJECT_FUTURE_TRACE_MAX_NOBJECTS
1453 #endif
1454  ;
1455 
1456  static constexpr bool do_trace(const uniqueidT& id) {
1457  return id.get_world_id() == world_id &&
1458  id.get_obj_id() < max_object_id;
1459  }
1460 
1461  static std::array<std::atomic<std::size_t>, max_object_id>
1462  nfuture_registered;
1463  static std::array<std::atomic<std::size_t>, max_object_id>
1464  nfuture_assigned;
1465 
1466  struct Initializer {
1467  Initializer() {
1468  for (auto &&v : nfuture_registered) {
1469  v.store(0);
1470  }
1471  for (auto &&v : nfuture_assigned) {
1472  v.store(0);
1473  }
1474  }
1475  };
1476  static Initializer initializer;
1477 
1478  struct FutureTracer : public CallbackInterface {
1479  FutureTracer(const uniqueidT &id) : id_(id) {
1480  if (do_trace(id_)) {
1481  nfuture_registered[id_.get_obj_id()]++;
1482  }
1483  }
1484 
1485  // Not allowed
1486  FutureTracer(const FutureTracer &) = delete;
1487  FutureTracer &operator=(const FutureTracer &) = delete;
1488 
1489  virtual ~FutureTracer() {}
1490 
1491  /// Notify this object that the future has been set.
1492 
1493  /// This will set the value of the future on the remote node and delete
1494  /// this callback object.
1495  void notify() override {
1496  if (do_trace(id_)) {
1497  nfuture_assigned[id_.get_obj_id()]++;
1498  }
1499  delete this;
1500  }
1501 
1502  private:
1503  uniqueidT id_;
1504  }; // struct FutureTracer
1505 
1506  }; // struct WorldObjectFutureTracer
1507  template <typename Derived>
1508  typename WorldObjectFutureTracer<Derived>::Initializer
1509  WorldObjectFutureTracer<Derived>::initializer;
1510  template <typename Derived>
1511  std::array<std::atomic<std::size_t>, WorldObjectFutureTracer<Derived>::max_object_id>
1512  WorldObjectFutureTracer<Derived>::nfuture_registered;
1513  template <typename Derived>
1514  std::array<std::atomic<std::size_t>, WorldObjectFutureTracer<Derived>::max_object_id>
1515  WorldObjectFutureTracer<Derived>::nfuture_assigned;
1516  } // namespace detail
1517 
1518  template <typename Derived>
1519  template <typename T>
1520  std::enable_if_t<!std::is_same_v<T,void>,void> WorldObject<Derived>::trace(Future<T>& f) const {
1521  f.register_callback(
1522  new typename detail::WorldObjectFutureTracer<Derived>::FutureTracer(
1523  this->id()));
1524  }
1525 
1526  template <typename Derived>
1527  bool WorldObject<Derived>::trace_futures(const uniqueidT& id) {
1528  return detail::WorldObjectFutureTracer<Derived>::do_trace(id);
1529  }
1530 
1531  template <typename Derived>
1532  std::size_t WorldObject<Derived>::trace_status_nfuture_registered(const uniqueidT& id) {
1533  if (detail::WorldObjectFutureTracer<
1534  Derived>::do_trace(id)) {
1535  return detail::WorldObjectFutureTracer<
1536  Derived>::nfuture_registered[id.get_obj_id()];
1537  }
1538  else return 0;
1539  }
1540 
1541  template <typename Derived>
1542  std::size_t WorldObject<Derived>::trace_status_nfuture_assigned(const uniqueidT& id) {
1543  if (detail::WorldObjectFutureTracer<
1544  Derived>::do_trace(id)) {
1545  return detail::WorldObjectFutureTracer<
1546  Derived>::nfuture_assigned[id.get_obj_id()];
1547  }
1548  else return 0;
1549  }
1550 
1551 #endif // MADNESS_WORLDOBJECT_FUTURE_TRACE
1552 
1553  namespace archive {
1554 
1555  /// Specialization of \c ArchiveLoadImpl for globally-addressable objects.
1556 
1557  /// \tparam Derived The derived class of \c WorldObject in a curiously
1558  /// repeating template pattern.
1559  template <class Derived>
1561 
1562  /// Read a globally-addressable object from a \c BufferInputArchive.
1563 
1564  /// \param[in,out] ar The archive.
1565  /// \param[out] ptr The read object.
1566  static inline void load(const BufferInputArchive& ar, WorldObject<Derived>*& ptr) {
1567  uniqueidT id;
1568  ar & id;
1569  World* world = World::world_from_id(id.get_world_id());
1570  MADNESS_ASSERT(world);
1571  auto ptr_opt = world->ptr_from_id< WorldObject<Derived> >(id);
1572  if (!ptr_opt) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0);
1573  ptr = *ptr_opt;
1574  if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally deregistered object",0);
1575  }
1576  };
1577 
1578  /// Specialization of \c ArchiveStoreImpl for globally-addressable objects.
1579 
1580  /// \tparam Derived The derived class of \c WorldObject in a curiously
1581  /// repeating template pattern.
1582  template <class Derived>
1584 
1585  /// Write a globally-addressable object to a \c BufferOutputArchive.
1586 
1587  /// \param[in,out] ar The archive.
1588  /// \param[in] ptr The object to store.
1589  static inline void store(const BufferOutputArchive& ar, WorldObject<Derived>* const& ptr) {
1590  ar & ptr->id();
1591  }
1592  };
1593 
1594  /// Specialization of \c ArchiveLoadImpl for constant, globally-addressable objects.
1595 
1596  /// \tparam Derived The derived class of \c WorldObject in a curiously
1597  /// repeating template pattern.
1598  template <class Derived>
1600 
1601  /// Read a globally-addressable object from a \c BufferInputArchive.
1602 
1603  /// \param[in,out] ar The archive.
1604  /// \param[out] ptr The read object.
1605  static inline void load(const BufferInputArchive& ar, const WorldObject<Derived>*& ptr) {
1606  uniqueidT id;
1607  ar & id;
1608  World* world = World::world_from_id(id.get_world_id());
1609  MADNESS_ASSERT(world);
1610  auto ptr_opt = world->ptr_from_id< WorldObject<Derived> >(id);
1611  if (!ptr_opt) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0);
1612  ptr = *ptr_opt;
1613  if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally deregistered object",0);
1614  }
1615  };
1616 
1617  /// Specialization of \c ArchiveStoreImpl for constant, globally-addressable objects.
1618 
1619  /// \tparam Derived The derived class of \c WorldObject in a curiously
1620  /// repeating template pattern.
1621  template <class Derived>
1623 
1624  /// Write a globally-addressable object to a \c BufferOutputArchive.
1625 
1626  /// \param[in,out] ar The archive.
1627  /// \param[in] ptr The object to store.
1628  static inline void store(const BufferOutputArchive& ar, const WorldObject<Derived>* const& ptr) {
1629  ar & ptr->id();
1630  }
1631  };
1632  } // namespace archive
1633 } // namespace madness
1634 
1635 #endif // MADNESS_WORLD_WORLD_OBJECT_H__INCLUDED
1636 
1637 /// @}
World active message that extends an RMI message.
Definition: worldam.h:80
Implements the functionality of futures.
Definition: future.h:74
Specialization of Future<void> for internal convenience. This does nothing useful!
Definition: future.h:736
static const Future< void > value
Definition: future.h:742
A future is a possibly yet unevaluated value.
Definition: future.h:373
remote_refT remote_ref(World &world) const
Returns a structure used to pass references to another process.
Definition: future.h:675
static const attrT ATTR_UNORDERED
Definition: worldrmi.h:180
Simple structure used to manage references/pointers to remote instances.
Definition: worldref.h:395
Mutex that is applied/released at start/end of a scope.
Definition: worldmutex.h:239
Spinlock using pthread spinlock operations.
Definition: worldmutex.h:253
void lock() const
Acquire the spinlock waiting if necessary.
Definition: worldmutex.h:277
void unlock() const
Free a spinlock owned by this thread.
Definition: worldmutex.h:287
Contains attributes of a task.
Definition: thread.h:323
void send(ProcessID dest, am_handlerT op, const AmArg *arg, const int attr=RMI::ATTR_ORDERED)
Sends a managed non-blocking active message.
Definition: worldam.h:278
Implements most parts of a globally addressable object (via unique ID).
Definition: world_object.h:364
static const T & am_arg(const T &t)
Definition: world_object.h:549
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn) const
Definition: world_object.h:731
WorldObject(World &world)
Constructor that associates an object (via the derived class) with a globally unique ID.
Definition: world_object.h:703
static bool is_ready(const uniqueidT &id, objT *&obj, const AmArg &arg, am_handlerT ptr)
Definition: world_object.h:411
static Spinlock pending_mutex
Definition: world_object.h:389
const uniqueidT & id() const
Returns the globally unique object ID.
Definition: world_object.h:711
WorldObject< Derived > objT
Definition: world_object.h:367
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2,a3,a4,a5,a6).
Definition: world_object.h:1207
WorldObject(const WorldObject &other)
Definition: world_object.h:370
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1).
Definition: world_object.h:1028
World & world
The World this object belongs to. (Think globally, act locally).
Definition: world_object.h:381
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8).
Definition: world_object.h:1303
std::list< detail::PendingMsg > pendingT
Definition: world_object.h:376
WorldObject & operator=(const WorldObject &)=delete
detail::task_result_type< memfnT >::futureT send_am(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const a9T &a9) const
Definition: world_object.h:583
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2,a3).
Definition: world_object.h:1089
void process_pending()
To be called from derived constructor to process pending messages.
Definition: world_object.h:656
static void spawn_remote_task_handler(const AmArg &arg)
Handler for remote arguments.
Definition: world_object.h:505
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const a9T &a9) const
Definition: world_object.h:986
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4) const
Definition: world_object.h:818
ProcessID me
Rank of self.
Definition: world_object.h:385
volatile bool ready
True if ready to rock 'n roll.
Definition: world_object.h:384
virtual ~WorldObject()
Definition: world_object.h:1385
detail::voidT voidT
Definition: world_object.h:379
taskT::futureT send_task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const a9T &a9, const TaskAttributes &attr) const
Definition: world_object.h:633
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7).
Definition: world_object.h:1254
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2).
Definition: world_object.h:1057
uniqueidT objid
Sense of self.
Definition: world_object.h:386
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7) const
Definition: world_object.h:911
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8) const
Definition: world_object.h:947
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)().
Definition: world_object.h:1005
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2) const
Definition: world_object.h:769
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const a9T &a9, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8,...
Definition: world_object.h:1360
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5) const
Definition: world_object.h:847
static const T & am_arg(const Future< T > &f)
Definition: world_object.h:536
static volatile pendingT pending
Buffer for pending messages.
Definition: world_object.h:390
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3) const
Definition: world_object.h:791
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2,a3,a4,a5).
Definition: world_object.h:1164
static void handler(const AmArg &arg)
Handler for an incoming AM.
Definition: world_object.h:471
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1) const
Definition: world_object.h:749
World & get_world() const
Returns a reference to the world.
Definition: world_object.h:717
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)(a1,a2,a3,a4).
Definition: world_object.h:1125
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6) const
Definition: world_object.h:878
void add(TaskInterface *t)
Add a new local task, taking ownership of the pointer.
Definition: world_task_queue.h:466
A parallel world class.
Definition: world.h:132
static World * world_from_id(std::uint64_t id)
Convert a World ID to a World pointer.
Definition: world.h:474
WorldTaskQueue & taskq
Task queue.
Definition: world.h:204
void unregister_ptr(const uniqueidT id)
Unregister a global object via its the unique ID.
Definition: world.h:387
std::optional< T * > ptr_from_id(uniqueidT id) const
Look up a local pointer from a world-wide unique ID.
Definition: world.h:414
static bool exists(World *world)
Check if the World exists in the registry.
Definition: world.h:247
WorldAmInterface & am
AM interface.
Definition: world.h:203
Wraps an archive around a memory buffer for input.
Definition: buffer_archive.h:134
Wraps an archive around a memory buffer for output.
Definition: buffer_archive.h:59
Functor wrapper for object and member function pointers.
Definition: mem_func_wrapper.h:89
Class for unique global IDs.
Definition: uniqueid.h:53
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition: derivatives.cc:72
auto T(World &world, response_space &f) -> response_space
Definition: global_functions.cc:34
archive_array< unsigned char > wrap_opaque(const T *, unsigned int)
Factory function to wrap a pointer to contiguous data as an opaque (uchar) archive_array.
Definition: archive.h:925
auto to_rel_memfn_ptr(const T &fn)
converts nonstatic member function pointer to the relative equivalent
Definition: archive.h:259
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only)
Definition: tensor.h:2502
static const double v
Definition: hatom_sf_dirac.cc:20
#define MADNESS_PRAGMA_CLANG(x)
Definition: madness_config.h:200
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition: madness_exception.h:119
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition: madness_exception.h:134
#define MADNESS_ASSERT_NOEXCEPT(condition)
Same as MADNESS_ASSERT , but never throws.
Definition: madness_exception.h:141
std::enable_if< std::is_void< typename detail::result_of< fnT >::type >::value >::type run_function(Future< void > &result, fnT fn, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &)
Definition: taskfn.h:317
static const uniqueidT & peek(const AmArg &arg)
Extract the unique object ID from an incoming active message header.
Definition: world_object.h:200
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
AmArg * new_am_arg(const argT &... args)
Convenience template for serializing arguments into a new AmArg.
Definition: worldam.h:194
bool initialized()
Check if the MADNESS runtime has been initialized (and not subsequently finalized).
Definition: world.cc:74
static double pop(std::vector< double > &v)
Definition: SCF.cc:113
void free_am_arg(AmArg *arg)
Frees an AmArg allocated with alloc_am_arg.
Definition: worldam.h:177
NDIM & f
Definition: mra.h:2416
void(* am_handlerT)(const AmArg &)
Type of AM handler functions.
Definition: worldam.h:77
std::string type(const PairType &n)
Definition: PNOParameters.h:18
AmArg * copy_am_arg(const AmArg &arg)
Definition: worldam.h:170
Definition: mraimpl.h:50
Wrap a callable object and its arguments into a task function.
Definition: taskfn.h:473
Base class for WorldObject, useful for introspection.
Definition: world_object.h:340
virtual ~WorldObjectBase()=default
static void load(const BufferInputArchive &ar, WorldObject< Derived > *&ptr)
Read a globally-addressable object from a BufferInputArchive.
Definition: world_object.h:1566
static void load(const BufferInputArchive &ar, const WorldObject< Derived > *&ptr)
Read a globally-addressable object from a BufferInputArchive.
Definition: world_object.h:1605
Default load of an object via serialize(ar, t).
Definition: archive.h:666
static void store(const BufferOutputArchive &ar, WorldObject< Derived > *const &ptr)
Write a globally-addressable object to a BufferOutputArchive.
Definition: world_object.h:1589
static void store(const BufferOutputArchive &ar, const WorldObject< Derived > *const &ptr)
Write a globally-addressable object to a BufferOutputArchive.
Definition: world_object.h:1628
Default store of an object via serialize(ar, t).
Definition: archive.h:611
Common base class for pending messages to ensure in-order processing.
Definition: world_object.h:63
void invokehandler()
Definition: world_object.h:71
uniqueidT id
Definition: world_object.h:64
AmArg * arg
Definition: world_object.h:66
am_handlerT handler
Definition: world_object.h:65
PendingMsg(uniqueidT id, am_handlerT handler, const AmArg &arg)
Definition: world_object.h:68
std::conditional< memfunc_traits< memfnT >::constness, const objT *, objT * >::type ptrT
Definition: world_object.h:281
MemFuncWrapper< shared_ptrT, memfnT, typename result_of< memfnT >::type > wrapperT
Definition: world_object.h:288
std::conditional< memfunc_traits< memfnT >::constness, std::shared_ptr< const objT >, std::shared_ptr< objT > >::type shared_ptrT
Definition: world_object.h:285
Definition: world_object.h:212
static wrapperT make_task_fn(const objT *obj, memfnT memfn)
Definition: world_object.h:227
static wrapperT make_task_fn(WorldObject< objT > *obj, memfnT memfn)
Definition: world_object.h:259
std::conditional< memfunc_traits< memfnT >::constness, const objT *, objT * >::type ptrT
Definition: world_object.h:215
static wrapperT make_task_fn(const WorldObject< objT > *obj, memfnT memfn)
Definition: world_object.h:249
static wrapperT make_task_fn(objT *obj, memfnT memfn)
Definition: world_object.h:238
MemFuncWrapper< ptrT, memfnT, typename result_of< memfnT >::type > wrapperT
Definition: world_object.h:218
Definition: world_object.h:94
TaskAttributes attr
Definition: world_object.h:100
void serialize(const Archive &ar)
Serializes a info_base for I/O.
Definition: world_object.h:130
ProcessID requestor
Definition: world_object.h:98
memfunT_rel_ptr memfun_rel_ptr
Definition: world_object.h:99
memfunT memfun() const
Definition: world_object.h:103
uniqueidT id
Definition: world_object.h:97
info_base()
Definition: world_object.h:109
info_base(const uniqueidT &id, ProcessID requestor, memfunT memfun, const TaskAttributes &attr=TaskAttributes())
Definition: world_object.h:118
decltype(archive::to_rel_memfn_ptr(std::declval< memfunT >())) memfunT_rel_ptr
Definition: world_object.h:95
Definition: world_object.h:140
Future< REMFUTURE(MEMFUN_RETURNT(memfunT)) > futureT
Future for a return value of the memory function.
Definition: world_object.h:142
info()
Definition: world_object.h:148
void serialize(const Archive &ar)
Serializes a info for I/O.
Definition: world_object.h:178
info(const AmArg &arg)
Definition: world_object.h:154
refT ref
Definition: world_object.h:146
info(const uniqueidT &id, ProcessID requestor, memfunT memfun, const refT &ref, const TaskAttributes &attr=TaskAttributes())
Definition: world_object.h:168
RemoteReference< FutureImpl< REMFUTURE(MEMFUN_RETURNT(memfunT)) > > refT
Definition: world_object.h:144
T type
Definition: taskfn.h:213
Implements Dqueue, Thread, ThreadBase and ThreadPool.
#define REMFUTURE(T)
Macro to determine type of future (by removing wrapping Future template).
Definition: type_traits.h:162
#define MEMFUN_RETURNT(MEMFUN)
Macro to make member function type traits easier to use.
Definition: type_traits.h:697
const double a2
Definition: vnucso.cc:86
const double a1
Definition: vnucso.cc:85
Defines TaskInterface and implements WorldTaskQueue and associated stuff.
int ProcessID
Used to clearly identify process number/rank.
Definition: worldtypes.h:43