diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp index eac242acfaaf..46dd763a4fb4 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/make_heap.hpp @@ -344,11 +344,12 @@ namespace hpx { namespace parallel { inline namespace v1 { policy.executor(), op, shapes); // Required synchronization per level - hpx::wait_all_nothrow(workitems); - - // collect exceptions - util::detail::handle_local_exceptions< - ExPolicy>::call(workitems, errors, false); + if (hpx::wait_all_nothrow(workitems)) + { + // collect exceptions + util::detail::handle_local_exceptions< + ExPolicy>::call(workitems, errors, false); + } } if (!errors.empty()) diff --git a/libs/core/algorithms/include/hpx/parallel/util/foreach_partitioner.hpp b/libs/core/algorithms/include/hpx/parallel/util/foreach_partitioner.hpp index ed982ad18663..4ef578bb07d2 100644 --- a/libs/core/algorithms/include/hpx/parallel/util/foreach_partitioner.hpp +++ b/libs/core/algorithms/include/hpx/parallel/util/foreach_partitioner.hpp @@ -138,13 +138,14 @@ namespace hpx { namespace parallel { namespace util { std::pair&& items, F&& f, FwdIter last) { // wait for all tasks to finish - hpx::wait_all_nothrow(hpx::get<0>(items), hpx::get<1>(items)); - - // always rethrow if inititems/workitems have at least one - // exceptional future - handle_local_exceptions::call(hpx::get<0>(items)); - handle_local_exceptions::call(hpx::get<1>(items)); - + if (hpx::wait_all_nothrow( + hpx::get<0>(items), hpx::get<1>(items))) + { + // always rethrow if inititems/workitems have at least one + // exceptional future + handle_local_exceptions::call(hpx::get<0>(items)); + handle_local_exceptions::call(hpx::get<1>(items)); + } return f(HPX_MOVE(last)); } @@ -152,11 +153,12 @@ namespace hpx { namespace parallel { namespace util { static FwdIter reduce(Items&& items, F&& f, FwdIter last) { // wait for all tasks to finish - hpx::wait_all_nothrow(items); - - // always rethrow if items has at least one exceptional future - handle_local_exceptions::call(items); - + if (hpx::wait_all_nothrow(items)) + { + // always rethrow if items has at least one exceptional + // future + handle_local_exceptions::call(items); + } return f(HPX_MOVE(last)); } }; diff --git a/libs/core/algorithms/include/hpx/parallel/util/partitioner.hpp b/libs/core/algorithms/include/hpx/parallel/util/partitioner.hpp index 1a7115ab70b7..7e9b6da57473 100644 --- a/libs/core/algorithms/include/hpx/parallel/util/partitioner.hpp +++ b/libs/core/algorithms/include/hpx/parallel/util/partitioner.hpp @@ -283,11 +283,12 @@ namespace hpx { namespace parallel { namespace util { static R reduce(Items&& workitems, F&& f) { // wait for all tasks to finish - hpx::wait_all_nothrow(workitems); - - // always rethrow workitems has at least one exceptional future - handle_local_exceptions::call(workitems); - + if (hpx::wait_all_nothrow(workitems)) + { + // always rethrow workitems has at least one exceptional + // future + handle_local_exceptions::call(workitems); + } return f(HPX_MOVE(workitems)); } @@ -295,10 +296,12 @@ namespace hpx { namespace parallel { namespace util { static void reduce(Items&& workitems, hpx::util::empty_function) { // wait for all tasks to finish - hpx::wait_all_nothrow(workitems); - - // always rethrow workitems has at least one exceptional future - handle_local_exceptions::call(workitems); + if (hpx::wait_all_nothrow(workitems)) + { + // always rethrow workitems has at least one exceptional + // future + handle_local_exceptions::call(workitems); + } } template diff --git a/libs/core/algorithms/include/hpx/parallel/util/partitioner_with_cleanup.hpp b/libs/core/algorithms/include/hpx/parallel/util/partitioner_with_cleanup.hpp index b73c6b3f60ca..c4060cdb893c 100644 --- a/libs/core/algorithms/include/hpx/parallel/util/partitioner_with_cleanup.hpp +++ b/libs/core/algorithms/include/hpx/parallel/util/partitioner_with_cleanup.hpp @@ -86,13 +86,13 @@ namespace hpx { namespace parallel { namespace util { static R reduce(Items&& workitems, F&& f, Cleanup&& cleanup) { // wait for all tasks to finish - hpx::wait_all_nothrow(workitems); - - // always rethrow if 'errors' is not empty or workitems has - // exceptional future - handle_local_exceptions::call_with_cleanup( - workitems, HPX_FORWARD(Cleanup, cleanup)); - + if (hpx::wait_all_nothrow(workitems)) + { + // always rethrow if 'errors' is not empty or workitems has + // exceptional future + handle_local_exceptions::call_with_cleanup( + workitems, HPX_FORWARD(Cleanup, cleanup)); + } return f(HPX_MOVE(workitems)); } diff --git a/libs/core/algorithms/include/hpx/parallel/util/scan_partitioner.hpp b/libs/core/algorithms/include/hpx/parallel/util/scan_partitioner.hpp index 8adb7f6ec3a2..c36b1ed9cabf 100644 --- a/libs/core/algorithms/include/hpx/parallel/util/scan_partitioner.hpp +++ b/libs/core/algorithms/include/hpx/parallel/util/scan_partitioner.hpp @@ -148,7 +148,10 @@ namespace hpx { namespace parallel { namespace util { } // Wait for all f1 tasks to finish - hpx::wait_all_nothrow(workitems); + if (hpx::wait_all_nothrow(workitems)) + { + handle_local_exceptions::call(workitems, errors); + } // perform f2 sequentially in one go f2results.resize(workitems.size()); @@ -343,12 +346,14 @@ namespace hpx { namespace parallel { namespace util { return R(); #else // wait for all tasks to finish - hpx::wait_all_nothrow(workitems, finalitems); - - // always rethrow if 'errors' is not empty or 'workitems' or - // 'finalitems' have an exceptional future - handle_local_exceptions::call(workitems, errors); - handle_local_exceptions::call(finalitems, errors); + if (hpx::wait_all_nothrow(workitems, finalitems) || + !errors.empty()) + { + // always rethrow if 'errors' is not empty or 'workitems' or + // 'finalitems' have an exceptional future + handle_local_exceptions::call(workitems, errors); + handle_local_exceptions::call(finalitems, errors); + } try { @@ -376,11 +381,12 @@ namespace hpx { namespace parallel { namespace util { return R(); #else // wait for all tasks to finish - hpx::wait_all_nothrow(finalitems); - - // always rethrow if 'errors' is not empty or - // 'finalitems' have an exceptional future - handle_local_exceptions::call(finalitems, errors); + if (hpx::wait_all_nothrow(finalitems) || !errors.empty()) + { + // always rethrow if 'errors' is not empty or 'finalitems' + // have an exceptional future + handle_local_exceptions::call(finalitems, errors); + } try { diff --git a/libs/core/async_combinators/include/hpx/async_combinators/wait_all.hpp b/libs/core/async_combinators/include/hpx/async_combinators/wait_all.hpp index e840f6c482a0..44905cf9f9c7 100644 --- a/libs/core/async_combinators/include/hpx/async_combinators/wait_all.hpp +++ b/libs/core/async_combinators/include/hpx/async_combinators/wait_all.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2022 Hartmut Kaiser // Copyright (c) 2013 Agustin Berge // // SPDX-License-Identifier: BSL-1.0 @@ -264,30 +264,41 @@ namespace hpx { auto next_future_data = hpx::traits::detail::get_shared_state(*next); - if (next_future_data && !next_future_data->is_ready()) + if (next_future_data) { - next_future_data->execute_deferred(); - - // execute_deferred might have made the future ready if (!next_future_data->is_ready()) { - // Attach a continuation to this future which will - // re-evaluate it and continue to the next element - // in the sequence (if any). - next_future_data->set_on_completed( - [this_ = HPX_MOVE(this_), - next = HPX_FORWARD(Iter, next), - end = HPX_FORWARD( - Iter, end)]() mutable -> void { - this_->template await_range( - HPX_MOVE(next), HPX_MOVE(end)); - }); + next_future_data->execute_deferred(); + + // execute_deferred might have made the future ready + if (!next_future_data->is_ready()) + { + // Attach a continuation to this future which will + // re-evaluate it and continue to the next element + // in the sequence (if any). + next_future_data->set_on_completed( + [this_ = HPX_MOVE(this_), + next = HPX_FORWARD(Iter, next), + end = HPX_FORWARD( + Iter, end)]() mutable -> void { + this_->template await_range( + HPX_MOVE(next), HPX_MOVE(end)); + }); + + // explicitly destruct iterators as those might + // become dangling after we make ourselves ready + next = std::decay_t{}; + end = std::decay_t{}; + + return; + } + } - // explicitly destruct iterators as those might - // become dangling after we make ourselves ready - next = std::decay_t{}; - end = std::decay_t{}; - return; + // check whether the current future is exceptional + if (!has_exceptional_results_ && + next_future_data->has_exception()) + { + has_exceptional_results_ = true; } } } @@ -318,22 +329,32 @@ namespace hpx { auto next_future_data = hpx::traits::detail::get_shared_state(hpx::get(t_)); - if (next_future_data && !next_future_data->is_ready()) + if (next_future_data) { - next_future_data->execute_deferred(); - - // execute_deferred might have made the future ready if (!next_future_data->is_ready()) { - // Attach a continuation to this future which will - // re-evaluate it and continue to the next argument - // (if any). - next_future_data->set_on_completed( - [this_ = HPX_MOVE(this_)]() -> void { - this_->template await_future(); - }); - - return; + next_future_data->execute_deferred(); + + // execute_deferred might have made the future ready + if (!next_future_data->is_ready()) + { + // Attach a continuation to this future which will + // re-evaluate it and continue to the next argument + // (if any). + next_future_data->set_on_completed( + [this_ = HPX_MOVE(this_)]() -> void { + this_->template await_future(); + }); + + return; + } + } + + // check whether the current future is exceptional + if (!has_exceptional_results_ && + next_future_data->has_exception()) + { + has_exceptional_results_ = true; } } @@ -369,7 +390,7 @@ namespace hpx { } public: - void wait_all() + bool wait_all() { do_await<0>(); @@ -379,16 +400,21 @@ namespace hpx { { this->wait(); } + + // return whether at least one of the futures has become + // exceptional + return has_exceptional_results_; } private: Tuple const& t_; + bool has_exceptional_results_ = false; }; } // namespace detail /////////////////////////////////////////////////////////////////////////// template - void wait_all_nothrow(std::vector const& values) + bool wait_all_nothrow(std::vector const& values) { if (!values.empty()) { @@ -399,38 +425,46 @@ namespace hpx { // frame is initialized with initial reference count hpx::intrusive_ptr frame(new frame_type(data), false); - frame->wait_all(); + return frame->wait_all(); } + return false; } template void wait_all(std::vector const& values) { - hpx::wait_all_nothrow(values); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow(values)) + { + hpx::detail::throw_if_exceptional(values); + } } template - HPX_FORCEINLINE void wait_all_nothrow(std::vector& values) + HPX_FORCEINLINE bool wait_all_nothrow(std::vector& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); + return hpx::wait_all_nothrow( + const_cast const&>(values)); } template HPX_FORCEINLINE void wait_all(std::vector& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow( + const_cast const&>(values))) + { + hpx::detail::throw_if_exceptional(values); + } } template #if !defined(HPX_INTEL_VERSION) HPX_FORCEINLINE #endif - void + bool wait_all_nothrow(std::vector&& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); + return hpx::wait_all_nothrow( + const_cast const&>(values)); } template @@ -440,13 +474,16 @@ namespace hpx { void wait_all(std::vector&& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow( + const_cast const&>(values))) + { + hpx::detail::throw_if_exceptional(values); + } } /////////////////////////////////////////////////////////////////////////// template - void wait_all_nothrow(std::array const& values) + bool wait_all_nothrow(std::array const& values) { using result_type = hpx::tuple const&>; using frame_type = hpx::detail::wait_all_frame; @@ -455,53 +492,64 @@ namespace hpx { // frame is initialized with initial reference count hpx::intrusive_ptr frame(new frame_type(data), false); - frame->wait_all(); + return frame->wait_all(); } template void wait_all(std::array const& values) { - hpx::wait_all_nothrow(values); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow(values)) + { + hpx::detail::throw_if_exceptional(values); + } } template - HPX_FORCEINLINE void wait_all_nothrow(std::array& values) + HPX_FORCEINLINE bool wait_all_nothrow(std::array& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); + return hpx::wait_all_nothrow( + const_cast const&>(values)); } template HPX_FORCEINLINE void wait_all(std::array& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow( + const_cast const&>(values))) + { + hpx::detail::throw_if_exceptional(values); + } } template - HPX_FORCEINLINE void wait_all_nothrow(std::array&& values) + HPX_FORCEINLINE bool wait_all_nothrow(std::array&& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); + return hpx::wait_all_nothrow( + const_cast const&>(values)); } template HPX_FORCEINLINE void wait_all(std::array&& values) { - hpx::wait_all_nothrow(const_cast const&>(values)); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow( + const_cast const&>(values))) + { + hpx::detail::throw_if_exceptional(values); + } } /////////////////////////////////////////////////////////////////////////// template >> - void wait_all_nothrow(Iterator begin, Iterator end) + bool wait_all_nothrow(Iterator begin, Iterator end) { if (begin != end) { auto values = traits::acquire_shared_state()(begin, end); - hpx::wait_all_nothrow(values); + return hpx::wait_all_nothrow(values); } + return false; } template ()(begin, end); - hpx::wait_all_nothrow(values); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow(values)) + { + hpx::detail::throw_if_exceptional(values); + } } } @@ -521,14 +571,15 @@ namespace hpx { template >> - void wait_all_n_nothrow(Iterator begin, std::size_t count) + bool wait_all_n_nothrow(Iterator begin, std::size_t count) { if (count != 0) { auto values = traits::acquire_shared_state()(begin, count); - hpx::wait_all_nothrow(values); + return hpx::wait_all_nothrow(values); } + return false; } template ()(begin, count); - hpx::wait_all_nothrow(values); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_all_nothrow(values)) + { + hpx::detail::throw_if_exceptional(values); + } } } /////////////////////////////////////////////////////////////////////////// - constexpr inline void wait_all_nothrow() noexcept {} + constexpr inline bool wait_all_nothrow() noexcept + { + return false; + } constexpr inline void wait_all() noexcept {} /////////////////////////////////////////////////////////////////////////// template - void wait_all_nothrow(Ts&&... ts) + bool wait_all_nothrow(Ts&&... ts) { if constexpr (sizeof...(Ts) != 0) { @@ -564,15 +620,18 @@ namespace hpx { // frame is initialized with initial reference count hpx::intrusive_ptr frame(new frame_type(values), false); - frame->wait_all(); + return frame->wait_all(); } + return false; } template void wait_all(Ts&&... ts) { - hpx::wait_all_nothrow(ts...); - hpx::detail::throw_if_exceptional(HPX_FORWARD(Ts, ts)...); + if (hpx::wait_all_nothrow(ts...)) + { + hpx::detail::throw_if_exceptional(HPX_FORWARD(Ts, ts)...); + } } } // namespace hpx diff --git a/libs/core/async_combinators/include/hpx/async_combinators/wait_any.hpp b/libs/core/async_combinators/include/hpx/async_combinators/wait_any.hpp index ef23fa6a4a0d..5c689b9e26b5 100644 --- a/libs/core/async_combinators/include/hpx/async_combinators/wait_any.hpp +++ b/libs/core/async_combinators/include/hpx/async_combinators/wait_any.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2022 Hartmut Kaiser // Copyright (c) 2013 Agustin Berge // // SPDX-License-Identifier: BSL-1.0 @@ -137,9 +137,9 @@ namespace hpx { /////////////////////////////////////////////////////////////////////////// template - void wait_any_nothrow(std::vector const& futures) + bool wait_any_nothrow(std::vector const& futures) { - hpx::wait_some_nothrow(1, futures); + return hpx::wait_some_nothrow(1, futures); } template @@ -149,9 +149,9 @@ namespace hpx { } template - void wait_any_nothrow(std::vector& lazy_values) + bool wait_any_nothrow(std::vector& lazy_values) { - hpx::wait_any_nothrow( + return hpx::wait_any_nothrow( const_cast const&>(lazy_values)); } @@ -162,9 +162,9 @@ namespace hpx { } template - void wait_any_nothrow(std::vector&& lazy_values) + bool wait_any_nothrow(std::vector&& lazy_values) { - hpx::wait_any_nothrow( + return hpx::wait_any_nothrow( const_cast const&>(lazy_values)); } @@ -176,9 +176,9 @@ namespace hpx { /////////////////////////////////////////////////////////////////////////// template - void wait_any_nothrow(std::array const& futures) + bool wait_any_nothrow(std::array const& futures) { - hpx::wait_some_nothrow(1, futures); + return hpx::wait_some_nothrow(1, futures); } template @@ -188,9 +188,9 @@ namespace hpx { } template - void wait_any_nothrow(std::array& lazy_values) + bool wait_any_nothrow(std::array& lazy_values) { - hpx::wait_any_nothrow( + return hpx::wait_any_nothrow( const_cast const&>(lazy_values)); } @@ -201,9 +201,9 @@ namespace hpx { } template - void wait_any_nothrow(std::array&& lazy_values) + bool wait_any_nothrow(std::array&& lazy_values) { - hpx::wait_any_nothrow( + return hpx::wait_any_nothrow( const_cast const&>(lazy_values)); } @@ -217,9 +217,9 @@ namespace hpx { template >> - void wait_any_nothrow(Iterator begin, Iterator end) + bool wait_any_nothrow(Iterator begin, Iterator end) { - hpx::wait_some_nothrow(1, begin, end); + return hpx::wait_some_nothrow(1, begin, end); } template >> - void wait_any_n_nothrow(Iterator begin, std::size_t count) + bool wait_any_n_nothrow(Iterator begin, std::size_t count) { - hpx::wait_some_n_nothrow(1, begin, count); + return hpx::wait_some_n_nothrow(1, begin, count); } template - void wait_any_nothrow(Ts&&... ts) + bool wait_any_nothrow(Ts&&... ts) { - hpx::wait_some_nothrow(1, HPX_FORWARD(Ts, ts)...); + return hpx::wait_some_nothrow(1, HPX_FORWARD(Ts, ts)...); } template @@ -338,7 +338,7 @@ namespace hpx::lcos { 1, 8, "hpx::lcos::wait_any is deprecated. Use hpx::wait_any instead.") inline void wait_any(error_code& = throws) { - hpx::wait_some(1); + hpx::wait_some(0); } /////////////////////////////////////////////////////////////////////////// diff --git a/libs/core/async_combinators/include/hpx/async_combinators/wait_some.hpp b/libs/core/async_combinators/include/hpx/async_combinators/wait_some.hpp index daf8780d8444..dc3bc25eff5d 100644 --- a/libs/core/async_combinators/include/hpx/async_combinators/wait_some.hpp +++ b/libs/core/async_combinators/include/hpx/async_combinators/wait_some.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2022 Hartmut Kaiser // Copyright (c) 2013 Agustin Berge // // SPDX-License-Identifier: BSL-1.0 @@ -193,21 +193,32 @@ namespace hpx { std::size_t counter = wait_.count_.load(std::memory_order_acquire); - if (counter < wait_.needed_count_ && shared_state && - !shared_state->is_ready()) + if (counter < wait_.needed_count_ && shared_state) { - // handle future only if not enough futures are ready yet - // also, do not touch any futures which are already ready - shared_state->execute_deferred(); - - // execute_deferred might have made the future ready if (!shared_state->is_ready()) { - shared_state->set_on_completed(util::deferred_call( - &wait_some::on_future_ready, - wait_.shared_from_this(), - hpx::execution_base::this_thread::agent())); - return; + // handle future only if not enough futures are ready yet + // also, do not touch any futures which are already ready + shared_state->execute_deferred(); + + // execute_deferred might have made the future ready + if (!shared_state->is_ready()) + { + shared_state->set_on_completed( + util::deferred_call( + &wait_some::on_future_ready, + wait_.shared_from_this(), + hpx::execution_base::this_thread:: + agent())); + return; + } + } + + // check whether the current future is exceptional + if (!wait_.has_exceptional_results_ && + shared_state->has_exception()) + { + wait_.has_exceptional_results_ = true; } } @@ -284,11 +295,10 @@ namespace hpx { : values_(values) , count_(0) , needed_count_(n) - , goal_reached_on_calling_thread_(false) { } - void operator()() + bool operator()() { // set callback functions to executed wait future is ready set_on_completed_callback(*this); @@ -306,12 +316,15 @@ namespace hpx { // at least N futures should be ready HPX_ASSERT( count_.load(std::memory_order_acquire) >= needed_count_); + + return has_exceptional_results_; } argument_type const& values_; std::atomic count_; std::size_t const needed_count_; - bool goal_reached_on_calling_thread_; + bool goal_reached_on_calling_thread_ = false; + bool has_exceptional_results_ = false; }; template @@ -323,37 +336,40 @@ namespace hpx { /////////////////////////////////////////////////////////////////////////// template - void wait_some_nothrow(std::size_t n, std::vector const& values) + bool wait_some_nothrow(std::size_t n, std::vector const& values) { static_assert( hpx::traits::is_future_v, "invalid use of hpx::wait_some"); if (n == 0) { - return; + return false; } if (n > values.size()) { HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::wait_some", "number of results to wait for is out of bounds"); - return; + return false; } auto lazy_values = traits::acquire_shared_state_disp()(values); auto f = detail::get_wait_some_frame(lazy_values, n); - (*f)(); + + return (*f)(); } template void wait_some(std::size_t n, std::vector const& values) { - hpx::wait_some_nothrow(n, values); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_some_nothrow(n, values)) + { + hpx::detail::throw_if_exceptional(values); + } } template - void wait_some_nothrow(std::size_t n, std::vector& values) + bool wait_some_nothrow(std::size_t n, std::vector& values) { return hpx::wait_some_nothrow( n, const_cast const&>(values)); @@ -362,13 +378,15 @@ namespace hpx { template void wait_some(std::size_t n, std::vector& values) { - hpx::wait_some_nothrow( - n, const_cast const&>(values)); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_some_nothrow( + n, const_cast const&>(values))) + { + hpx::detail::throw_if_exceptional(values); + } } template - void wait_some_nothrow(std::size_t n, std::vector&& values) + bool wait_some_nothrow(std::size_t n, std::vector&& values) { return hpx::wait_some_nothrow( n, const_cast const&>(values)); @@ -377,81 +395,91 @@ namespace hpx { template void wait_some(std::size_t n, std::vector&& values) { - hpx::wait_some_nothrow( - n, const_cast const&>(values)); - hpx::detail::throw_if_exceptional(values); + if (hpx::wait_some_nothrow( + n, const_cast const&>(values))) + { + hpx::detail::throw_if_exceptional(values); + } } /////////////////////////////////////////////////////////////////////////// template - void wait_some_nothrow(std::size_t n, std::array const& values) + bool wait_some_nothrow(std::size_t n, std::array const& values) { static_assert( hpx::traits::is_future_v, "invalid use of wait_some"); if (n == 0) { - return; + return false; } if (n > values.size()) { HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::wait_some", "number of results to wait for is out of bounds"); - return; + return false; } auto lazy_values = traits::acquire_shared_state_disp()(values); auto f = detail::get_wait_some_frame(lazy_values, n); - (*f)(); + + return (*f)(); } template void wait_some(std::size_t n, std::array const& lazy_values) { - hpx::wait_some_nothrow(n, lazy_values); - hpx::detail::throw_if_exceptional(lazy_values); + if (hpx::wait_some_nothrow(n, lazy_values)) + { + hpx::detail::throw_if_exceptional(lazy_values); + } } template - void wait_some_nothrow(std::size_t n, std::array& lazy_values) + bool wait_some_nothrow(std::size_t n, std::array& lazy_values) { - hpx::wait_some_nothrow( + return hpx::wait_some_nothrow( n, const_cast const&>(lazy_values)); } template void wait_some(std::size_t n, std::array& lazy_values) { - hpx::wait_some_nothrow( - n, const_cast const&>(lazy_values)); - hpx::detail::throw_if_exceptional(lazy_values); + if (hpx::wait_some_nothrow( + n, const_cast const&>(lazy_values))) + { + hpx::detail::throw_if_exceptional(lazy_values); + } } template - void wait_some_nothrow(std::size_t n, std::array&& lazy_values) + bool wait_some_nothrow(std::size_t n, std::array&& lazy_values) { - hpx::wait_some_nothrow( + return hpx::wait_some_nothrow( n, const_cast const&>(lazy_values)); } template void wait_some(std::size_t n, std::array&& lazy_values) { - hpx::wait_some_nothrow( - n, const_cast const&>(lazy_values)); - hpx::detail::throw_if_exceptional(lazy_values); + if (hpx::wait_some_nothrow( + n, const_cast const&>(lazy_values))) + { + hpx::detail::throw_if_exceptional(lazy_values); + } } /////////////////////////////////////////////////////////////////////////// template >> - void wait_some_nothrow(std::size_t n, Iterator begin, Iterator end) + bool wait_some_nothrow(std::size_t n, Iterator begin, Iterator end) { auto values = traits::acquire_shared_state()(begin, end); auto f = detail::get_wait_some_frame(values, n); - (*f)(); + + return (*f)(); } template ()(begin, end); auto f = detail::get_wait_some_frame(values, n); - (*f)(); - hpx::detail::throw_if_exceptional(values); + + if ((*f)()) + { + hpx::detail::throw_if_exceptional(values); + } } template >> - void wait_some_n_nothrow(std::size_t n, Iterator begin, std::size_t count) + bool wait_some_n_nothrow(std::size_t n, Iterator begin, std::size_t count) { auto values = traits::acquire_shared_state()(begin, count); auto f = detail::get_wait_some_frame(values, n); - (*f)(); + + return (*f)(); } template ()(begin, count); auto f = detail::get_wait_some_frame(values, n); - (*f)(); - hpx::detail::throw_if_exceptional(values); + + if ((*f)()) + { + hpx::detail::throw_if_exceptional(values); + } } - inline void wait_some_nothrow(std::size_t n) + inline bool wait_some_nothrow(std::size_t n) { if (n != 0) { - HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::wait_some", + HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::wait_some_nothrow", "number of results to wait for is out of bounds"); } + return false; } inline void wait_some(std::size_t n) { - wait_some_nothrow(n); + if (n != 0) + { + HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::wait_some", + "number of results to wait for is out of bounds"); + } } /////////////////////////////////////////////////////////////////////////// template - void wait_some_nothrow(std::size_t n, hpx::future&& f) + bool wait_some_nothrow(std::size_t n, hpx::future&& f) { if (n != 1) { HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::wait_some", "number of results to wait for is out of bounds"); - return; + return false; } f.wait(); + + return f.has_exception(); } template void wait_some(std::size_t n, hpx::future&& f) { - hpx::wait_some_nothrow(n, HPX_MOVE(f)); - hpx::detail::throw_if_exceptional(f); + if (hpx::wait_some_nothrow(n, HPX_MOVE(f))) + { + hpx::detail::throw_if_exceptional(f); + } } template - void wait_some_nothrow(std::size_t n, hpx::shared_future&& f) + bool wait_some_nothrow(std::size_t n, hpx::shared_future&& f) { if (n != 1) { HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::wait_some", "number of results to wait for is out of bounds"); - return; + return false; } f.wait(); + + return f.has_exception(); } template void wait_some(std::size_t n, hpx::shared_future&& f) { - hpx::wait_some_nothrow(n, HPX_MOVE(f)); - hpx::detail::throw_if_exceptional(f); + if (hpx::wait_some_nothrow(n, HPX_MOVE(f))) + { + hpx::detail::throw_if_exceptional(f); + } } /////////////////////////////////////////////////////////////////////////// template - void wait_some_nothrow(std::size_t n, Ts&&... ts) + bool wait_some_nothrow(std::size_t n, Ts&&... ts) { if (n == 0) { - return; + return false; } if (n > sizeof...(Ts)) { HPX_THROW_EXCEPTION(hpx::bad_parameter, "hpx::lcos::wait_some", "number of results to wait for is out of bounds"); - return; + return false; } using result_type = @@ -562,14 +610,17 @@ namespace hpx { result_type values(traits::detail::get_shared_state(ts)...); auto f = detail::get_wait_some_frame(values, n); - (*f)(); + + return (*f)(); } template void wait_some(std::size_t n, Ts&&... ts) { - hpx::wait_some_nothrow(n, ts...); - hpx::detail::throw_if_exceptional(HPX_FORWARD(Ts, ts)...); + if (hpx::wait_some_nothrow(n, ts...)) + { + hpx::detail::throw_if_exceptional(HPX_FORWARD(Ts, ts)...); + } } } // namespace hpx diff --git a/libs/core/async_combinators/tests/unit/wait_all.cpp b/libs/core/async_combinators/tests/unit/wait_all.cpp index 9cf1a33bd761..511bac0d6406 100644 --- a/libs/core/async_combinators/tests/unit/wait_all.cpp +++ b/libs/core/async_combinators/tests/unit/wait_all.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Hartmut Kaiser +// Copyright (c) 2017-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,16 +13,9 @@ #include #include -int make_int_slowly() -{ - hpx::this_thread::sleep_for(std::chrono::milliseconds(100)); - return 42; -} - hpx::future make_future() { - hpx::packaged_task task(make_int_slowly); - return task.get_future(); + return hpx::make_ready_future_after(std::chrono::milliseconds(100), 42); } void test_wait_all() @@ -32,7 +25,7 @@ void test_wait_all() future_array.push_back(make_future()); future_array.push_back(make_future()); - hpx::wait_all_nothrow(future_array); + HPX_TEST(!hpx::wait_all_nothrow(future_array)); for (auto& f : future_array) { @@ -43,7 +36,7 @@ void test_wait_all() auto f1 = make_future(); auto f2 = make_future(); - hpx::wait_all_nothrow(f1, f2); + HPX_TEST(!hpx::wait_all_nothrow(f1, f2)); HPX_TEST(f1.is_ready()); HPX_TEST(f2.is_ready()); @@ -57,7 +50,7 @@ void test_wait_all() bool caught_exception = false; try { - hpx::wait_all_nothrow(future_array); + HPX_TEST(hpx::wait_all_nothrow(future_array)); for (auto& f : future_array) { @@ -146,7 +139,8 @@ void test_wait_all_n() future_array.push_back(make_future()); future_array.push_back(make_future()); - hpx::wait_all_n_nothrow(future_array.begin(), future_array.size()); + HPX_TEST(!hpx::wait_all_n_nothrow( + future_array.begin(), future_array.size())); for (auto& f : future_array) { @@ -162,7 +156,8 @@ void test_wait_all_n() bool caught_exception = false; try { - hpx::wait_all_n_nothrow(future_array.begin(), future_array.size()); + HPX_TEST(hpx::wait_all_n_nothrow( + future_array.begin(), future_array.size())); for (auto& f : future_array) { diff --git a/libs/core/async_combinators/tests/unit/wait_all_std_array.cpp b/libs/core/async_combinators/tests/unit/wait_all_std_array.cpp index 67e6254d884c..636bb1cce67e 100644 --- a/libs/core/async_combinators/tests/unit/wait_all_std_array.cpp +++ b/libs/core/async_combinators/tests/unit/wait_all_std_array.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Hartmut Kaiser +// Copyright (c) 2017-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,16 +13,9 @@ #include #include -int make_int_slowly() -{ - hpx::this_thread::sleep_for(std::chrono::milliseconds(100)); - return 42; -} - hpx::future make_future() { - hpx::packaged_task task(make_int_slowly); - return task.get_future(); + return hpx::make_ready_future_after(std::chrono::milliseconds(100), 42); } void test_wait_all() @@ -32,7 +25,7 @@ void test_wait_all() future_array[0] = make_future(); future_array[1] = make_future(); - hpx::wait_all_nothrow(future_array); + HPX_TEST(!hpx::wait_all_nothrow(future_array)); for (auto& f : future_array) { @@ -48,7 +41,7 @@ void test_wait_all() bool caught_exception = false; try { - hpx::wait_all_nothrow(future_array); + HPX_TEST(hpx::wait_all_nothrow(future_array)); for (auto& f : future_array) { @@ -96,7 +89,7 @@ void test_wait_all_n() future_array[0] = make_future(); future_array[1] = make_future(); - hpx::wait_all_n_nothrow(future_array.begin(), 2); + HPX_TEST(!hpx::wait_all_n_nothrow(future_array.begin(), 2)); for (auto& f : future_array) { @@ -112,7 +105,7 @@ void test_wait_all_n() bool caught_exception = false; try { - hpx::wait_all_n_nothrow(future_array.begin(), 2); + HPX_TEST(hpx::wait_all_n_nothrow(future_array.begin(), 2)); for (auto& f : future_array) { diff --git a/libs/core/async_combinators/tests/unit/wait_any.cpp b/libs/core/async_combinators/tests/unit/wait_any.cpp index 1274b9865382..c044857d0113 100644 --- a/libs/core/async_combinators/tests/unit/wait_any.cpp +++ b/libs/core/async_combinators/tests/unit/wait_any.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Hartmut Kaiser +// Copyright (c) 2017-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,16 +13,9 @@ #include #include -int make_int_slowly() -{ - hpx::this_thread::sleep_for(std::chrono::milliseconds(100)); - return 42; -} - hpx::future make_future() { - hpx::packaged_task task(make_int_slowly); - return task.get_future(); + return hpx::make_ready_future_after(std::chrono::milliseconds(100), 42); } void test_wait_any() @@ -32,7 +25,7 @@ void test_wait_any() future_array.push_back(make_future()); future_array.push_back(make_future()); - hpx::wait_any_nothrow(future_array); + HPX_TEST(!hpx::wait_any_nothrow(future_array)); int count = 0; for (auto& f : future_array) @@ -48,7 +41,7 @@ void test_wait_any() auto f1 = make_future(); auto f2 = make_future(); - hpx::wait_any_nothrow(f1, f2); + HPX_TEST(!hpx::wait_any_nothrow(f1, f2)); HPX_TEST(f1.is_ready() || f2.is_ready()); } @@ -61,7 +54,7 @@ void test_wait_any() bool caught_exception = false; try { - hpx::wait_any_nothrow(future_array); + HPX_TEST(hpx::wait_any_nothrow(future_array)); int count = 0; for (auto& f : future_array) @@ -115,7 +108,8 @@ void test_wait_any_n() future_array.push_back(make_future()); future_array.push_back(make_future()); - hpx::wait_any_n_nothrow(future_array.begin(), future_array.size()); + HPX_TEST(!hpx::wait_any_n_nothrow( + future_array.begin(), future_array.size())); int count = 0; for (auto& f : future_array) @@ -136,7 +130,8 @@ void test_wait_any_n() bool caught_exception = false; try { - hpx::wait_any_n_nothrow(future_array.begin(), future_array.size()); + HPX_TEST(hpx::wait_any_n_nothrow( + future_array.begin(), future_array.size())); int count = 0; for (auto& f : future_array) diff --git a/libs/core/async_combinators/tests/unit/wait_any_std_array.cpp b/libs/core/async_combinators/tests/unit/wait_any_std_array.cpp index 45e703eba300..4e6a44fa27a5 100644 --- a/libs/core/async_combinators/tests/unit/wait_any_std_array.cpp +++ b/libs/core/async_combinators/tests/unit/wait_any_std_array.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Hartmut Kaiser +// Copyright (c) 2017-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,16 +13,9 @@ #include #include -int make_int_slowly() -{ - hpx::this_thread::sleep_for(std::chrono::milliseconds(100)); - return 42; -} - hpx::future make_future() { - hpx::packaged_task task(make_int_slowly); - return task.get_future(); + return hpx::make_ready_future_after(std::chrono::milliseconds(100), 42); } void test_wait_any() @@ -32,7 +25,7 @@ void test_wait_any() future_array[0] = make_future(); future_array[1] = make_future(); - hpx::wait_any_nothrow(future_array); + HPX_TEST(!hpx::wait_any_nothrow(future_array)); int count = 0; for (auto& f : future_array) @@ -53,7 +46,7 @@ void test_wait_any() bool caught_exception = false; try { - hpx::wait_any_nothrow(future_array); + HPX_TEST(hpx::wait_any_nothrow(future_array)); int count = 0; for (auto& f : future_array) @@ -106,7 +99,7 @@ void test_wait_any_n() future_array[0] = make_future(); future_array[1] = make_future(); - hpx::wait_any_n_nothrow(future_array.begin(), 2); + HPX_TEST(!hpx::wait_any_n_nothrow(future_array.begin(), 2)); int count = 0; for (auto& f : future_array) @@ -127,7 +120,7 @@ void test_wait_any_n() bool caught_exception = false; try { - hpx::wait_any_n_nothrow(future_array.begin(), 2); + HPX_TEST(hpx::wait_any_n_nothrow(future_array.begin(), 2)); int count = 0; for (auto& f : future_array) diff --git a/libs/core/async_combinators/tests/unit/wait_some.cpp b/libs/core/async_combinators/tests/unit/wait_some.cpp index d94e11c52475..f4ae165db33d 100644 --- a/libs/core/async_combinators/tests/unit/wait_some.cpp +++ b/libs/core/async_combinators/tests/unit/wait_some.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Hartmut Kaiser +// Copyright (c) 2017-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,16 +13,9 @@ #include #include -int make_int_slowly() -{ - hpx::this_thread::sleep_for(std::chrono::milliseconds(100)); - return 42; -} - hpx::future make_future() { - hpx::packaged_task task(make_int_slowly); - return task.get_future(); + return hpx::make_ready_future_after(std::chrono::milliseconds(100), 42); } void test_wait_some() @@ -32,7 +25,7 @@ void test_wait_some() future_array.push_back(make_future()); future_array.push_back(make_future()); - hpx::wait_some_nothrow(1, future_array); + HPX_TEST(!hpx::wait_some_nothrow(1, future_array)); int count = 0; for (auto& f : future_array) @@ -48,7 +41,7 @@ void test_wait_some() auto f1 = make_future(); auto f2 = make_future(); - hpx::wait_some_nothrow(1, f1, f2); + HPX_TEST(!hpx::wait_some_nothrow(1, f1, f2)); HPX_TEST(f1.is_ready() || f2.is_ready()); } @@ -61,7 +54,7 @@ void test_wait_some() bool caught_exception = false; try { - hpx::wait_some_nothrow(1, future_array); + HPX_TEST(hpx::wait_some_nothrow(1, future_array)); int count = 0; for (auto& f : future_array) @@ -135,7 +128,8 @@ void test_wait_some_n() future_array.push_back(make_future()); future_array.push_back(make_future()); - hpx::wait_some_n_nothrow(1, future_array.begin(), future_array.size()); + HPX_TEST(!hpx::wait_some_n_nothrow( + 1, future_array.begin(), future_array.size())); int count = 0; for (auto& f : future_array) @@ -156,8 +150,8 @@ void test_wait_some_n() bool caught_exception = false; try { - hpx::wait_some_n_nothrow( - 1, future_array.begin(), future_array.size()); + HPX_TEST(hpx::wait_some_n_nothrow( + 1, future_array.begin(), future_array.size())); int count = 0; for (auto& f : future_array) diff --git a/libs/core/async_combinators/tests/unit/wait_some_std_array.cpp b/libs/core/async_combinators/tests/unit/wait_some_std_array.cpp index b091d2a529d5..07ed066bb97a 100644 --- a/libs/core/async_combinators/tests/unit/wait_some_std_array.cpp +++ b/libs/core/async_combinators/tests/unit/wait_some_std_array.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Hartmut Kaiser +// Copyright (c) 2017-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,16 +13,9 @@ #include #include -int make_int_slowly() -{ - hpx::this_thread::sleep_for(std::chrono::milliseconds(100)); - return 42; -} - hpx::future make_future() { - hpx::packaged_task task(make_int_slowly); - return task.get_future(); + return hpx::make_ready_future_after(std::chrono::milliseconds(100), 42); } void test_wait_some() @@ -32,7 +25,7 @@ void test_wait_some() future_array[0] = make_future(); future_array[1] = make_future(); - hpx::wait_some_nothrow(1, future_array); + HPX_TEST(!hpx::wait_some_nothrow(1, future_array)); int count = 0; for (auto& f : future_array) @@ -53,7 +46,7 @@ void test_wait_some() bool caught_exception = false; try { - hpx::wait_some_nothrow(1, future_array); + HPX_TEST(hpx::wait_some_nothrow(1, future_array)); int count = 0; for (auto& f : future_array) @@ -106,7 +99,7 @@ void test_wait_some_n() future_array[0] = make_future(); future_array[1] = make_future(); - hpx::wait_some_n_nothrow(1, future_array.begin(), 2); + HPX_TEST(!hpx::wait_some_n_nothrow(1, future_array.begin(), 2)); int count = 0; for (auto& f : future_array) @@ -127,7 +120,7 @@ void test_wait_some_n() bool caught_exception = false; try { - hpx::wait_some_n_nothrow(1, future_array.begin(), 2); + HPX_TEST(hpx::wait_some_n_nothrow(1, future_array.begin(), 2)); int count = 0; for (auto& f : future_array) diff --git a/libs/core/futures/tests/regressions/exception_from_continuation_1613.cpp b/libs/core/futures/tests/regressions/exception_from_continuation_1613.cpp index 3b73f82edf66..60a42c55a7e7 100644 --- a/libs/core/futures/tests/regressions/exception_from_continuation_1613.cpp +++ b/libs/core/futures/tests/regressions/exception_from_continuation_1613.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2021 Hartmut Kaiser +// Copyright (c) 2015-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -61,7 +61,7 @@ void test_exception_from_continuation2() // make futures ready in backwards sequence hpx::apply([&p]() { p.set_value(); }); - hpx::wait_all_nothrow(results); + HPX_TEST(hpx::wait_all_nothrow(results)); HPX_TEST_EQ(recursion_level.load(), NUM_FUTURES); HPX_TEST_EQ(exceptions_thrown.load(), std::size_t(1)); diff --git a/libs/full/compute/include/hpx/compute/host/numa_allocator.hpp b/libs/full/compute/include/hpx/compute/host/numa_allocator.hpp index 0c994e03f86f..6567f9dc6f04 100644 --- a/libs/full/compute/include/hpx/compute/host/numa_allocator.hpp +++ b/libs/full/compute/include/hpx/compute/host/numa_allocator.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2015 Thomas Heller -// Copyright (c) 2015-2016 Hartmut Kaiser +// Copyright (c) 2015-2022 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -130,11 +130,13 @@ namespace hpx { namespace parallel { namespace util { #endif })); } - hpx::wait_all_nothrow(first_touch); - for (auto&& f : first_touch) + if (hpx::wait_all_nothrow(first_touch)) { - f.get(); // rethrow exceptions + for (auto&& f : first_touch) + { + f.get(); // rethrow exceptions + } } // return the overall memory block diff --git a/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed.cpp b/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed.cpp index 86374ac91ee4..7810e6be5073 100644 --- a/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed.cpp +++ b/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2022 Hartmut Kaiser // Copyright (c) 2018-2019 Adrian Serio // Copyright (c) 2019-2020 Nikunj Gupta // @@ -131,7 +131,7 @@ int hpx_main(hpx::program_options::variables_map& vm) std::rotate(locales.begin(), locales.begin() + 1, locales.end()); } - hpx::wait_all_nothrow(tasks); + HPX_TEST(!hpx::wait_all_nothrow(tasks)); double elapsed = t.elapsed(); diff --git a/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed_validate.cpp b/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed_validate.cpp index 68042a6f13b1..96de5f8be553 100644 --- a/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed_validate.cpp +++ b/libs/full/resiliency_distributed/tests/performance/replay/async_replay_distributed_validate.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2022 Hartmut Kaiser // Copyright (c) 2018-2019 Adrian Serio // Copyright (c) 2019-2020 Nikunj Gupta // @@ -124,7 +124,7 @@ int hpx_main(hpx::program_options::variables_map& vm) std::rotate(locales.begin(), locales.begin() + 1, locales.end()); } - hpx::wait_all_nothrow(tasks); + HPX_TEST(!hpx::wait_all_nothrow(tasks)); double elapsed = t.elapsed(); std::cout << "Replay Validate: " << elapsed << std::endl;