MADNESS 0.10.1
future.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 future.h
34 \brief Implements \c Future and related items.
35 \ingroup futures
36*/
37
38#ifndef MADNESS_WORLD_FUTURE_H__INCLUDED
39#define MADNESS_WORLD_FUTURE_H__INCLUDED
40
41#include <atomic>
42#include <vector>
43#include <stack>
44#include <new>
47#include <madness/world/stack.h>
49#include <madness/world/world.h>
50
51/// \addtogroup futures
52/// @{
53namespace madness {
54
55 //extern SharedCounter future_count; // For tracking memory leak
56
57 // forward decl
58 template <typename T> class Future;
59
60 /// Human readable printing of a \c Future to a stream.
61
62 /// \tparam T The type of future.
63 /// \param[in,out] out The output stream.
64 /// \param[in] f The future.
65 /// \return The output stream.
66 template <typename T>
67 std::ostream& operator<<(std::ostream& out, const Future<T>& f);
68
69
70 /// Implements the functionality of futures.
71
72 /// \tparam T The type of future.
73 template <typename T>
74 class FutureImpl : private Spinlock {
75 friend class Future<T>;
76 friend std::ostream& operator<< <T>(std::ostream& out, const Future<T>& f);
77
78 private:
79 /// The static stack size used for callbacks and future assignment used
80 /// for small stack size optimizations.
81 static const int MAXCALLBACKS = 4;
82
85
86 /// A stack that stores callbacks that are invoked once the future has
87 /// been assigned.
89
90 /// A stack that stores future objects that are set to the same value
91 /// as this future, once it has been set.
92 volatile mutable assignmentT assignments;
93
94 /// A flag indicating if the future has been set.
95 std::atomic<bool> assigned; // Use of atomic for necessary memory barriers/fences
96
97 /// Reference to a remote future pimpl.
99
100 volatile T t; ///< The future data.
101
102 /// AM handler for remote set operations.
103
104 /// \todo Description needed.
105 /// \param[in] arg Description needed.
106 static void set_handler(const AmArg& arg) {
108 archive::BufferInputArchive input_arch = arg & ref;
109 // The remote reference holds a copy of the shared_ptr, so no need
110 // to take another.
111 {
112 FutureImpl<T>* pimpl = ref.get();
113
115 if(pimpl->remote_ref) {
116 // Unarchive the value to a temporary since it is going to
117 // be forwarded to another node.
118 MADNESS_PRAGMA_CLANG(diagnostic push)
119 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wuninitialized-const-reference")
120 T value;
121 input_arch & value;
122 MADNESS_PRAGMA_CLANG(diagnostic pop)
123
124
125 // Copy world and owner from remote_ref since sending remote_ref
126 // will invalidate it.
127 World& world = pimpl->remote_ref.get_world();
128 const ProcessID owner = pimpl->remote_ref.owner();
130 new_am_arg(pimpl->remote_ref, value));
131
132 pimpl->set_assigned(value);
133 } else {
134 // Unarchive the value of the future
135 input_arch & const_cast<T&>(pimpl->t);
136
137 pimpl->set_assigned(const_cast<const T&>(pimpl->t));
138 }
139 }
140 ref.reset();
141 }
142
143
144 /// \todo Brief description needed.
145
146 /// Invoked locally by set routine after assignment.
147 /// \todo Description needed.
148 /// \param[in] value Description needed.
149 inline void set_assigned(const T& value) {
150 // Assume that whoever is invoking this routine is holding
151 // a copy of our shared pointer on its *stack* so that
152 // if this future is destroyed as a result of a callback
153 // the destructor of this object is not invoked until
154 // we return.
155 //
156 // Also assume that the caller either has the lock
157 // or is sure that we are single threaded.
159 assigned = true;
160
161 assignmentT& as = const_cast<assignmentT&>(assignments);
162 callbackT& cb = const_cast<callbackT&>(callbacks);
163
164 while (!as.empty()) {
165 MADNESS_ASSERT(as.top());
166 as.top()->set(value);
167 as.pop();
168 }
169
170 while (!cb.empty()) {
171 MADNESS_ASSERT(cb.top());
172 cb.top()->notify();
173 cb.pop();
174 }
175
176 as.reset();
177 cb.reset();
178 }
179
180 /// Pass by value with implied copy to manage lifetime of \c f.
181
182 /// \todo Description needed.
183 /// \param[in] f Description needed.
184 inline void add_to_assignments(const std::shared_ptr< FutureImpl<T> > f) {
185 // ASSUME lock is already acquired
186 if (assigned) {
187 f->set(const_cast<T&>(t));
188 }
189 else {
190 assignmentT* as = const_cast<assignmentT*>(&assignments);
191 as->push(f);
192 }
193 }
194
195
196 public:
197
198 /// Constructor that uses a local unassigned value.
200 : callbacks()
201 , assignments()
202 , assigned(false)
203 , remote_ref()
204 , t()
205 {
206 }
207
208
209 /// Constructor that uses a wrapper for a remote future.
210
211 /// \todo Description needed.
212 /// \param[in] remote_ref Description needed.
214 : callbacks()
215 , assignments()
216 , assigned(false)
218 , t()
219 {
220 }
221
222
223 /// Checks if the value has been assigned.
224
225 /// \return True if the value has been assigned; false otherwise.
226 inline bool probe() const {
227 return assigned;
228 }
229
230
231 /// Registers a function to be invoked when future is assigned.
232
233 /// Callbacks are invoked in the order registered. If the
234 /// future is already assigned, the callback is immediately
235 /// invoked.
236 /// \todo Description needed.
237 /// \param callback Description needed.
238 inline void register_callback(CallbackInterface* callback) {
240 if (assigned) callback->notify();
241 else const_cast<callbackT&>(callbacks).push(callback);
242 }
243
244
245 /// Sets the value of the future (assignment).
246
247 /// \todo Descriptions needed.
248 /// \tparam U Description needed.
249 /// \param[in] value Description needed.
250 template <typename U>
251 void set(U&& value) {
253 if(remote_ref) {
254 // Copy world and owner from remote_ref since sending remote_ref
255 // will invalidate it.
256 World& world = remote_ref.get_world();
257 const ProcessID owner = remote_ref.owner();
259 new_am_arg(remote_ref, value));
260 set_assigned(std::forward<U>(value));
261 } else {
262 set_assigned((const_cast<T&>(t) = std::forward<U>(value)));
263 }
264 }
265
266
267 /// \todo Brief description needed.
268
269 /// \todo Descriptions needed.
270 /// \param[in] input_arch Description needed.
271 void set(const archive::BufferInputArchive& input_arch) {
274 input_arch & const_cast<T&>(t);
275 set_assigned(const_cast<T&>(t));
276 }
277
278
279 /// Gets/forces the value, waiting if necessary.
280
281 /// \param dowork If true (default) and the future is not ready
282 /// this thread will execute other tasks while waiting
283 /// \warning PaRSEC backend does not support `dowork=true`
284 /// from a callstack containing a running MADNESS task already,
285 /// hence must use `dowork=false` when need to call from within a task
286 /// \return reference to the contained value
287 /// \pre `this->is_local()`
288 T& get(bool dowork = true) {
289 MADNESS_ASSERT(! remote_ref); // Only for local futures
290 World::await([this] () -> bool { return this->probe(); }, dowork);
291 return *const_cast<T*>(&t);
292 }
293
294
295 /// Gets/forces the value, waiting if necessary.
296
297 /// \param dowork If true (default) and the future is not ready
298 /// this thread will execute other tasks while waiting
299 /// \warning PaRSEC backend does not support `dowork=true`
300 /// from a callstack containing a running MADNESS task already,
301 /// hence must use `dowork=false` when need to call from within a task
302 /// \return reference to the contained value
303 /// \pre `this->is_local()`
304 const T& get(bool dowork = true) const {
305 MADNESS_ASSERT(! remote_ref); // Only for local futures
306 World::await([this] () -> bool { return this->probe(); }, dowork);
307 return *const_cast<const T*>(&t);
308 }
309
310 /// \todo Brief description needed.
311
312 /// \todo Description needed.
313 /// \return Description needed.
314 bool is_local() const {
315 return ! remote_ref;
316 }
317
318 /// \todo Brief description needed.
319
320 /// \todo Is this function needed?
321 /// \todo Details needed.
322 /// \param f Description needed.
323 /// \return Description needed.
325 MADNESS_EXCEPTION("IS THIS WORKING? maybe now we have the mutex", 0);
326// ScopedMutex<Spinlock> fred(this);
327// MADNESS_ASSERT(!world); // was return false;
328// MADNESS_ASSERT(!assigned || f->assigned);
329// if (f->world) {
330// world = f->world;
331// remote_ref = f->remote_ref;
332// f->world = 0;
333// }
334// while(f->callbacks.size()) callbacks.push(f->callbacks.pop());
335// while(f->assignments.size()) assignments.push(f->assignments.pop());
336 return true;
337 }
338
339 /// Destructor.
340
341 /// \todo Perhaps a comment about its behavior.
342 virtual ~FutureImpl() {
343 if (const_cast<callbackT&>(callbacks).size()) {
344 print("Future: uninvoked callbacks being destroyed?", assigned);
345 abort();
346 }
347 if (const_cast<assignmentT&>(assignments).size()) {
348 print("Future: uninvoked assignment being destroyed?", assigned);
349 abort();
350 }
351 }
352 }; // class FutureImpl
353
354
355 /// A future is a possibly yet unevaluated value.
356
357 /// Uses delegation to \c FutureImpl to provide desired copy/assignment
358 /// semantics, as well as safe reference counting for remote futures.
359 ///
360 /// Since we are using futures a lot to store local values coming
361 /// from containers and inside task wrappers for messages, we
362 /// included in this class a value. If a future is assigned
363 /// before a copy/remote-reference is taken, the shared pointer is
364 /// never made. The point of this is to eliminate the two `malloc`s
365 /// that must be performed for every new \c shared_ptr.
366 /// \tparam T The type of future.
367 /// \todo Can this detailed description be made clearer?
368 template <typename T>
369 class Future {
370
371 friend std::ostream& operator<< <T>(std::ostream& out, const Future<T>& f);
372
373 private:
374
375 /// Pointer to the implementation object.
376 std::shared_ptr< FutureImpl<T> > f;
377 char buffer[sizeof(T)]; ///< Buffer to hold a single \c T object.
378 T* const value; ///< Pointer to buffer when it holds a \c T object.
379
380 /// \todo Has something to do with the "Gotchas" section in \ref futures. More detail needed.
381
382 /// \todo Perhaps more detail here, too... At the very least, can we give it a better name?
383 class dddd {};
384
385
386 /// \todo Constructor for ...
387
388 /// \todo Description needed.
389 /// \param[in] blah Description needed.
390 explicit Future(const dddd& blah) : f(), value(nullptr) { }
391
392 public:
393 /// \todo Brief description needed.
395
396 /// Makes an unassigned future.
398 f(new FutureImpl<T>()), value(nullptr)
399 {
400 }
401
402 /// Makes an assigned future.
403
404 /// \todo Description needed.
405 /// \param[in] t Description needed.
406 explicit Future(const T& t) :
407 f(), value(new(static_cast<void*>(buffer)) T(t))
408 {
409 }
410
411
412 /// Makes a future wrapping a remote reference.
413
414 /// \param[in] remote_ref The remote reference.
415 explicit Future(const remote_refT& remote_ref) :
417 remote_ref.get_shared() :
418 std::make_shared<FutureImpl<T> >(remote_ref)),
419 // std::shared_ptr<FutureImpl<T> >(new FutureImpl<T>(remote_ref))),
420 value(nullptr)
421 {
422 }
423
424
425 /// Makes an assigned future from an input archive.
426
427 /// \param[in] input_arch The input archive.
428 explicit Future(const archive::BufferInputArchive& input_arch) :
429 f(), value(new(static_cast<void*>(buffer)) T())
430 {
431 input_arch & (*value);
432 }
433
434
435 /// Shallow copy constructor.
436
437 /// \param[in] other The future to copy.
438 Future(const Future<T>& other) :
439 f(other.f),
440 value(other.value ?
441 new(static_cast<void*>(buffer)) T(* other.value) :
442 nullptr)
443 {
444 if(other.is_default_initialized())
445 f.reset(new FutureImpl<T>()); // Other was default constructed so make a new f
446 }
447
448 /// Destructor.
450 if(value)
451 value->~T();
452 }
453
454
455 /// \todo Informative description needed.
456
457 /// See "Gotchas" on \ref futures about why this exists and how to use it.
459 return Future<T>(dddd());
460 }
461
462 /// Check if the future is default initialized.
463
464 /// \return True if this future was constructed with
465 /// \c default_initializer(); false otherwise.
467 return ! (f || value);
468 }
469
470
471 /// Shallow assignment operator.
472
473 /// \param[in] other The future to copy.
474 /// \return This.
476 if(this != &other) {
478 if(f && other.value)
479 set(other);
480 else
481 f = other.f;
482 }
483 return *this;
484 }
485
486
487 /// \brief `A.set(B)`, where `A` and `B` are futures ensures `A`
488 /// has/will have the same value as `B`.
489
490 /// An exception is thrown if `A` is already assigned since a
491 /// \c Future is a single assignment variable. We don't yet
492 /// track multiple assignments from unassigned futures.
493 ///
494 /// If `B` is already assigned, this is the same as `A.set(B.get())`,
495 /// which sets `A` to the value of `B`.
496 ///
497 /// If `B` has not yet been assigned, the behavior is to ensure
498 /// that, when `B` is assigned, both `A` and `B` will be assigned
499 /// and have the same value (though they may/may not refer to
500 /// the same underlying copy of the data and indeed may even
501 /// be in different processes).
502 /// \todo Verification needed in the param statement.
503 /// \param[in] other The future `B` described above. `*this` is `A`.
504 void set(const Future<T>& other) {
506 if(f != other.f) {
507 MADNESS_ASSERT(! f->probe());
508 if (other.probe()) {
509 set(other.get()); // The easy case
510 } else {
511 // Assignment is supposed to happen just once so
512 // safe to assume that this is not being messed
513 // with ... also other might invoke the assignment
514 // callback since it could have been assigned
515 // between the test above and now (and this does
516 // happen)
517 std::shared_ptr< FutureImpl<T> > ff = f; // manage lifetime of me
518 std::shared_ptr< FutureImpl<T> > of = other.f; // manage lifetime of other
519
520 { // BEGIN CRITICAL SECTION
521 ScopedMutex<Spinlock> fred(of.get());
522 of->add_to_assignments(ff); // Recheck of assigned is performed in here
523 } // END CRITICAL SECTION
524 }
525 }
526 }
527
528
529 /// Assigns the value.
530
531 /// The value can only be set \em once.
532 /// \param[in] value The value to be assigned.
533 inline void set(const T& value) {
535 std::shared_ptr< FutureImpl<T> > ff = f; // manage lifetime of f
536 ff->set(value);
537 }
538
539 /// Assigns the value.
540
541 /// The value can only be set \em once.
542 /// \param[in] value The value to be assigned.
543 inline void set(T&& value) {
545 std::shared_ptr< FutureImpl<T> > ff = f; // manage lifetime of f
546 ff->set(std::move(value));
547 }
548
549 /// Assigns the value.
550
551 /// The value can only be set \em once.
552 /// \todo Description needed.
553 /// \param[in] input_arch Description needed.
554 inline void set(const archive::BufferInputArchive& input_arch) {
556 std::shared_ptr< FutureImpl<T> > ff = f; // manage lifetime of f
557 ff->set(input_arch);
558 }
559
560
561 /// Gets the value, waiting if necessary.
562
563 /// \param dowork If true (default) and the future is not ready
564 /// this thread will execute other tasks while waiting
565 /// \warning PaRSEC backend does not support `dowork=true`
566 /// from a callstack containing a running MADNESS task already,
567 /// hence must use `dowork=false` when need to call from within a task
568 /// \return reference to the contained value
569 /// \pre `this->is_local()`
570 inline T& get(bool dowork = true) & {
571 MADNESS_CHECK(this->is_local());
572 return (f ? f->get(dowork) : *value);
573 }
574
575 /// Gets the value, waiting if necessary.
576
577 /// \param dowork If true (default) and the future is not ready
578 /// this thread will execute other tasks while waiting
579 /// \warning PaRSEC backend does not support `dowork=true`
580 /// from a callstack containing a running MADNESS task already,
581 /// hence must use `dowork=false` when need to call from within a task
582 /// \return reference to the contained value
583 /// \pre `this->is_local()`
584 inline const T& get(bool dowork = true) const & {
585 MADNESS_CHECK(this->is_local());
586 return (f ? f->get(dowork) : *value);
587 }
588
589 /// Gets the value, waiting if necessary.
590
591 /// \param dowork If true (default) and the future is not ready
592 /// this thread will execute other tasks while waiting
593 /// \warning PaRSEC backend does not support `dowork=true`
594 /// from a callstack containing a running MADNESS task already,
595 /// hence must use `dowork=false` when need to call from within a task
596 /// \return the contained value
597 /// \pre `this->is_local()`
598 inline T get(bool dowork = true) && {
599 // According to explanation here
600 // https://stackoverflow.com/questions/4986673/c11-rvalues-and-move-semantics-confusion-return-statement
601 // should not return && since that will still be a ref to
602 // local value. Also, does not seem as if reference
603 // lifetime extension applies (see https://abseil.io/tips/107)
604 MADNESS_CHECK(this->is_local());
605 if (f) {
606 // N.B. it is only safe to move the data out if f is the owner (i.e. it is the sole ref)
607 // it's not clear how to safely detect ownership beyond the obvious cases (see https://stackoverflow.com/questions/41142315/why-is-stdshared-ptrunique-deprecated)
608 // e.g. in the common case f is set by a task, hence its refcount is 2 until the task has completed *and* been destroyed
609 // so will tread lightly here ... don't move unless safe
610 auto &value_ref = f->get(dowork);
611 // if the task setting f is gone *and* this is the only ref, move out
612 // to prevent a race with another thread that will make a copy of this Future while we are moving the data
613 // atomically swap f with nullptr, then check use count of f's copy
614 auto fcopy = std::atomic_exchange(&f, {}); // N.B. deprecated in C++20! need to convert f to std::atomic<std::shared_ptr<FutureImpl>>
615 // f is now null and no new ref to the value can be created
616 if (fcopy.use_count() == 1)
617 return std::move(value_ref);
618 else
619 return value_ref;
620 } else
621 return std::move(*value);
622 }
623
624 /// Check whether this future has been assigned.
625
626 /// \return True if the future has been assigned; false otherwise.
627 inline bool probe() const {
628 return (f ? f->probe() : bool(value));
629 }
630
631 /// Same as \c get()&.
632
633 /// \return An lvalue reference to the value.
634 inline operator T&() & { // Must return & since taskfn uses it in argument holder
635 return static_cast<Future&>(*this).get();
636 }
637
638 /// Same as `get() const&`.
639
640 /// \return A const lvalue reference to the value.
641 inline operator const T&() const& { // Must return & since taskfn uses it in argument holder
642 return static_cast<const Future&>(*this).get();
643 }
644
645 /// An rvalue analog of \c get().
646
647 /// \return An rvalue reference to the value.
648 inline operator T() && {
649 return static_cast<Future&&>(*this).get();
650 }
651
652 /// Returns a structure used to pass references to another process.
653
654 /// This is used for passing pointers/references to another
655 /// process. To make remote references completely safe, the
656 /// \c RemoteReference increments the internal reference count of
657 /// the \c Future. The counter is decremented by either
658 /// assigning to the remote \c Future or its destructor if it is
659 /// never assigned. The remote \c Future is \em only useful for
660 /// setting the future. It will \em not be notified if the value
661 /// is set elsewhere.
662 ///
663 /// If this is already a reference to a remote future, the
664 /// actual remote reference is returned; that is, \em not a
665 /// a reference to the local future. Therefore, the local
666 /// future will not be notified when the result is set
667 /// (i.e., the communication is short circuited).
668 /// \param[in,out] world The communication world.
669 /// \todo Verify the return comment.
670 /// \return The remote reference.
671 inline remote_refT remote_ref(World& world) const {
673 if (f->remote_ref)
674 return f->remote_ref;
675 else
676 return RemoteReference< FutureImpl<T> >(world, f);
677 }
678
679
680 /// Checks the future remoteness trait
681
682 /// \return true if the future refers to an already available or
683 /// to-be-locally-produced result
684 inline bool is_local() const {
685 return (f && f->is_local()) || value;
686 }
687
688
689 /// Checks the future remoteness trait
690
691 /// \return true if the future refers to another future on a another rank, i.e. it will be set when the
692 /// referred-to future is set
693 inline bool is_remote() const {
694 return !is_local();
695 }
696
697
698 /// Registers an object to be called when future is assigned.
699
700 /// Callbacks are invoked in the order registered. If the
701 /// future is already assigned, the callback is immediately
702 /// invoked.
703 /// \param[in] callback The callback to be invoked.
704 inline void register_callback(CallbackInterface* callback) {
705 if(probe()) {
706 callback->notify();
707 } else {
709 f->register_callback(callback);
710 }
711 }
712 }; // class Future
713
714
715 /// A future of a future is forbidden (by deleted constructor).
716
717 /// \tparam T The type of future.
718 template <typename T>
719 class Future< Future<T> > {
720 Future() = delete;
721 };
722
723
724 /// \brief Specialization of \c FutureImpl<void> for internal convenience.
725 /// This does nothing useful!
726 template <>
727 class FutureImpl<void> {};
728
729 /// \brief Specialization of \c Future<void> for internal convenience.
730 /// This does nothing useful!
731 template <> class
733 public:
734 /// \todo Brief description needed.
736
737 /// \todo Brief description needed.
738 static const Future<void> value;
739
740
741 /// \todo Brief description needed.
742
743 /// \todo Descriptions needed.
744 /// \param[in,out] world Description needed.
745 /// \return Description needed.
746 static remote_refT remote_ref(World& world) {
747 return remote_refT();
748 }
749
751
752
753 /// \todo Brief description needed.
754
755 /// \todo Description needed.
756 /// \param[in] remote_ref Description needed.
757 Future(const RemoteReference< FutureImpl<void> >& remote_ref) {}
758
759
760 /// Construct from an input archive.
761
762 /// \param[in] input_arch The input archive.
764 input_arch & *this;
765 }
766
767
768 /// Assignment operator.
769
770 /// \param[in] other The future to copy.
771 /// \return This.
772 inline Future<void>& operator=(const Future<void>& other) {
773 return *this;
774 }
775
776 /// Set the future from another \c void future.
777
778 /// In this specialization, do nothing.
779 /// \param[in] f The other future.
780 static void set(const Future<void>& f) { }
781
782
783 /// Set the future.
784
785 /// In this specialization, do nothing.
786 static void set() { }
787
788
789 /// Check if this future has been assigned.
790
791 /// \return True (in this specialization).
792 static bool probe() {
793 return true;
794 }
795
796 }; // class Future<void>
797
798
799 /// Specialization of \c Future for a vector of `Future`s.
800
801 /// Enables passing a vector of futures into a task and having the
802 /// dependencies correctly tracked. Does not directly support most
803 /// operations that other futures do; these are the responsibility of the
804 /// individual futures in the vector.
805 /// \tparam T The type of future.
806 template <typename T>
807 class Future< std::vector< Future<T> > > : public DependencyInterface, private NO_DEFAULTS {
808 private:
809 /// Alias for a vector of futures.
810 typedef typename std::vector< Future<T> > vectorT;
811
812 /// The vector of futures.
814
815 public:
816 Future() : v() { }
817
818 /// \todo Brief description needed.
819
820 /// \todo Description needed.
821 /// \param[in] v Vector of something...
822 Future(const vectorT& v) : DependencyInterface(v.size()), v(v) {
823 for (int i=0; i<(int)v.size(); ++i) {
824 this->v[i].register_callback(this);
825 }
826 }
827
828 /// \todo Brief description needed.
829
830 /// \todo Description needed.
831 /// \param[in] input_arch Description needed.
832 ///
833 /// \todo Not implemented. If this is deliberate, specify why and change the tag to \\attention.
834 explicit Future(const archive::BufferInputArchive& input_arch) {
835 input_arch & v;
836 }
837
838
839 /// Access the vector of futures.
840
841 /// \return The vector of futures.
843 return v;
844 }
845
846
847 /// Access the const vector of futures.
848
849 /// \return The vector of futures.
850 const vectorT& get() const {
851 return v;
852 }
853
854
855 /// Access the vector of futures.
856
857 /// \return The vector of futures.
858 operator vectorT& () {
859 return get();
860 }
861
862
863 /// Access the const vector of futures.
864
865 /// \return The vector of futures.
866 operator const vectorT& () const {
867 return get();
868 }
869
870
871 /// Check if all of the futures in the vector have been assigned.
872
873 /// \return True if all futures have been assigned; false otherwise.
874 bool probe() const {
876 }
877
878 }; // class Future< std::vector< Future<T> > >
879
880
881 /// Factory for a vectors of futures.
882
883 /// Rationale for this function can be found in \ref futures.
884 /// \tparam T The type of future in the vector.
885 /// \param[in] n The size of the vector to create.
886 /// \return A vector of futures, as described in \ref futures.
887 template <typename T>
888 std::vector< Future<T> > future_vector_factory(std::size_t n) {
889 return std::vector< Future<T> >(n, Future<T>::default_initializer());
890 }
891
892
893 namespace archive {
894
895 /// Serialize an assigned future.
896
897 /// \tparam Archive Archive type.
898 /// \tparam T Future type.
899 template <class Archive, typename T>
900 struct ArchiveStoreImpl< Archive, Future<T>, std::enable_if_t<!std::is_void_v<T>> > {
901
902 /// Store the assigned future in an archive.
903
904 /// \param[in,out] ar The archive.
905 /// \param[in] f The future.
906 template <typename U = T, typename A = Archive>
907 static inline
908 std::enable_if_t<is_serializable_v<A, U>,void>
909 store(const Archive& ar, const Future<T>& f) {
910 MAD_ARCHIVE_DEBUG(std::cout << "serializing future" << std::endl);
911 MADNESS_ASSERT(f.probe());
912 ar & f.get();
913 }
914 };
915
916
917 /// Deserialize a future into an unassigned future.
918
919 /// \tparam Archive Archive type.
920 /// \tparam T Future type.
921 template <class Archive, typename T>
922 struct ArchiveLoadImpl< Archive, Future<T>, std::enable_if_t<!std::is_void_v<T>> > {
923
924 /// Read into an unassigned future.
925
926 /// \param[in,out] ar The archive.
927 /// \param[out] f The future.
928 template <typename U = T, typename A = Archive>
929 static inline
930 std::enable_if_t<is_serializable_v<A, U>,void> load(const Archive& ar, Future<T>& f) {
931 MAD_ARCHIVE_DEBUG(std::cout << "deserializing future" << std::endl);
932 MADNESS_ASSERT(!f.probe());
933 T value;
934 ar & value;
935 f.set(value);
936 }
937 };
938
939
940 /// Serialize an assigned future (\c void specialization).
941
942 /// \tparam Archive Archive type.
943 template <class Archive>
944 struct ArchiveStoreImpl< Archive, Future<void> > {
945
946 /// Store the assigned \c void future in the archive (do nothing).
947
948 /// \param[in,out] ar The archive.
949 /// \param[in] f The \c void future.
950 static inline void store(const Archive& ar, const Future<void>& f)
951 { }
952 };
953
954
955 /// Deserialize a future into an unassigned future (\c void specialization).
956
957 /// \tparam Archive Archive type.
958 template <class Archive>
959 struct ArchiveLoadImpl< Archive, Future<void> > {
960
961 /// Read into an unassigned \c void future.
962
963 /// \param[in,out] ar The archive.
964 /// \param[out] f The \c void future.
965 static inline void load(const Archive& ar, const Future<void>& f)
966 { }
967 };
968
969 /// Serialize a vector of assigned futures.
970
971 /// \tparam Archive Archive type.
972 /// \tparam T Future type.
973 template <class Archive, typename T>
974 struct ArchiveStoreImpl< Archive, std::vector<Future<T> > > {
975
976 /// Store the vector of assigned futures in the archive.
977
978 /// \param[in,out] ar The archive.
979 /// \param[in] v The vector of futures.
980 static inline void store(const Archive& ar, const std::vector<Future<T> >& v) {
981 MAD_ARCHIVE_DEBUG(std::cout << "serializing vector of futures" << std::endl);
982 ar & v.size();
983 for(typename std::vector<Future<T> >::const_iterator it = v.begin(); it != v.end(); ++it) {
984 MADNESS_ASSERT(it->probe());
985 ar & it->get();
986 }
987 }
988 };
989
990
991 /// Deserialize a vector of futures into a vector of unassigned futures.
992
993 /// \tparam Archive Archive type.
994 /// \tparam T Future type.
995 template <class Archive, typename T>
996 struct ArchiveLoadImpl< Archive, std::vector<Future<T> > > {
997
998 /// Read into a vector of unassigned futures.
999
1000 /// \param[in,out] ar The archive.
1001 /// \param[out] v The vector of futures.
1002 static inline void load(const Archive& ar, std::vector<Future<T> >& v) {
1003 MAD_ARCHIVE_DEBUG(std::cout << "deserializing vector of futures" << std::endl);
1004 std::size_t n = 0;
1005 ar & n;
1006 if(v.size() < n)
1007 v.reserve(n);
1008 if(v.size() > n)
1009 v.resize(n);
1010 for(typename std::vector<Future<T> >::iterator it = v.begin(); it < v.end(); ++it, --n) {
1011 MADNESS_ASSERT(! it->probe());
1012 it->set(ar);
1013 }
1014 for(; n != 0; --n)
1015 v.push_back(Future<T>(ar));
1016 }
1017 };
1018 } // namespace archive
1019
1020
1021 // Friendly I/O to streams for futures
1022
1023 /// Stream output operator for a future.
1024
1025 /// \tparam T The type of future.
1026 /// \param[in,out] out The output stream.
1027 /// \param[in] f The future.
1028 /// \return The output stream.
1029 template <typename T>
1030 std::ostream& operator<<(std::ostream& out, const Future<T>& f);
1031
1032
1033 /// Stream output operator for a \c void future.
1034
1035 /// \param[in,out] out The output stream.
1036 /// \param[in] f The future.
1037 /// \return The output stream.
1038 template <>
1039 std::ostream& operator<<(std::ostream& out, const Future<void>& f);
1040
1041
1042 /// \todo Brief description needed.
1043
1044 /// \todo Descriptions needed.
1045 /// \tparam T Description needed.
1046 /// \param[in,out] The output stream.
1047 /// \param[in] f The future to be output.
1048 /// \return The output stream.
1049 template <typename T>
1050 inline std::ostream& operator<<(std::ostream& out, const Future<T>& f) {
1051 if (f.probe()) {
1052 if constexpr (is_ostreammable_v<T>) {
1053 out << f.get();
1054 }
1055 }
1056 else if (f.is_remote()) out << f.f->remote_ref;
1057 else if (f.f) out << "<unassigned refcnt=" << f.f.use_count() << ">";
1058 else out << "<unassigned>";
1059 return out;
1060 }
1061
1062} // namespace madness
1063
1064/// @}
1065
1066#endif // MADNESS_WORLD_FUTURE_H__INCLUDED
#define MAD_ARCHIVE_DEBUG(s)
Macro for helping debug archive tools.
Definition archive.h:77
Disables default copy constructor and assignment operators.
Definition nodefaults.h:49
World active message that extends an RMI message.
Definition worldam.h:80
The class used for callbacks (e.g., dependency tracking).
Definition dependency_interface.h:61
virtual void notify()=0
Invoked by the callback to notify when a dependency is satisfied.
Provides an interface for tracking dependencies.
Definition dependency_interface.h:100
bool probe() const
Returns true if ndepend == 0 (no unsatisfied dependencies).
Definition dependency_interface.h:178
void register_callback(CallbackInterface *callback)
Registers a callback that will be executed when ndepend==0; immediately invoked if ndepend==0.
Definition dependency_interface.h:201
Implements the functionality of futures.
Definition future.h:74
FutureImpl()
Constructor that uses a local unassigned value.
Definition future.h:199
static void set_handler(const AmArg &arg)
AM handler for remote set operations.
Definition future.h:106
const T & get(bool dowork=true) const
Gets/forces the value, waiting if necessary.
Definition future.h:304
static const int MAXCALLBACKS
Definition future.h:81
volatile T t
The future data.
Definition future.h:100
FutureImpl(const RemoteReference< FutureImpl< T > > &remote_ref)
Constructor that uses a wrapper for a remote future.
Definition future.h:213
void set_assigned(const T &value)
Definition future.h:149
void add_to_assignments(const std::shared_ptr< FutureImpl< T > > f)
Pass by value with implied copy to manage lifetime of f.
Definition future.h:184
void register_callback(CallbackInterface *callback)
Registers a function to be invoked when future is assigned.
Definition future.h:238
Stack< std::shared_ptr< FutureImpl< T > >, MAXCALLBACKS > assignmentT
Assignment type.
Definition future.h:84
Stack< CallbackInterface *, MAXCALLBACKS > callbackT
Callback type.
Definition future.h:83
void set(U &&value)
Sets the value of the future (assignment).
Definition future.h:251
void set(const archive::BufferInputArchive &input_arch)
Definition future.h:271
virtual ~FutureImpl()
Destructor.
Definition future.h:342
bool replace_with(FutureImpl< T > *f)
Definition future.h:324
RemoteReference< FutureImpl< T > > remote_ref
Reference to a remote future pimpl.
Definition future.h:98
bool probe() const
Checks if the value has been assigned.
Definition future.h:226
T & get(bool dowork=true)
Gets/forces the value, waiting if necessary.
Definition future.h:288
volatile callbackT callbacks
Definition future.h:88
volatile assignmentT assignments
Definition future.h:92
std::atomic< bool > assigned
A flag indicating if the future has been set.
Definition future.h:95
bool is_local() const
Definition future.h:314
Definition future.h:383
vectorT v
The vector of futures.
Definition future.h:813
bool probe() const
Check if all of the futures in the vector have been assigned.
Definition future.h:874
const vectorT & get() const
Access the const vector of futures.
Definition future.h:850
Future(const vectorT &v)
Definition future.h:822
vectorT & get()
Access the vector of futures.
Definition future.h:842
Future(const archive::BufferInputArchive &input_arch)
Definition future.h:834
std::vector< Future< T > > vectorT
Alias for a vector of futures.
Definition future.h:810
static const Future< void > value
Definition future.h:738
static void set(const Future< void > &f)
Set the future from another void future.
Definition future.h:780
static void set()
Set the future.
Definition future.h:786
Future()
Definition future.h:750
static remote_refT remote_ref(World &world)
Definition future.h:746
Future(const archive::BufferInputArchive &input_arch)
Construct from an input archive.
Definition future.h:763
Future(const RemoteReference< FutureImpl< void > > &remote_ref)
Definition future.h:757
RemoteReference< FutureImpl< void > > remote_refT
Definition future.h:735
static bool probe()
Check if this future has been assigned.
Definition future.h:792
Future< void > & operator=(const Future< void > &other)
Assignment operator.
Definition future.h:772
A future is a possibly yet unevaluated value.
Definition future.h:369
T & get(bool dowork=true) &
Gets the value, waiting if necessary.
Definition future.h:570
T get(bool dowork=true) &&
Gets the value, waiting if necessary.
Definition future.h:598
Future(const T &t)
Makes an assigned future.
Definition future.h:406
T *const value
Pointer to buffer when it holds a T object.
Definition future.h:378
remote_refT remote_ref(World &world) const
Returns a structure used to pass references to another process.
Definition future.h:671
Future()
Makes an unassigned future.
Definition future.h:397
const T & get(bool dowork=true) const &
Gets the value, waiting if necessary.
Definition future.h:584
void set(const Future< T > &other)
A.set(B), where A and B are futures ensures A has/will have the same value as B.
Definition future.h:504
void set(const T &value)
Assigns the value.
Definition future.h:533
void set(const archive::BufferInputArchive &input_arch)
Assigns the value.
Definition future.h:554
Future(const archive::BufferInputArchive &input_arch)
Makes an assigned future from an input archive.
Definition future.h:428
~Future()
Destructor.
Definition future.h:449
static const Future< T > default_initializer()
See "Gotchas" on Futures about why this exists and how to use it.
Definition future.h:458
Future(const dddd &blah)
Definition future.h:390
char buffer[sizeof(T)]
Buffer to hold a single T object.
Definition future.h:377
RemoteReference< FutureImpl< T > > remote_refT
Definition future.h:394
bool is_local() const
Checks the future remoteness trait.
Definition future.h:684
Future(const remote_refT &remote_ref)
Makes a future wrapping a remote reference.
Definition future.h:415
bool is_remote() const
Checks the future remoteness trait.
Definition future.h:693
void register_callback(CallbackInterface *callback)
Registers an object to be called when future is assigned.
Definition future.h:704
Future(const Future< T > &other)
Shallow copy constructor.
Definition future.h:438
std::shared_ptr< FutureImpl< T > > f
Pointer to the implementation object.
Definition future.h:376
void set(T &&value)
Assigns the value.
Definition future.h:543
Future< T > & operator=(const Future< T > &other)
Shallow assignment operator.
Definition future.h:475
bool is_default_initialized() const
Check if the future is default initialized.
Definition future.h:466
bool probe() const
Check whether this future has been assigned.
Definition future.h:627
Simple structure used to manage references/pointers to remote instances.
Definition worldref.h:395
void reset()
Release this reference.
Definition worldref.h:478
pointerT get() const
Reference pointer accessor.
Definition worldref.h:497
Mutex that is applied/released at start/end of a scope.
Definition worldmutex.h:239
Spinlock using pthread spinlock operations.
Definition worldmutex.h:253
Dynamically sized Stack with small stack size optimization.
Definition stack.h:154
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
A parallel world class.
Definition world.h:132
static void await(SafeMPI::Request &request, bool dowork=true)
Wait for a MPI request to complete.
Definition world.h:534
WorldAmInterface & am
AM interface.
Definition world.h:205
Wraps an archive around a memory buffer for input.
Definition buffer_archive.h:134
Defines DependencyInterface and CallbackInterface.
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:28
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:2503
static const double v
Definition hatom_sf_dirac.cc:20
#define MADNESS_PRAGMA_CLANG(x)
Definition madness_config.h:200
#define MADNESS_CHECK(condition)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:182
#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
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
std::ostream & operator<<(std::ostream &os, const particle< PDIM > &p)
Definition lowrankfunction.h:401
AmArg * new_am_arg(const argT &... args)
Convenience template for serializing arguments into a new AmArg.
Definition worldam.h:194
static double pop(std::vector< double > &v)
Definition SCF.cc:115
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:226
NDIM & f
Definition mra.h:2528
std::vector< Future< T > > future_vector_factory(std::size_t n)
Factory for a vectors of futures.
Definition future.h:888
Definition mraimpl.h:51
Implements NO_DEFAULTS.
Implement Stack for a fixed-size stack container.
static std::enable_if_t< is_serializable_v< A, U >, void > load(const Archive &ar, Future< T > &f)
Read into an unassigned future.
Definition future.h:930
static void load(const Archive &ar, const Future< void > &f)
Read into an unassigned void future.
Definition future.h:965
static void load(const Archive &ar, std::vector< Future< T > > &v)
Read into a vector of unassigned futures.
Definition future.h:1002
Default load of an object via serialize(ar, t).
Definition archive.h:667
static std::enable_if_t< is_serializable_v< A, U >, void > store(const Archive &ar, const Future< T > &f)
Store the assigned future in an archive.
Definition future.h:909
static void store(const Archive &ar, const Future< void > &f)
Store the assigned void future in the archive (do nothing).
Definition future.h:950
static void store(const Archive &ar, const std::vector< Future< T > > &v)
Store the vector of assigned futures in the archive.
Definition future.h:980
Default store of an object via serialize(ar, t).
Definition archive.h:612
double fred(const coordT &r)
Definition tdse4.cc:368
Declares the World class for the parallel runtime environment.
Implements RemoteReference which is for internal use.
int ProcessID
Used to clearly identify process number/rank.
Definition worldtypes.h:43