-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
recovered make_shared_context/capture and marked them [[deprecated]]
- Loading branch information
Showing
8 changed files
with
329 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#ifndef BOOST_LEAF_CAPTURE_HPP_INCLUDED | ||
#define BOOST_LEAF_CAPTURE_HPP_INCLUDED | ||
|
||
// Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc. | ||
|
||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/leaf/config.hpp> | ||
#include <boost/leaf/handle_errors.hpp> | ||
|
||
#if BOOST_LEAF_CFG_CAPTURE | ||
|
||
namespace boost { namespace leaf { | ||
|
||
namespace leaf_detail | ||
{ | ||
template <class R, bool IsResult = is_result_type<R>::value> | ||
struct is_result_tag; | ||
|
||
template <class R> | ||
struct is_result_tag<R, false> | ||
{ | ||
}; | ||
|
||
template <class R> | ||
struct is_result_tag<R, true> | ||
{ | ||
}; | ||
} | ||
|
||
#ifdef BOOST_LEAF_NO_EXCEPTIONS | ||
|
||
namespace leaf_detail | ||
{ | ||
template <class R, class F, class... A> | ||
inline | ||
decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) | ||
capture_impl(is_result_tag<R, false>, F && f, A... a) noexcept | ||
{ | ||
return std::forward<F>(f)(std::forward<A>(a)...); | ||
} | ||
|
||
template <class R, class Future> | ||
inline | ||
decltype(std::declval<Future>().get()) | ||
future_get_impl(is_result_tag<R, false>, Future & fut) noexcept | ||
{ | ||
return fut.get(); | ||
} | ||
} | ||
|
||
#else | ||
|
||
namespace leaf_detail | ||
{ | ||
// Not defined, no longer supported. Please use try_capture_all instead of make_shared_context/capture. | ||
template <class R, class F, class... A> | ||
decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) | ||
capture_impl(is_result_tag<R, false>, F && f, A... a); | ||
|
||
// Not defined, no longer supported. Please use try_capture_all instead of make_shared_context/capture. | ||
template <class R, class Future> | ||
decltype(std::declval<Future>().get()) | ||
future_get_impl(is_result_tag<R, false>, Future & fut ); | ||
} | ||
|
||
#endif | ||
|
||
namespace leaf_detail | ||
{ | ||
template <class R, class F, class... A> | ||
inline | ||
decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) | ||
capture_impl(is_result_tag<R, true>, F && f, A... a) noexcept | ||
{ | ||
return try_capture_all( | ||
[&] | ||
{ | ||
return std::forward<F>(f)(std::forward<A>(a)...); | ||
} ); | ||
} | ||
|
||
template <class R, class Future> | ||
inline | ||
decltype(std::declval<Future>().get()) | ||
future_get_impl(is_result_tag<R, true>, Future & fut) noexcept | ||
{ | ||
if( auto r = fut.get() ) | ||
return r; | ||
else | ||
{ | ||
r.unload(); | ||
return r; | ||
} | ||
} | ||
} | ||
|
||
template <class F, class... A> | ||
inline | ||
decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) | ||
capture(context_ptr &&, F && f, A... a) | ||
{ | ||
using namespace leaf_detail; | ||
return capture_impl(is_result_tag<decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))>(), std::forward<F>(f), std::forward<A>(a)...); | ||
} | ||
|
||
template <class Future> | ||
inline | ||
decltype(std::declval<Future>().get()) | ||
future_get( Future & fut ) | ||
{ | ||
using namespace leaf_detail; | ||
return future_get_impl(is_result_tag<decltype(std::declval<Future>().get())>(), fut); | ||
} | ||
|
||
} } | ||
|
||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
// Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc. | ||
|
||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/leaf/config.hpp> | ||
|
||
#if defined(BOOST_LEAF_NO_THREADS) || !BOOST_LEAF_CFG_CAPTURE | ||
|
||
#include <iostream> | ||
|
||
int main() | ||
{ | ||
std::cout << "Unit test not applicable." << std::endl; | ||
return 0; | ||
} | ||
|
||
#else | ||
|
||
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER | ||
# include "leaf.hpp" | ||
#else | ||
# include <boost/leaf/capture.hpp> | ||
# include <boost/leaf/result.hpp> | ||
# include <boost/leaf/handle_errors.hpp> | ||
# include <boost/leaf/on_error.hpp> | ||
#endif | ||
|
||
#include "lightweight_test.hpp" | ||
#include <vector> | ||
#include <future> | ||
#include <iterator> | ||
#include <algorithm> | ||
|
||
namespace leaf = boost::leaf; | ||
|
||
template <int> struct info { int value; }; | ||
|
||
struct fut_info | ||
{ | ||
int a; | ||
int b; | ||
int result; | ||
std::future<leaf::result<int>> fut; | ||
}; | ||
|
||
template <class ErrorHandlers, class F> | ||
std::vector<fut_info> launch_tasks( int task_count, F f ) | ||
{ | ||
BOOST_LEAF_ASSERT(task_count>0); | ||
std::vector<fut_info> fut; | ||
std::generate_n( std::back_inserter(fut), task_count, | ||
[=] | ||
{ | ||
int const a = rand(); | ||
int const b = rand(); | ||
int const res = (rand()%10) - 5; | ||
return fut_info { a, b, res, std::async( std::launch::async, | ||
[=] | ||
{ | ||
return leaf::capture(leaf::make_shared_context<ErrorHandlers>(), f, a, b, res); | ||
} ) }; | ||
} ); | ||
return fut; | ||
} | ||
|
||
int main() | ||
{ | ||
int received_a, received_b; | ||
auto error_handlers = std::make_tuple( | ||
[&received_a, &received_b]( info<1> const & x1, info<2> const & x2, info<4> const & ) | ||
{ | ||
received_a = x1.value; | ||
received_b = x2.value; | ||
return -1; | ||
}, | ||
[] | ||
{ | ||
return -2; | ||
} ); | ||
|
||
{ | ||
std::vector<fut_info> fut = launch_tasks<decltype(error_handlers)>( | ||
100, | ||
[]( int a, int b, int res ) -> leaf::result<int> | ||
{ | ||
if( res >= 0 ) | ||
return res; | ||
else | ||
return leaf::new_error( info<1>{a}, info<2>{b}, info<3>{} ); | ||
} ); | ||
|
||
for( auto & f : fut ) | ||
{ | ||
f.fut.wait(); | ||
int r = leaf::try_handle_all( | ||
[&] | ||
{ | ||
auto load = leaf::on_error( info<4>{} ); | ||
|
||
// Calling future_get is required in order to make the on_error (above) work. | ||
return leaf::future_get(f.fut); | ||
}, | ||
error_handlers ); | ||
if( f.result>=0 ) | ||
BOOST_TEST_EQ(r, f.result); | ||
else | ||
{ | ||
BOOST_TEST_EQ(r, -1); | ||
BOOST_TEST_EQ(f.a, received_a); | ||
BOOST_TEST_EQ(f.b, received_b); | ||
} | ||
} | ||
} | ||
|
||
{ | ||
std::vector<fut_info> fut = launch_tasks<decltype(error_handlers)>( | ||
100, | ||
[]( int a, int b, int res ) -> leaf::result<int> | ||
{ | ||
if( res >= 0 ) | ||
return res; | ||
else | ||
return leaf::new_error( info<1>{a}, info<2>{b}, info<3>{} ); | ||
} ); | ||
|
||
for( auto & f : fut ) | ||
{ | ||
f.fut.wait(); | ||
int r = leaf::try_handle_all( | ||
[&] | ||
{ | ||
auto load = leaf::on_error( info<4>{} ); | ||
|
||
return leaf::try_handle_some( | ||
[&] | ||
{ | ||
// Not calling future_get, a on_error in this scope won't work correctly. | ||
// This is to verify that the on_error in the outer scope (above) works. | ||
return f.fut.get(); | ||
}, | ||
[]( leaf::error_info const & err ) | ||
{ | ||
return err.error(); | ||
} ); | ||
}, | ||
error_handlers ); | ||
if( f.result>=0 ) | ||
BOOST_TEST_EQ(r, f.result); | ||
else | ||
{ | ||
BOOST_TEST_EQ(r, -1); | ||
BOOST_TEST_EQ(f.a, received_a); | ||
BOOST_TEST_EQ(f.b, received_b); | ||
} | ||
} | ||
} | ||
|
||
return boost::report_errors(); | ||
} | ||
|
||
#endif |