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>
48 #include <madness/world/worldref.h>
49 #include <madness/world/world.h>
50 
51 /// \addtogroup futures
52 /// @{
53 namespace 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.
88  volatile callbackT callbacks;
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();
133  world.am.send(owner, FutureImpl<T>::set_handler,
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();
262  world.am.send(owner, FutureImpl<T>::set_handler,
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.
401  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) :
420  f(remote_ref.is_local() ?
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.
470  bool is_default_initialized() const {
471  return ! (f || value);
472  }
473 
474 
475  /// Shallow assignment operator.
476 
477  /// \param[in] other The future to copy.
478  /// \return This.
479  Future<T>& operator=(const Future<T>& other) {
480  if(this != &other) {
481  MADNESS_ASSERT(!probe());
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) {
509  MADNESS_ASSERT(f);
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) {
538  MADNESS_CHECK(f);
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) {
548  MADNESS_CHECK(f);
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) {
559  MADNESS_CHECK(f);
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 {
676  MADNESS_ASSERT(!probe());
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 {
712  MADNESS_ASSERT(f);
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
736  Future<void> {
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 
754  Future() {}
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.
767  Future(const archive::BufferInputArchive& input_arch) {
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
Specialization of FutureImpl<void> for internal convenience. This does nothing useful!
Definition: future.h:731
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
T & get(bool dowork=true)
Gets/forces the value, waiting if necessary.
Definition: future.h:292
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
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
Future(const vectorT &v)
Definition: future.h:826
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
const vectorT & get() const
Access the const vector of futures.
Definition: future.h:854
vectorT & get()
Access the vector of futures.
Definition: future.h:846
Specialization of Future<void> for internal convenience. This does nothing useful!
Definition: future.h:736
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< void > & operator=(const Future< void > &other)
Assignment operator.
Definition: future.h:776
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
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: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
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
T & get(bool dowork=true) &
Gets the value, waiting if necessary.
Definition: future.h:574
Future(const archive::BufferInputArchive &input_arch)
Makes an assigned future from an input archive.
Definition: future.h:432
~Future()
Destructor.
Definition: future.h:453
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
const T & get(bool dowork=true) const &
Gets the value, waiting if necessary.
Definition: future.h:588
Future< T > & operator=(const Future< T > &other)
Shallow assignment operator.
Definition: future.h:479
void set(T &&value)
Assigns the value.
Definition: future.h:547
static const Future< T > default_initializer()
See "Gotchas" on Futures about why this exists and how to use it.
Definition: future.h:462
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
bool empty() const
Check if the stack is empty.
Definition: stack.h:387
void reset()
Empty the stack and free memory.
Definition: stack.h:406
reference top()
Get the last item pushed onto the stack.
Definition: stack.h:355
void push(const_reference value)
Push a new item onto the stack.
Definition: stack.h:318
void pop()
Pop an item off of the stack.
Definition: stack.h:345
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:190
#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
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
AmArg * new_am_arg(const argT &... args)
Convenience template for serializing arguments into a new AmArg.
Definition: worldam.h:194
std::vector< Future< T > > future_vector_factory(std::size_t n)
Factory for a vectors of futures.
Definition: future.h:892
std::ostream & operator<<(std::ostream &os, const particle< PDIM > &p)
Definition: lowrankfunction.h:397
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
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