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