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
43
44#include <array>
45#include <atomic>
46#include <cstddef>
47#include <type_traits>
48
49/// \addtogroup world_object
50/// @{
51
52namespace 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.
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)
122 , memfun_rel_ptr(archive::to_rel_memfn_ptr(memfun))
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.
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.
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
340
341 /// Holds the parts of a \c WorldObject that do not depend on the derived
342 /// class: the unique object ID and the \c World the object belongs to,
343 /// the latter accessible to the derived class via \c get_world().
344 /// Should not be used directly, but rather through \c WorldObject<Derived>.
346 private:
347 uniqueidT objid; ///< Unique object ID; null until \c register_self() has been called.
348 World& world; ///< Memoized reference to the world to which this object belongs.
349 World::liveness_handleT world_liveness; ///< Reports whether \c world is still alive.
350
351 protected:
352
353 /// Construct a new WorldObjectBase.
354
355 /// Protected, should only be called from the \c WorldObject constructor.
356 /// \note This does \em not register the object with \p w; the derived
357 /// \c WorldObject must call \c register_self() to do that, once
358 /// its own members have been initialized.
359 /// \param[in] w The world to which this object belongs.
361 : objid(), world(w), world_liveness(w.liveness())
362 { }
363
364 /// Copy constructor; produces an \em unregistered object.
365
366 /// Exists solely so that the derived \c WorldObject remains copy
367 /// constructible (which pre-C++17 is needed to permit RVO), never to
368 /// produce a usable object. The copy aliases the world of \p other but
369 /// deliberately does not copy its ID and is not registered with the
370 /// world: were the copy destroyed it would otherwise unregister
371 /// \p other, evicting a live object from the world's ID maps.
372 /// \param[in] other The object whose world is to be aliased.
374 : objid(), world(other.world), world_liveness(other.world_liveness)
375 { }
376
377 /// Registers this object with its world, making it globally addressable.
378
379 /// \attention Must be called by the \c WorldObject constructor \em after
380 /// all of its members have been initialized: registration publishes this
381 /// object to the active-message handlers running on the runtime threads,
382 /// which read those members (see \c WorldObject::is_ready()).
383 /// \tparam DerivedT The derived class being registered.
384 /// \param[in] this_ptr Pointer to the derived object being registered.
385 template <typename DerivedT>
386 void register_self(DerivedT* this_ptr) {
387 MADNESS_ASSERT(!objid); // registering twice would leak the first ID
388 objid = world.register_ptr(this_ptr);
389 }
390
391 /// Unchecked access to the memoized world reference.
392
393 /// \warning Does not validate that the world is still alive; only use
394 /// where that has already been established (e.g. right after a
395 /// \c world_is_alive() check).
396 /// \return A reference to the world.
397 World& get_world_unchecked() const noexcept {
398 return world;
399 }
400
401 public:
402
404 // objid is null for an unregistered object, i.e. one produced by the
405 // copy ctor above; such an object owns no entry in the world's maps
406 if(initialized() && objid) {
408 "WorldObjectBase::~WorldObjectBase() the world of this object has already been destroyed");
409 // The assertion above is compiled out in release builds, so it
410 // cannot be what keeps us off a dangling reference; world_is_alive()
411 // is a real (relaxed) load and always runs. Nothing is leaked by
412 // skipping: the maps we would unregister from died with the world.
413 if(world_is_alive()) {
414 auto* world_ptr = World::world_from_id(objid.get_world_id());
415 MADNESS_ASSERT_NOEXCEPT(world_ptr != nullptr && "WorldObjectBase::~WorldObjectBase() failed to find world");
416 MADNESS_ASSERT_NOEXCEPT(world_ptr == &world &&
417 "WorldObjectBase::~WorldObjectBase() cached world differs from world in object ID");
419 }
420 }
421 }
422
423 /// Returns the globally unique object ID.
424 const uniqueidT& id() const {
425 return objid;
426 }
427
428 /// Reports whether the world to which this object belongs still exists.
429
430 /// A \c WorldObject must not outlive its \c World, but it happens; this
431 /// makes the (otherwise silent) use-after-free detectable.
432 /// \return True if the world of this object has not been destroyed yet.
433 bool world_is_alive() const noexcept {
434 return world_liveness && world_liveness->load(std::memory_order_relaxed);
435 }
436
437 /// Get the world to which this object belongs.
438 /// \return A reference to the world.
439 /// \note The reference is memoized, hence only valid while that world is
440 /// alive; this is asserted here rather than paying for a lookup of
441 /// the world by its ID, since \c get_world() is called in hot loops.
442 /// \todo Promote the assertion to \c MADNESS_CHECK, so that the
443 /// use-after-free is also caught in release builds (where
444 /// \c MADNESS_ASSERT compiles away), once the cost of the
445 /// liveness load in hot loops has been measured.
446 World& get_world() const {
448 return world;
449 }
450
451 /// Get the world to which this object belongs, without risking a throw.
452
453 /// Same as \c get_world(), except the memoized reference is validated
454 /// with \c MADNESS_ASSERT_NOEXCEPT, which aborts rather than throws.
455 /// Use this from destructors and other \c noexcept contexts, where a
456 /// throwing \c MADNESS_ASSERT would call \c std::terminate and thereby
457 /// discard the diagnostic.
458 /// \return A reference to the world.
459 World& get_world_noexcept() const noexcept {
461 return world;
462 }
463 };
464
465 /// Implements most parts of a globally addressable object (via unique ID).
466
467 /// This class is deliberately not default constructible and does
468 /// not support assignment or copying. This ensures that each instance
469 /// is unique. Have a look at \c madness::WorldContainer for an example
470 /// of wrapping this using the PIMPL idiom and a shared pointer.
471 ///
472 /// When deriving classes:
473 /// -# Derived class has `WorldObject<Derived>` as a public base class.
474 /// -# Derived constructor:
475 /// -# invokes `WorldObject<Derived>(world)` constructor.
476 /// -# invokes `process_pending()`.
477 /// -# Derived destructor must either be deferred or preceeded by `gop.fence()`.
478 /// -# Derived class must have at least one virtual function for serialization
479 /// of derived class pointers to be cast to the appropriate type.
480 ///
481 /// The \c World is accessed through \c WorldObjectBase::get_world(), which
482 /// validates that it is still alive; derived classes that have already
483 /// established that can use \c WorldObjectBase::get_world_unchecked().
484 /// \note This class used to expose the \c World as a public data member
485 /// named \c world. That member is gone; replace \c obj.world with
486 /// \c obj.get_world() and, within a derived class, \c world with
487 /// \c this->get_world().
488 /// \tparam Derived The derived class. \c WorldObject is a curiously
489 /// recurring template pattern.
490 template <class Derived>
492 public:
493 /// \todo Description needed.
495
496 // copy ctor must be enabled to permit RVO; in C++17 will not need this.
497 // It never produces a usable object. The safety of that does not rest on
498 // the abort() alone: the base copy ctor deliberately leaves the copy
499 // unregistered, so destroying one would not unregister `other`.
501 : WorldObjectBase(other), ready(false), me(other.me) { abort(); }
502 // no copy
504
505 private:
506 /// \todo Description needed.
507 typedef std::list<detail::PendingMsg> pendingT;
508
509 /// \todo Description needed.
511
512 // The order here matters in a multi-threaded world
513 volatile bool ready; ///< True if ready to rock 'n roll.
514 ProcessID me; ///< Rank of self.
515
516
517 inline static Spinlock pending_mutex; ///< \todo Description needed.
518 inline static volatile pendingT pending; ///< Buffer for pending messages.
519
520
521 /// \todo Complete: Determine if [unknown] is ready (for ...).
522
523 /// The slightly convoluted logic is to ensure ordering when
524 /// processing pending messages. If a new message arrives
525 /// while processing incoming messages it must be queued.
526 ///
527 /// - If the object does not exist ---> not ready.
528 /// - If the object exists and is ready ---> ready.
529 /// - If the object exists and is not ready then
530 /// - if we are doing a queued/pending message --> ready.
531 /// - else this is a new message --> not ready.
532 ///
533 /// \param[in] id Description needed.
534 /// \param[in,out] obj Description needed.
535 /// \param[in] arg Description needed.
536 /// \param[in,out] ptr Description needed.
537 /// \return Description needed.
538 /// \todo Parameter/return descriptions needed.
539 static bool is_ready(const uniqueidT& id, objT*& obj, const AmArg& arg, am_handlerT ptr) {
540 std::optional<Derived *> opt_obj =
541 arg.get_world()->template ptr_from_id<Derived>(id);
542 if (opt_obj) {
543 // if opt_obj == nullptr, then this ID has already been deregistered
544 MADNESS_ASSERT(*opt_obj != nullptr);
545 obj = static_cast<objT *>(*opt_obj);
546 } else
547 obj = nullptr;
548
549 if (obj) {
550 if (obj->ready || arg.is_pending())
551 return true;
552 }
553
554 MADNESS_PRAGMA_CLANG(diagnostic push)
555 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template")
556
557 ScopedMutex<Spinlock> lock(pending_mutex); // BEGIN CRITICAL SECTION
558
559 if (!obj) {
560 std::optional<Derived *> opt_obj =
561 arg.get_world()->template ptr_from_id<Derived>(id);
562 if (opt_obj) {
563 // if opt_obj == nullptr, then this ID has already been deregistered
564 MADNESS_ASSERT(*opt_obj != nullptr);
565 obj = static_cast<objT *>(*opt_obj);
566 } else
567 obj = nullptr;
568 }
569
570 if (obj) {
571 if (obj->ready || arg.is_pending())
572 return true; // END CRITICAL SECTION
573 }
574 const_cast<AmArg &>(arg).set_pending();
575 const_cast<pendingT &>(pending).push_back(
576 detail::PendingMsg(id, ptr, arg));
577
578 MADNESS_PRAGMA_CLANG(diagnostic pop)
579
580 return false; // END CRITICAL SECTION
581 }
582
583 /// Handler for an incoming AM.
584
585 /// \todo Descriptions needed.
586 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
587 /// \tparam arg1T Type of argument 1.
588 /// \tparam arg2T Type of argument 2.
589 /// \tparam arg3T Type of argument 3.
590 /// \tparam arg4T Type of argument 4.
591 /// \tparam arg5T Type of argument 5.
592 /// \tparam arg6T Type of argument 6.
593 /// \tparam arg7T Type of argument 7.
594 /// \tparam arg8T Type of argument 8.
595 /// \tparam arg9T Type of argument 9.
596 /// \param[in] arg Description needed.
597 template <typename memfnT, typename arg1T, typename arg2T, typename arg3T, typename arg4T,
598 typename arg5T, typename arg6T, typename arg7T, typename arg8T, typename arg9T>
599 static void handler(const AmArg& arg) {
601
602 const uniqueidT& id = detail::peek(arg);
603 am_handlerT ptr = handler<memfnT,arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T,arg8T,arg9T>;
604 objT* obj;
605 if (is_ready(id,obj,arg,ptr)) {
607 typename detail::task_arg<arg1T>::type arg1;
608 typename detail::task_arg<arg2T>::type arg2;
609 typename detail::task_arg<arg3T>::type arg3;
610 typename detail::task_arg<arg4T>::type arg4;
611 typename detail::task_arg<arg5T>::type arg5;
612 typename detail::task_arg<arg6T>::type arg6;
613 typename detail::task_arg<arg7T>::type arg7;
614 typename detail::task_arg<arg8T>::type arg8;
615 typename detail::task_arg<arg9T>::type arg9;
616 MADNESS_PRAGMA_CLANG(diagnostic push)
617 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wuninitialized-const-reference")
618 arg & info & arg1 & arg2 & arg3 & arg4 & arg5 & arg6 & arg7 & arg8 & arg9;
619 MADNESS_PRAGMA_CLANG(diagnostic pop)
620 typename detail::info<memfnT>::futureT result(info.ref);
621 detail::run_function(result, task_helper::make_task_fn(obj, info.memfun()),
622 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
623 }
624 }
625
626
627 /// Handler for remote arguments.
628
629 /// \todo Descriptions needed.
630 /// \tparam taskT Description needed.
631 /// \param[in] arg Description needed.
632 template <typename taskT>
633 static void spawn_remote_task_handler(const AmArg& arg) {
634 typedef detail::WorldObjectTaskHelper<Derived,
635 typename taskT::functionT::memfn_type> task_helper;
636
637 MADNESS_ASSERT(taskT::arity <= 9u);
638
639 const uniqueidT& id = detail::peek(arg);
640 am_handlerT ptr = & objT::template spawn_remote_task_handler<taskT>;
641 objT* obj;
642 if (is_ready(id,obj,arg,ptr)) {
644
645 archive::BufferInputArchive input_arch = arg & info;
646
647 // Construct task
648 taskT* task = new taskT(typename taskT::futureT(info.ref),
649 task_helper::make_task_fn(obj, info.memfun()), info.attr, input_arch);
650
651 // Add task to queue
652 arg.get_world()->taskq.add(task);
653 }
654 }
655
656
657 /// \todo Brief description needed.
658
659 /// \todo Descriptions needed.
660 /// \tparam T Description needed.
661 /// \param[in] f Description needed.
662 /// \return Description needed.
663 template <typename T>
664 static inline const T& am_arg(const Future<T>& f) {
665 MADNESS_ASSERT(f.probe()); // Cannot serialize unassigned futures
666 return f.get();
667 }
668
669
670 /// \todo Brief description needed.
671
672 /// \todo Descriptions needed.
673 /// \tparam T Description needed.
674 /// \param[in] t Description needed.
675 /// \return Description needed.
676 template <typename T>
677 static inline const T& am_arg(const T& t) {
678 return t;
679 }
680
681
682 /// \todo Brief description needed.
683
684 /// \todo Descriptions needed.
685 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
686 /// \tparam a1T Type of argument 1.
687 /// \tparam a2T Type of argument 2.
688 /// \tparam a3T Type of argument 3.
689 /// \tparam a4T Type of argument 4.
690 /// \tparam a5T Type of argument 5.
691 /// \tparam a6T Type of argument 6.
692 /// \tparam a7T Type of argument 7.
693 /// \tparam a8T Type of argument 8.
694 /// \tparam a9T Type of argument 9.
695 /// \param dest Description needed.
696 /// \param memfn Verify: The member function to be invoked for the task.
697 /// \param a1 Argument 1.
698 /// \param a2 Argument 2.
699 /// \param a3 Argument 3.
700 /// \param a4 Argument 4.
701 /// \param a5 Argument 5.
702 /// \param a6 Argument 6.
703 /// \param a7 Argument 7.
704 /// \param a8 Argument 8.
705 /// \param a9 Argument 9.
706 /// \return Description needed.
707 template <typename memfnT, typename a1T, typename a2T, typename a3T,
708 typename a4T, typename a5T, typename a6T, typename a7T,
709 typename a8T, typename a9T>
711 send_am(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
712 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
713 const a7T& a7, const a8T& a8, const a9T& a9) const
714 {
717 if (dest == me)
718 detail::run_function(result, task_helper::make_task_fn(this, memfn),
719 a1, a2, a3, a4, a5, a6, a7, a8, a9);
720 else {
721 World& world = this->get_world();
722 detail::info<memfnT> info(this->id(), me, memfn, result.remote_ref(world));
723 world.am.send(dest, & objT::template handler<memfnT, a1T, a2T, a3T, a4T, a5T, a6T, a7T, a8T, a9T>,
724 new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9));
725 }
726
727 return result;
728 }
729
730
731 /// \todo Brief description needed.
732
733 /// \todo Descriptions needed.
734 /// \tparam taskT Description needed.
735 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
736 /// \tparam a1T Type of argument 1.
737 /// \tparam a2T Type of argument 2.
738 /// \tparam a3T Type of argument 3.
739 /// \tparam a4T Type of argument 4.
740 /// \tparam a5T Type of argument 5.
741 /// \tparam a6T Type of argument 6.
742 /// \tparam a7T Type of argument 7.
743 /// \tparam a8T Type of argument 8.
744 /// \tparam a9T Type of argument 9.
745 /// \param dest Description needed.
746 /// \param memfn Verify: The member function to be invoked for the task.
747 /// \param a1 Argument 1.
748 /// \param a2 Argument 2.
749 /// \param a3 Argument 3.
750 /// \param a4 Argument 4.
751 /// \param a5 Argument 5.
752 /// \param a6 Argument 6.
753 /// \param a7 Argument 7.
754 /// \param a8 Argument 8.
755 /// \param a9 Argument 9.
756 /// \param attr Description needed.
757 /// \return Description needed.
758 template <typename taskT, typename memfnT, typename a1T, typename a2T, typename a3T,
759 typename a4T, typename a5T, typename a6T, typename a7T,
760 typename a8T, typename a9T>
761 typename taskT::futureT
762 send_task(ProcessID dest, memfnT memfn, const a1T& a1,
763 const a2T& a2, const a3T& a3, const a4T& a4, const a5T& a5,
764 const a6T& a6, const a7T& a7, const a8T& a8, const a9T& a9,
765 const TaskAttributes& attr) const
766 {
767 typename taskT::futureT result;
768 World& world = this->get_world();
769 const ProcessID me = world.rank();
770 detail::info<memfnT> info(this->id(), me, memfn, result.remote_ref(world), attr);
771 world.am.send(dest, & objT::template spawn_remote_task_handler<taskT>,
772 new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9), RMI::ATTR_UNORDERED);
773
774 return result;
775 }
776
777 protected:
778
779 /// To be called from \em derived constructor to process pending messages.
780
781 /// Cannot call this from the \c WorldObject constructor since the
782 /// derived class would not yet be fully constructed.
783 ///
784 /// \attention No incoming messages are processed until this routine is
785 /// invoked; the derived class may rely upon a well defined state
786 /// until this routine is invoked.
788 // Messages may be arriving while we are processing the
789 // pending queue. To maximize concurrency copy messages
790 // out of queue before processing outside critical section.
791 //int ndone = 0;
792 while (!ready) {
793 pendingT tmp;
794
795 MADNESS_PRAGMA_CLANG(diagnostic push)
796 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template")
797
798 pending_mutex.lock(); // BEGIN CRITICAL SECTION
799 pendingT& nv = const_cast<pendingT&>(pending);
800 for (pendingT::iterator it=nv.begin(); it!=nv.end();) {
801 detail::PendingMsg& p = *it;
802 if (p.id == this->id()) {
803 tmp.push_back(p);
804 it = nv.erase(it);
805 }
806 else {
807 ++it;
808 }
809 }
810 if (tmp.size() == 0) ready=true;
811 pending_mutex.unlock(); // END CRITICAL SECTION
812
813 MADNESS_PRAGMA_CLANG(diagnostic pop)
814
815 while (tmp.size()) {
816 tmp.front().invokehandler();
817 tmp.pop_front();
818 //++ndone;
819 }
820 }
821 //if (ndone) std::cout << world.rank() << ":pending:" << ndone << std::endl;
822 }
823
824
825 public:
826 /// \brief Constructor that associates an object (via the derived class)
827 /// with a globally unique ID.
828
829 /// \attention The derived class MUST call \c process_pending from
830 /// its constructor to both
831 /// -# process any messages that arrived prior to construction.
832 /// -# to enable processing of future messages.
833 /// \param[in,out] world The \c World encapsulating the \"global\" domain.
836 , ready(false)
837 , me(world.rank())
838 {
839 // Registration must come last, hence is not part of the member
840 // initialization above: it publishes this object to the AM handlers
841 // running on the runtime threads, which read `ready` to decide
842 // whether an incoming message must be queued (see is_ready()).
843 // Since construction is collective, such a message can already be
844 // in flight while we are still in here.
845 this->register_self(static_cast<Derived*>(this));
846 };
847
848
849 /// \todo Brief description needed.
850
851 /// \todo Descriptions needed.
852 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
853 /// \param dest Description needed.
854 /// \param memfn Verify: The member function to be invoked for the task.
855 /// \return Description needed.
856 template <typename memfnT>
858 send(ProcessID dest, memfnT memfn) const {
859 return send_am(dest, memfn, voidT::value, voidT::value, voidT::value,
862 }
863
864
865 /// \todo Brief description needed.
866
867 /// \todo Descriptions needed.
868 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
869 /// \tparam a1T Type of argument 1.
870 /// \param dest Description needed.
871 /// \param memfn Verify: The member function to be invoked for the task.
872 /// \param a1 Argument 1.
873 /// \return Description needed.
874 template <typename memfnT, typename a1T>
876 send(ProcessID dest, memfnT memfn, const a1T& a1) const {
877 return send_am(dest, memfn, am_arg(a1), voidT::value, voidT::value,
880 }
881
882
883 /// \todo Brief description needed.
884
885 /// \todo Descriptions needed.
886 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
887 /// \tparam a1T Type of argument 1.
888 /// \tparam a2T Type of argument 2.
889 /// \param dest Description needed.
890 /// \param memfn Verify: The member function to be invoked for the task.
891 /// \param a1 Argument 1.
892 /// \param a2 Argument 2.
893 /// \return Description needed.
894 template <typename memfnT, typename a1T, typename a2T>
896 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2) const {
897 return send_am(dest, memfn, am_arg(a1), am_arg(a2), voidT::value,
900 }
901
902
903 /// \todo Brief description needed.
904
905 /// \todo Descriptions needed.
906 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
907 /// \tparam a1T Type of argument 1.
908 /// \tparam a2T Type of argument 2.
909 /// \tparam a3T Type of argument 3.
910 /// \param dest Description needed.
911 /// \param memfn Verify: The member function to be invoked for the task.
912 /// \param a1 Argument 1.
913 /// \param a2 Argument 2.
914 /// \param a3 Argument 3.
915 /// \return Description needed.
916 template <typename memfnT, typename a1T, typename a2T, typename a3T>
918 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
919 const a3T& a3) const
920 {
921 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
924 }
925
926
927 /// \todo Brief description needed.
928
929 /// \todo Descriptions needed.
930 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
931 /// \tparam a1T Type of argument 1.
932 /// \tparam a2T Type of argument 2.
933 /// \tparam a3T Type of argument 3.
934 /// \tparam a4T Type of argument 4.
935 /// \param dest Description needed.
936 /// \param memfn Verify: The member function to be invoked for the task.
937 /// \param a1 Argument 1.
938 /// \param a2 Argument 2.
939 /// \param a3 Argument 3.
940 /// \param a4 Argument 4.
941 /// \return Description needed.
942 template <typename memfnT, typename a1T, typename a2T, typename a3T,
943 typename a4T>
945 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
946 const a3T& a3, const a4T& a4) const
947 {
948 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
951 }
952
953
954 /// \todo Brief description needed.
955
956 /// \todo Descriptions needed.
957 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
958 /// \tparam a1T Type of argument 1.
959 /// \tparam a2T Type of argument 2.
960 /// \tparam a3T Type of argument 3.
961 /// \tparam a4T Type of argument 4.
962 /// \tparam a5T Type of argument 5.
963 /// \param dest Description needed.
964 /// \param memfn Verify: The member function to be invoked for the task.
965 /// \param a1 Argument 1.
966 /// \param a2 Argument 2.
967 /// \param a3 Argument 3.
968 /// \param a4 Argument 4.
969 /// \param a5 Argument 5.
970 /// \return Description needed.
971 template <typename memfnT, typename a1T, typename a2T, typename a3T,
972 typename a4T, typename a5T>
974 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
975 const a3T& a3, const a4T& a4, const a5T& a5) const
976 {
977 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
980 }
981
982
983 /// \todo Brief description needed.
984
985 /// \todo Descriptions needed.
986 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
987 /// \tparam a1T Type of argument 1.
988 /// \tparam a2T Type of argument 2.
989 /// \tparam a3T Type of argument 3.
990 /// \tparam a4T Type of argument 4.
991 /// \tparam a5T Type of argument 5.
992 /// \tparam a6T Type of argument 6.
993 /// \param dest Description needed.
994 /// \param memfn Verify: The member function to be invoked for the task.
995 /// \param a1 Argument 1.
996 /// \param a2 Argument 2.
997 /// \param a3 Argument 3.
998 /// \param a4 Argument 4.
999 /// \param a5 Argument 5.
1000 /// \param a6 Argument 6.
1001 /// \return Description needed.
1002 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1003 typename a4T, typename a5T, typename a6T>
1005 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1006 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6) const
1007 {
1008 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
1010 voidT::value);
1011 }
1012
1013
1014 /// \todo Brief description needed.
1015
1016 /// \todo Descriptions needed.
1017 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1018 /// \tparam a1T Type of argument 1.
1019 /// \tparam a2T Type of argument 2.
1020 /// \tparam a3T Type of argument 3.
1021 /// \tparam a4T Type of argument 4.
1022 /// \tparam a5T Type of argument 5.
1023 /// \tparam a6T Type of argument 6.
1024 /// \tparam a7T Type of argument 7.
1025 /// \param dest Description needed.
1026 /// \param memfn Verify: The member function to be invoked for the task.
1027 /// \param a1 Argument 1.
1028 /// \param a2 Argument 2.
1029 /// \param a3 Argument 3.
1030 /// \param a4 Argument 4.
1031 /// \param a5 Argument 5.
1032 /// \param a6 Argument 6.
1033 /// \param a7 Argument 7.
1034 /// \return Description needed.
1035 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1036 typename a4T, typename a5T, typename a6T, typename a7T>
1038 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1039 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1040 const a7T& a7) const
1041 {
1042 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
1043 am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), voidT::value,
1044 voidT::value);
1045 }
1046
1047
1048 /// \todo Brief description needed.
1049
1050 /// \todo Descriptions needed.
1051 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1052 /// \tparam a1T Type of argument 1.
1053 /// \tparam a2T Type of argument 2.
1054 /// \tparam a3T Type of argument 3.
1055 /// \tparam a4T Type of argument 4.
1056 /// \tparam a5T Type of argument 5.
1057 /// \tparam a6T Type of argument 6.
1058 /// \tparam a7T Type of argument 7.
1059 /// \tparam a8T Type of argument 8.
1060 /// \param dest Description needed.
1061 /// \param memfn Verify: The member function to be invoked for the task.
1062 /// \param a1 Argument 1.
1063 /// \param a2 Argument 2.
1064 /// \param a3 Argument 3.
1065 /// \param a4 Argument 4.
1066 /// \param a5 Argument 5.
1067 /// \param a6 Argument 6.
1068 /// \param a7 Argument 7.
1069 /// \param a8 Argument 8.
1070 /// \return Description needed.
1071 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1072 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T>
1074 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1075 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1076 const a7T& a7, const a8T& a8) const
1077 {
1078 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
1079 am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8),
1080 voidT::value);
1081 }
1082
1083
1084 /// \todo Brief description needed.
1085
1086 /// \todo Descriptions needed.
1087 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1088 /// \tparam a1T Type of argument 1.
1089 /// \tparam a2T Type of argument 2.
1090 /// \tparam a3T Type of argument 3.
1091 /// \tparam a4T Type of argument 4.
1092 /// \tparam a5T Type of argument 5.
1093 /// \tparam a6T Type of argument 6.
1094 /// \tparam a7T Type of argument 7.
1095 /// \tparam a8T Type of argument 8.
1096 /// \tparam a9T Type of argument 9.
1097 /// \param dest Description needed.
1098 /// \param memfn Verify: The member function to be invoked for the task.
1099 /// \param a1 Argument 1.
1100 /// \param a2 Argument 2.
1101 /// \param a3 Argument 3.
1102 /// \param a4 Argument 4.
1103 /// \param a5 Argument 5.
1104 /// \param a6 Argument 6.
1105 /// \param a7 Argument 7.
1106 /// \param a8 Argument 8.
1107 /// \param a9 Argument 9.
1108 /// \return Description needed.
1109 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1110 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T,
1111 typename a9T>
1113 send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1114 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1115 const a7T& a7, const a8T& a8, const a9T& a9) const
1116 {
1117 return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
1118 am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8),
1119 am_arg(a9));
1120 }
1121
1122 /// Sends task to derived class method `returnT (this->*memfn)()`.
1123
1124 /// \todo Descriptions needed.
1125 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1126 /// \param dest Description needed.
1127 /// \param memfn Verify: The member function to be invoked for the task.
1128 /// \param attr Description needed.
1129 /// \return Description needed.
1130 template <typename memfnT>
1132 task(ProcessID dest, memfnT memfn, const TaskAttributes& attr = TaskAttributes()) const {
1135 if (dest == me)
1136 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn), attr);
1137 else
1138 return send_task<taskT>(dest, memfn, voidT::value, voidT::value,
1141 }
1142
1143 /// Sends task to derived class method `returnT (this->*memfn)(a1)`.
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 /// \param dest Description needed.
1149 /// \param memfn Verify: The member function to be invoked for the task.
1150 /// \param a1 Argument 1.
1151 /// \param attr Description needed.
1152 /// \return Description needed.
1153 template <typename memfnT, typename a1T>
1155 task(ProcessID dest, memfnT memfn, const a1T& a1,
1156 const TaskAttributes& attr = TaskAttributes()) const
1157 {
1159 typedef TaskFn<typename task_helper::wrapperT,
1160 typename detail::task_arg<a1T>::type> taskT;
1161 if (dest == me)
1162 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1163 a1, attr);
1164 else
1165 return send_task<taskT>(dest, memfn, am_arg(a1), voidT::value,
1168 }
1169
1170 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2)`.
1171
1172 /// \todo Descriptions needed.
1173 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1174 /// \tparam a1T Type of argument 1.
1175 /// \tparam a2T Type of argument 2.
1176 /// \param dest Description needed.
1177 /// \param memfn Verify: The member function to be invoked for the task.
1178 /// \param a1 Argument 1.
1179 /// \param a2 Argument 2.
1180 /// \param attr Description needed.
1181 /// \return Description needed.
1182 template <typename memfnT, typename a1T, typename a2T>
1184 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1185 const TaskAttributes& attr = TaskAttributes()) const
1186 {
1188 typedef TaskFn<typename task_helper::wrapperT,
1190 typename detail::task_arg<a2T>::type> taskT;
1191 if (dest == me)
1192 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1193 a1, a2, attr);
1194 else
1195 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1198 }
1199
1200 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3)`.
1201
1202 /// \todo Descriptions needed.
1203 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1204 /// \tparam a1T Type of argument 1.
1205 /// \tparam a2T Type of argument 2.
1206 /// \tparam a3T Type of argument 3.
1207 /// \param dest Description needed.
1208 /// \param memfn Verify: The member function to be invoked for the task.
1209 /// \param a1 Argument 1.
1210 /// \param a2 Argument 2.
1211 /// \param a3 Argument 3.
1212 /// \param attr Description needed.
1213 /// \return Description needed.
1214 template <typename memfnT, typename a1T, typename a2T, typename a3T>
1216 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1217 const a3T& a3, const TaskAttributes& attr = TaskAttributes()) const
1218 {
1220 typedef TaskFn<typename task_helper::wrapperT,
1223 typename detail::task_arg<a3T>::type> taskT;
1224 if (dest == me)
1225 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1226 a1, a2, a3, attr);
1227 else
1228 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1231 }
1232
1233 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4)`.
1234
1235 /// \todo Descriptions needed.
1236 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1237 /// \tparam a1T Type of argument 1.
1238 /// \tparam a2T Type of argument 2.
1239 /// \tparam a3T Type of argument 3.
1240 /// \tparam a4T Type of argument 4.
1241 /// \param dest Description needed.
1242 /// \param memfn Verify: The member function to be invoked for the task.
1243 /// \param a1 Argument 1.
1244 /// \param a2 Argument 2.
1245 /// \param a3 Argument 3.
1246 /// \param a4 Argument 4.
1247 /// \param attr Description needed.
1248 /// \return Description needed.
1249 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1250 typename a4T>
1252 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1253 const a3T& a3, const a4T& a4, const TaskAttributes& attr = TaskAttributes()) const
1254 {
1256 typedef TaskFn<typename task_helper::wrapperT,
1260 typename detail::task_arg<a4T>::type> taskT;
1261 if (dest == me)
1262 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1263 a1, a2, a3, a4, attr);
1264 else
1265 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1268 }
1269
1270 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5)`.
1271
1272 /// \todo Descriptions needed.
1273 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1274 /// \tparam a1T Type of argument 1.
1275 /// \tparam a2T Type of argument 2.
1276 /// \tparam a3T Type of argument 3.
1277 /// \tparam a4T Type of argument 4.
1278 /// \tparam a5T Type of argument 5.
1279 /// \param dest Description needed.
1280 /// \param memfn Verify: The member function to be invoked for the task.
1281 /// \param a1 Argument 1.
1282 /// \param a2 Argument 2.
1283 /// \param a3 Argument 3.
1284 /// \param a4 Argument 4.
1285 /// \param a5 Argument 5.
1286 /// \param attr Description needed.
1287 /// \return Description needed.
1288 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1289 typename a4T, typename a5T>
1291 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1292 const a3T& a3, const a4T& a4, const a5T& a5,
1293 const TaskAttributes& attr = TaskAttributes()) const
1294 {
1296 typedef TaskFn<typename task_helper::wrapperT,
1301 typename detail::task_arg<a5T>::type> taskT;
1302 if (dest == me)
1303 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1304 a1, a2, a3, a4, a5, attr);
1305 else
1306 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1307 am_arg(a3), am_arg(a4), am_arg(a5), voidT::value,
1309 }
1310
1311 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6)`.
1312
1313 /// \todo Descriptions needed.
1314 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1315 /// \tparam a1T Type of argument 1.
1316 /// \tparam a2T Type of argument 2.
1317 /// \tparam a3T Type of argument 3.
1318 /// \tparam a4T Type of argument 4.
1319 /// \tparam a5T Type of argument 5.
1320 /// \tparam a6T Type of argument 6.
1321 /// \param dest Description needed.
1322 /// \param memfn Verify: The member function to be invoked for the task.
1323 /// \param a1 Argument 1.
1324 /// \param a2 Argument 2.
1325 /// \param a3 Argument 3.
1326 /// \param a4 Argument 4.
1327 /// \param a5 Argument 5.
1328 /// \param a6 Argument 6.
1329 /// \param attr Description needed.
1330 /// \return Description needed.
1331 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1332 typename a4T, typename a5T, typename a6T>
1334 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1335 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1336 const TaskAttributes& attr = TaskAttributes()) const
1337 {
1339 typedef TaskFn<typename task_helper::wrapperT,
1345 typename detail::task_arg<a6T>::type> taskT;
1346 if (dest == me)
1347 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1348 a1, a2, a3, a4, a5, a6, attr);
1349 else {
1350 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1351 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1353 }
1354 }
1355
1356 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7)`.
1357
1358 /// \todo Descriptions needed.
1359 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1360 /// \tparam a1T Type of argument 1.
1361 /// \tparam a2T Type of argument 2.
1362 /// \tparam a3T Type of argument 3.
1363 /// \tparam a4T Type of argument 4.
1364 /// \tparam a5T Type of argument 5.
1365 /// \tparam a6T Type of argument 6.
1366 /// \tparam a7T Type of argument 7.
1367 /// \param dest Description needed.
1368 /// \param memfn Verify: The member function to be invoked for the task.
1369 /// \param a1 Argument 1.
1370 /// \param a2 Argument 2.
1371 /// \param a3 Argument 3.
1372 /// \param a4 Argument 4.
1373 /// \param a5 Argument 5.
1374 /// \param a6 Argument 6.
1375 /// \param a7 Argument 7.
1376 /// \param attr Description needed.
1377 /// \return Description needed.
1378 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1379 typename a4T, typename a5T, typename a6T, typename a7T>
1381 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1382 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1383 const a7T& a7, const TaskAttributes& attr = TaskAttributes()) const
1384 {
1386 typedef TaskFn<typename task_helper::wrapperT,
1393 typename detail::task_arg<a7T>::type> taskT;
1394 if (dest == me)
1395 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1396 a1, a2, a3, a4, a5, a6, a7, attr);
1397 else
1398 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1399 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1400 am_arg(a7), voidT::value, voidT::value, attr);
1401 }
1402
1403 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8)`.
1404
1405 /// \todo Descriptions needed.
1406 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1407 /// \tparam a1T Type of argument 1.
1408 /// \tparam a2T Type of argument 2.
1409 /// \tparam a3T Type of argument 3.
1410 /// \tparam a4T Type of argument 4.
1411 /// \tparam a5T Type of argument 5.
1412 /// \tparam a6T Type of argument 6.
1413 /// \tparam a7T Type of argument 7.
1414 /// \tparam a8T Type of argument 8.
1415 /// \param dest Description needed.
1416 /// \param memfn Verify: The member function to be invoked for the task.
1417 /// \param a1 Argument 1.
1418 /// \param a2 Argument 2.
1419 /// \param a3 Argument 3.
1420 /// \param a4 Argument 4.
1421 /// \param a5 Argument 5.
1422 /// \param a6 Argument 6.
1423 /// \param a7 Argument 7.
1424 /// \param a8 Argument 8.
1425 /// \param attr Description needed.
1426 /// \return Description needed.
1427 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1428 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T>
1430 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1431 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1432 const a7T& a7, const a8T& a8,
1433 const TaskAttributes& attr = TaskAttributes()) const
1434 {
1436 typedef TaskFn<typename task_helper::wrapperT,
1444 typename detail::task_arg<a8T>::type> taskT;
1445 if (dest == me)
1446 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1447 a1, a2, a3, a4, a5, a6, a7, a8, attr);
1448 else {
1449 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1450 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1451 am_arg(a7), am_arg(a8), voidT::value, attr);
1452 }
1453 }
1454
1455 /// Sends task to derived class method `returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8,a9)`.
1456
1457 /// \todo Descriptions needed.
1458 /// \tparam memfnT Verify: Signature of the member function in the derived class to be invoked for the task.
1459 /// \tparam a1T Type of argument 1.
1460 /// \tparam a2T Type of argument 2.
1461 /// \tparam a3T Type of argument 3.
1462 /// \tparam a4T Type of argument 4.
1463 /// \tparam a5T Type of argument 5.
1464 /// \tparam a6T Type of argument 6.
1465 /// \tparam a7T Type of argument 7.
1466 /// \tparam a8T Type of argument 8.
1467 /// \tparam a9T Type of argument 9.
1468 /// \param dest Description needed.
1469 /// \param memfn Verify: The member function to be invoked for the task.
1470 /// \param a1 Argument 1.
1471 /// \param a2 Argument 2.
1472 /// \param a3 Argument 3.
1473 /// \param a4 Argument 4.
1474 /// \param a5 Argument 5.
1475 /// \param a6 Argument 6.
1476 /// \param a7 Argument 7.
1477 /// \param a8 Argument 8.
1478 /// \param a9 Argument 9.
1479 /// \param attr Description needed.
1480 /// \return Description needed.
1481 ///
1482 /// \todo Could we use variadic templates to eliminate a lot of this code duplication?
1483 template <typename memfnT, typename a1T, typename a2T, typename a3T,
1484 typename a4T, typename a5T, typename a6T, typename a7T, typename a8T,
1485 typename a9T>
1487 task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
1488 const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
1489 const a7T& a7, const a8T& a8, const a9T& a9,
1490 const TaskAttributes& attr = TaskAttributes()) const
1491 {
1493 typedef TaskFn<typename task_helper::wrapperT,
1502 typename detail::task_arg<a9T>::type> taskT;
1503 if (dest == me)
1504 return this->get_world().taskq.add(task_helper::make_task_fn(this, memfn),
1505 a1, a2, a3, a4, a5, a6, a7, a8, a9, attr);
1506 else
1507 return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
1508 am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
1509 am_arg(a7), am_arg(a8), am_arg(a9), attr);
1510 }
1511
1512 virtual ~WorldObject() {
1513 // this body is pure diagnostics, and every assertion in it is
1514 // compiled out in release builds; world_is_alive() is not, so it is
1515 // what keeps the dereference below off a dangling reference. The
1516 // dead-world diagnostic itself is left to ~WorldObjectBase.
1517 if(initialized() && id() && this->world_is_alive()) {
1518 // noexcept variant: a throwing assertion in a destructor would
1519 // call std::terminate and discard the diagnostic
1520 World& world = this->get_world_noexcept();
1521 MADNESS_ASSERT_NOEXCEPT(world.ptr_from_id<Derived>(id()));
1522 MADNESS_ASSERT_NOEXCEPT(*world.ptr_from_id<Derived>(id()) == this);
1523 }
1524 }
1525
1526#ifdef MADNESS_WORLDOBJECT_FUTURE_TRACE
1527 /// "traces" future evaluation by counting their assignments in a static table
1528
1529 /// Counts future assignments in a a statically-sized table to make this as lightweight/lock-free as possible
1530 /// with minimal effort. Can only trace objects of a single World.
1531 /// \param[in,out] f the future to be traced; if ready, will be unchanged (but contribute to the trace
1532 /// statistics of this object), or have a callback registered that will update the tracing statistics on
1533 /// assignment
1534 /// \warning this function will trace futures for WorldObjects associated with default world (id=0) only;
1535 /// use CMake variable `MADNESS_WORLDOBJECT_FUTURE_TRACE_WORLD_ID` to adjust the target World ID.
1536 /// \warning this function will trace futures for WorldObjects with IDs < 1000000 only;
1537 /// use CMake variable `MADNESS_WORLDOBJECT_FUTURE_TRACE_MAX_NOBJECTS` to adjust the limit.
1538 template <typename T>
1539 std::enable_if_t<!std::is_same_v<T,void>,void> trace(Future<T>& f) const;
1540
1541 /// \param[in] id a WorldObject ID
1542 /// \return true if futures associated with \p id are traced
1543 static bool trace_futures(const uniqueidT &id);
1544
1545 /// \return true if futures associated with this object are traced
1546 bool trace_futures() const {
1547 return trace_futures(this->id());
1548 }
1549
1550 /// \param[in] id report tracing stats for this WorldObject
1551 /// \return number of futures given to trace() of the WorldObject with ID \p id
1552 static std::size_t trace_status_nfuture_registered(const uniqueidT& id);
1553
1554 /// \return number of futures given to trace() of this object
1555 std::size_t trace_status_nfuture_registered() const {
1556 return trace_status_nfuture_registered(this->id());
1557 }
1558
1559 /// \param[in] id report tracing stats for this WorldObject
1560 /// \return number of assigned futures given to trace() of the WorldObject with ID \p id
1561 static std::size_t trace_status_nfuture_assigned(const uniqueidT& id);
1562
1563 /// \return number of assigned futures registered via `this->trace()`
1564 std::size_t trace_status_nfuture_assigned() const {
1565 return trace_status_nfuture_assigned(this->id());
1566 }
1567#endif
1568 };
1569
1570#ifdef MADNESS_WORLDOBJECT_FUTURE_TRACE
1571 namespace detail {
1572 template <typename Derived> struct WorldObjectFutureTracer {
1573 // this value is the world ID to trace
1574 constexpr static std::size_t world_id =
1575#ifndef MADNESS_WORLDOBJECT_FUTURE_TRACE_WORLD_ID
1576 0
1577#else
1578 MADNESS_WORLDOBJECT_FUTURE_TRACE_WORLD_ID
1579#endif
1580 ;
1581 // this value is 1 greater than is the highest ID of WorldObjects to trace
1582 constexpr static std::size_t max_object_id =
1583#ifndef MADNESS_WORLDOBJECT_FUTURE_TRACE_MAX_NOBJECTS
1584 1000000
1585#else
1586 MADNESS_WORLDOBJECT_FUTURE_TRACE_MAX_NOBJECTS
1587#endif
1588 ;
1589
1590 static constexpr bool do_trace(const uniqueidT& id) {
1591 return id.get_world_id() == world_id &&
1592 id.get_obj_id() < max_object_id;
1593 }
1594
1595 static std::array<std::atomic<std::size_t>, max_object_id>
1596 nfuture_registered;
1597 static std::array<std::atomic<std::size_t>, max_object_id>
1598 nfuture_assigned;
1599
1600 struct Initializer {
1601 Initializer() {
1602 for (auto &&v : nfuture_registered) {
1603 v.store(0);
1604 }
1605 for (auto &&v : nfuture_assigned) {
1606 v.store(0);
1607 }
1608 }
1609 };
1610 static Initializer initializer;
1611
1612 struct FutureTracer : public CallbackInterface {
1613 FutureTracer(const uniqueidT &id) : id_(id) {
1614 if (do_trace(id_)) {
1615 nfuture_registered[id_.get_obj_id()]++;
1616 }
1617 }
1618
1619 // Not allowed
1620 FutureTracer(const FutureTracer &) = delete;
1621 FutureTracer &operator=(const FutureTracer &) = delete;
1622
1623 virtual ~FutureTracer() {}
1624
1625 /// Notify this object that the future has been set.
1626
1627 /// This will set the value of the future on the remote node and delete
1628 /// this callback object.
1629 void notify() override {
1630 if (do_trace(id_)) {
1631 nfuture_assigned[id_.get_obj_id()]++;
1632 }
1633 delete this;
1634 }
1635
1636 private:
1637 uniqueidT id_;
1638 }; // struct FutureTracer
1639
1640 }; // struct WorldObjectFutureTracer
1641 template <typename Derived>
1642 typename WorldObjectFutureTracer<Derived>::Initializer
1643 WorldObjectFutureTracer<Derived>::initializer;
1644 template <typename Derived>
1645 std::array<std::atomic<std::size_t>, WorldObjectFutureTracer<Derived>::max_object_id>
1646 WorldObjectFutureTracer<Derived>::nfuture_registered;
1647 template <typename Derived>
1648 std::array<std::atomic<std::size_t>, WorldObjectFutureTracer<Derived>::max_object_id>
1649 WorldObjectFutureTracer<Derived>::nfuture_assigned;
1650 } // namespace detail
1651
1652 template <typename Derived>
1653 template <typename T>
1654 std::enable_if_t<!std::is_same_v<T,void>,void> WorldObject<Derived>::trace(Future<T>& f) const {
1655 f.register_callback(
1656 new typename detail::WorldObjectFutureTracer<Derived>::FutureTracer(
1657 this->id()));
1658 }
1659
1660 template <typename Derived>
1661 bool WorldObject<Derived>::trace_futures(const uniqueidT& id) {
1662 return detail::WorldObjectFutureTracer<Derived>::do_trace(id);
1663 }
1664
1665 template <typename Derived>
1666 std::size_t WorldObject<Derived>::trace_status_nfuture_registered(const uniqueidT& id) {
1667 if (detail::WorldObjectFutureTracer<
1668 Derived>::do_trace(id)) {
1669 return detail::WorldObjectFutureTracer<
1670 Derived>::nfuture_registered[id.get_obj_id()];
1671 }
1672 else return 0;
1673 }
1674
1675 template <typename Derived>
1676 std::size_t WorldObject<Derived>::trace_status_nfuture_assigned(const uniqueidT& id) {
1677 if (detail::WorldObjectFutureTracer<
1678 Derived>::do_trace(id)) {
1679 return detail::WorldObjectFutureTracer<
1680 Derived>::nfuture_assigned[id.get_obj_id()];
1681 }
1682 else return 0;
1683 }
1684
1685#endif // MADNESS_WORLDOBJECT_FUTURE_TRACE
1686
1687 namespace archive {
1688
1689 /// Specialization of \c ArchiveLoadImpl for globally-addressable objects.
1690
1691 /// \tparam Derived The derived class of \c WorldObject in a curiously
1692 /// repeating template pattern.
1693 template <class Derived>
1695
1696 /// Read a globally-addressable object from a \c BufferInputArchive.
1697
1698 /// \param[in,out] ar The archive.
1699 /// \param[out] ptr The read object.
1700 static inline void load(const BufferInputArchive& ar, WorldObject<Derived>*& ptr) {
1701 uniqueidT id;
1702 ar & id;
1703 World* world = World::world_from_id(id.get_world_id());
1704 MADNESS_ASSERT(world);
1705 auto ptr_opt = world->ptr_from_id< WorldObject<Derived> >(id);
1706 if (!ptr_opt) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0);
1707 ptr = *ptr_opt;
1708 if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally deregistered object",0);
1709 }
1710 };
1711
1712 /// Specialization of \c ArchiveStoreImpl for globally-addressable objects.
1713
1714 /// \tparam Derived The derived class of \c WorldObject in a curiously
1715 /// repeating template pattern.
1716 template <class Derived>
1718
1719 /// Write a globally-addressable object to a \c BufferOutputArchive.
1720
1721 /// \param[in,out] ar The archive.
1722 /// \param[in] ptr The object to store.
1723 static inline void store(const BufferOutputArchive& ar, WorldObject<Derived>* const& ptr) {
1724 ar & ptr->id();
1725 }
1726 };
1727
1728 /// Specialization of \c ArchiveLoadImpl for constant, globally-addressable objects.
1729
1730 /// \tparam Derived The derived class of \c WorldObject in a curiously
1731 /// repeating template pattern.
1732 template <class Derived>
1734
1735 /// Read a globally-addressable object from a \c BufferInputArchive.
1736
1737 /// \param[in,out] ar The archive.
1738 /// \param[out] ptr The read object.
1739 static inline void load(const BufferInputArchive& ar, const WorldObject<Derived>*& ptr) {
1740 uniqueidT id;
1741 ar & id;
1742 World* world = World::world_from_id(id.get_world_id());
1743 MADNESS_ASSERT(world);
1744 auto ptr_opt = world->ptr_from_id< WorldObject<Derived> >(id);
1745 if (!ptr_opt) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0);
1746 ptr = *ptr_opt;
1747 if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally deregistered object",0);
1748 }
1749 };
1750
1751 /// Specialization of \c ArchiveStoreImpl for constant, globally-addressable objects.
1752
1753 /// \tparam Derived The derived class of \c WorldObject in a curiously
1754 /// repeating template pattern.
1755 template <class Derived>
1757
1758 /// Write a globally-addressable object to a \c BufferOutputArchive.
1759
1760 /// \param[in,out] ar The archive.
1761 /// \param[in] ptr The object to store.
1762 static inline void store(const BufferOutputArchive& ar, const WorldObject<Derived>* const& ptr) {
1763 ar & ptr->id();
1764 }
1765 };
1766 } // namespace archive
1767} // namespace madness
1768
1769#endif // MADNESS_WORLD_WORLD_OBJECT_H__INCLUDED
1770
1771/// @}
double w(double t, double eps)
Definition DKops.h:22
World active message that extends an RMI message.
Definition worldam.h:80
Implements the functionality of futures.
Definition future.h:75
Specialization of Future<void> for internal convenience. This does nothing useful!
Definition future.h:733
static const Future< void > value
Definition future.h:739
A future is a possibly yet unevaluated value.
Definition future.h:370
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:329
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:491
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:1334
WorldObject(World &world)
Constructor that associates an object (via the derived class) with a globally unique ID.
Definition world_object.h:834
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:1074
static const T & am_arg(const T &t)
Definition world_object.h:677
static bool is_ready(const uniqueidT &id, objT *&obj, const AmArg &arg, am_handlerT ptr)
Definition world_object.h:539
static Spinlock pending_mutex
Definition world_object.h:517
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1) const
Definition world_object.h:876
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:1113
WorldObject< Derived > objT
Definition world_object.h:494
WorldObject(const WorldObject &other)
Definition world_object.h:500
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:1291
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:1184
std::list< detail::PendingMsg > pendingT
Definition world_object.h:507
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:1252
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2) const
Definition world_object.h:896
void process_pending()
To be called from derived constructor to process pending messages.
Definition world_object.h:787
WorldObject & operator=(const WorldObject &)=delete
static void spawn_remote_task_handler(const AmArg &arg)
Handler for remote arguments.
Definition world_object.h:633
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:918
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:1038
ProcessID me
Rank of self.
Definition world_object.h:514
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:1430
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:1381
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn) const
Definition world_object.h:858
volatile bool ready
True if ready to rock 'n roll.
Definition world_object.h:513
virtual ~WorldObject()
Definition world_object.h:1512
detail::voidT voidT
Definition world_object.h:510
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:762
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:1155
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:1216
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:945
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:711
static const T & am_arg(const Future< T > &f)
Definition world_object.h:664
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:1005
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:974
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:1487
static volatile pendingT pending
Buffer for pending messages.
Definition world_object.h:518
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:1132
static void handler(const AmArg &arg)
Handler for an incoming AM.
Definition world_object.h:599
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:134
static World * world_from_id(std::uint64_t id)
Convert a World ID to a World pointer.
Definition world.h:516
WorldTaskQueue & taskq
Task queue.
Definition world.h:215
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:344
std::shared_ptr< const std::atomic< bool > > liveness_handleT
The type of the handle returned by liveness().
Definition world.h:327
void unregister_ptr(const uniqueidT id)
Unregister a global object via its the unique ID.
Definition world.h:413
uniqueidT register_ptr(T *ptr)
Associate a local pointer with a universe-wide unique ID.
Definition world.h:400
std::optional< T * > ptr_from_id(uniqueidT id) const
Look up a local pointer from a world-wide unique ID.
Definition world.h:440
WorldAmInterface & am
AM interface.
Definition world.h:214
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
unsigned long get_world_id() const
Access the World ID.
Definition uniqueid.h:90
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
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:926
auto to_rel_memfn_ptr(const T &fn)
converts nonstatic member function pointer to the relative equivalent
Definition archive.h:260
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:2643
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
Definition potentialmanager.cc:41
static const uniqueidT & peek(const AmArg &arg)
Extract the unique object ID from an incoming active message header.
Definition world_object.h:200
std::enable_if< std::is_void< typenamedetail::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
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
AmArg * copy_am_arg(const AmArg &arg)
Definition worldam.h:170
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:75
static double pop(std::vector< double > &v)
Definition SCF.cc:116
void free_am_arg(AmArg *arg)
Frees an AmArg allocated with alloc_am_arg.
Definition worldam.h:177
NDIM & f
Definition mra.h:2622
void(* am_handlerT)(const AmArg &)
Type of AM handler functions.
Definition worldam.h:77
std::string type(const PairType &n)
Definition PNOParameters.h:18
Definition mraimpl.h:51
Wrap a callable object and its arguments into a task function.
Definition taskfn.h:473
Base class for WorldObject.
Definition world_object.h:345
World & world
Memoized reference to the world to which this object belongs.
Definition world_object.h:348
World & get_world() const
Definition world_object.h:446
World & get_world_unchecked() const noexcept
Unchecked access to the memoized world reference.
Definition world_object.h:397
virtual ~WorldObjectBase()
Definition world_object.h:403
const uniqueidT & id() const
Returns the globally unique object ID.
Definition world_object.h:424
World & get_world_noexcept() const noexcept
Get the world to which this object belongs, without risking a throw.
Definition world_object.h:459
WorldObjectBase(World &w)
Construct a new WorldObjectBase.
Definition world_object.h:360
WorldObjectBase(const WorldObjectBase &other)
Copy constructor; produces an unregistered object.
Definition world_object.h:373
void register_self(DerivedT *this_ptr)
Registers this object with its world, making it globally addressable.
Definition world_object.h:386
uniqueidT objid
Unique object ID; null until register_self() has been called.
Definition world_object.h:347
World::liveness_handleT world_liveness
Reports whether world is still alive.
Definition world_object.h:349
bool world_is_alive() const noexcept
Reports whether the world to which this object belongs still exists.
Definition world_object.h:433
static void load(const BufferInputArchive &ar, WorldObject< Derived > *&ptr)
Read a globally-addressable object from a BufferInputArchive.
Definition world_object.h:1700
static void load(const BufferInputArchive &ar, const WorldObject< Derived > *&ptr)
Read a globally-addressable object from a BufferInputArchive.
Definition world_object.h:1739
Default load of an object via serialize(ar, t).
Definition archive.h:667
static void store(const BufferOutputArchive &ar, WorldObject< Derived > *const &ptr)
Write a globally-addressable object to a BufferOutputArchive.
Definition world_object.h:1723
static void store(const BufferOutputArchive &ar, const WorldObject< Derived > *const &ptr)
Write a globally-addressable object to a BufferOutputArchive.
Definition world_object.h:1762
Default store of an object via serialize(ar, t).
Definition archive.h:612
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, std::shared_ptr< constobjT >, std::shared_ptr< objT > >::type shared_ptrT
Definition world_object.h:285
std::conditional< memfunc_traits< memfnT >::constness, constobjT *, objT * >::type ptrT
Definition world_object.h:281
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, constobjT *, 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
Future< resultT > futureT
Definition taskfn.h:244
Implements Dqueue, Thread, ThreadBase and ThreadPool.
#define REMFUTURE(T)
Macro to determine type of future (by removing wrapping Future template).
Definition type_traits.h:163
#define MEMFUN_RETURNT(MEMFUN)
Macro to make member function type traits easier to use.
Definition type_traits.h:773
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