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