@@ -6,7 +6,13 @@ | |||
#include "core/stream.h" | |||
#include "core/task.h" | |||
#include "core/future.inl" | |||
#include "core/misc.inl" | |||
#include "core/result.inl" | |||
#include "core/stream.inl" | |||
#include "core/future/map.inl" | |||
#include "core/future/lazy.inl" | |||
#include "core/future/and_then.inl" | |||
#ifdef asyncpp_timing | |||
#include "core/future/timeout.inl" | |||
#endif |
@@ -2,6 +2,7 @@ | |||
#include <type_traits> | |||
#include "misc.h" | |||
#include "result.h" | |||
#include "future.pre.h" | |||
@@ -28,19 +29,17 @@ namespace asyncpp | |||
/** | |||
* @brief Transform the result of this future. | |||
*/ | |||
template<typename X_lambda> | |||
inline auto map(X_lambda&& p_lambda) const &; | |||
/** | |||
* @brief Transform the result of this future. | |||
*/ | |||
template<typename X_lambda> | |||
template< | |||
chaining_mode X_mode = copy, | |||
typename X_lambda> | |||
inline auto map(X_lambda&& p_lambda) &; | |||
/** | |||
* @brief Transform the result of this future. | |||
*/ | |||
template<typename X_lambda> | |||
template< | |||
chaining_mode X_mode = move, | |||
typename X_lambda> | |||
inline auto map(X_lambda&& p_lambda) &&; | |||
public: | |||
@@ -48,21 +47,18 @@ namespace asyncpp | |||
* @brief Execute the given lambda after the future is finished and | |||
* wait for the future returned by the lambda. | |||
*/ | |||
template<typename X_lambda> | |||
inline auto and_then(X_lambda&& p_lambda) const &; | |||
/** | |||
* @brief Execute the given lambda after the future is finished and | |||
* wait for the future returned by the lambda. | |||
*/ | |||
template<typename X_lambda> | |||
template< | |||
chaining_mode X_mode = copy, | |||
typename X_lambda> | |||
inline auto and_then(X_lambda&& p_lambda) &; | |||
/** | |||
* @brief Execute the given lambda after the future is finished and | |||
* wait for the future returned by the lambda. | |||
*/ | |||
template<typename X_lambda> | |||
template< | |||
chaining_mode X_mode = move, | |||
typename X_lambda> | |||
inline auto and_then(X_lambda&& p_lambda) &&; | |||
#ifdef asyncpp_timing | |||
@@ -72,15 +68,10 @@ namespace asyncpp | |||
* | |||
* This method is only enabled if timer.h is included before. | |||
*/ | |||
template<typename X_base, typename X_ratio> | |||
inline auto timeout(const duration<X_base, X_ratio>& p_timeout) const &; | |||
/** | |||
* @brief Throw an execption if the timeout has passed. | |||
* | |||
* This method is only enabled if timer.h is included before. | |||
*/ | |||
template<typename X_base, typename X_ratio> | |||
template< | |||
chaining_mode X_mode = copy, | |||
typename X_base, | |||
typename X_ratio> | |||
inline auto timeout(const duration<X_base, X_ratio>& p_timeout) &; | |||
/** | |||
@@ -88,7 +79,10 @@ namespace asyncpp | |||
* | |||
* This method is only enabled if timer.h is included before. | |||
*/ | |||
template<typename X_base, typename X_ratio> | |||
template< | |||
chaining_mode X_mode = move, | |||
typename X_base, | |||
typename X_ratio> | |||
inline auto timeout(const duration<X_base, X_ratio>& p_timeout) &&; | |||
#endif | |||
}; | |||
@@ -1,186 +0,0 @@ | |||
#pragma once | |||
#include "future.h" | |||
#include "future/map.inl" | |||
#include "future/lazy.inl" | |||
#include "future/and_then.inl" | |||
#ifdef asyncpp_timing | |||
#include <asyncpp/timing/timeout.inl> | |||
#endif | |||
namespace asyncpp | |||
{ | |||
/* base_future::map */ | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::map(X_lambda&& p_lambda) const & | |||
{ | |||
using lambda_type = X_lambda; | |||
using map_type = __future::map_impl<derived_type, lambda_type>; | |||
auto& self = static_cast<derived_type const &>(*this); | |||
return map_type( | |||
std::forward<derived_type const>(self), | |||
std::forward<X_lambda>(p_lambda)); | |||
} | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::map(X_lambda&& p_lambda) & | |||
{ | |||
using lambda_type = X_lambda; | |||
using map_type = __future::map_impl<derived_type&, lambda_type>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
return map_type( | |||
std::forward<derived_type &>(self), | |||
std::forward<X_lambda>(p_lambda)); | |||
} | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::map(X_lambda&& p_lambda) && | |||
{ | |||
using lambda_type = X_lambda; | |||
using map_type = __future::map_impl<derived_type, lambda_type>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
return map_type( | |||
std::forward<derived_type &&>(self), | |||
std::forward<X_lambda>(p_lambda)); | |||
} | |||
/* base_future::and_then */ | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::and_then(X_lambda&& p_lambda) const & | |||
{ | |||
using lambda_type = X_lambda; | |||
using and_then_type = __future::and_then_impl<derived_type, lambda_type>; | |||
auto& self = static_cast<derived_type const &>(*this); | |||
return and_then_type( | |||
std::forward<derived_type const>(self), | |||
std::forward<X_lambda>(p_lambda)); | |||
} | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::and_then(X_lambda&& p_lambda) & | |||
{ | |||
using lambda_type = X_lambda; | |||
using and_then_type = __future::and_then_impl<derived_type&, lambda_type>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
return and_then_type( | |||
std::forward<derived_type &>(self), | |||
std::forward<X_lambda>(p_lambda)); | |||
} | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::and_then(X_lambda&& p_lambda) && | |||
{ | |||
using lambda_type = X_lambda; | |||
using and_then_type = __future::and_then_impl<derived_type, lambda_type>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
return and_then_type( | |||
std::forward<derived_type &&>(self), | |||
std::forward<X_lambda>(p_lambda)); | |||
} | |||
/* base_future::timeout */ | |||
#ifdef asyncpp_timing | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_base, | |||
typename X_ratio> | |||
auto base_future<T_value, T_derived> | |||
::timeout(const duration<X_base, X_ratio>& p_timeout) const & | |||
{ | |||
using timeout_type = timing::timeout<derived_type>; | |||
auto& self = static_cast<derived_type const &>(*this); | |||
return timeout_type( | |||
std::forward<derived_type const>(self), | |||
p_timeout); | |||
} | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_base, | |||
typename X_ratio> | |||
auto base_future<T_value, T_derived> | |||
::timeout(const duration<X_base, X_ratio>& p_timeout) & | |||
{ | |||
using timeout_type = timing::timeout<derived_type&>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
return timeout_type( | |||
std::forward<derived_type &>(self), | |||
p_timeout); | |||
} | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
typename X_base, | |||
typename X_ratio> | |||
auto base_future<T_value, T_derived> | |||
::timeout(const duration<X_base, X_ratio>& p_timeout) && | |||
{ | |||
using timeout_type = timing::timeout<derived_type>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
return timeout_type( | |||
std::forward<derived_type &&>(self), | |||
p_timeout); | |||
} | |||
#endif | |||
} |
@@ -10,10 +10,10 @@ namespace __future { | |||
template< | |||
typename T_future, | |||
typename T_lambda> | |||
struct and_then_impl final : | |||
struct and_then_future final : | |||
public base_future< | |||
decltype(std::declval<T_lambda>()(std::declval<typename std::decay_t<T_future>::value_type>())), | |||
and_then_impl<T_future, T_lambda> | |||
and_then_future<T_future, T_lambda> | |||
> | |||
{ | |||
public: | |||
@@ -23,7 +23,7 @@ namespace __future { | |||
using second_future_type = decltype(std::declval<lambda_type>()(std::declval<first_value_type>())); | |||
using second_future_type_ptr = std::unique_ptr<second_future_type>; | |||
using value_type = typename second_future_type::value_type; | |||
using this_type = and_then_impl<value_type, lambda_type>; | |||
using this_type = and_then_future<value_type, lambda_type>; | |||
using base_future_type = base_future<value_type, this_type>; | |||
using result_type = typename base_future_type::result_type; | |||
@@ -39,10 +39,13 @@ namespace __future { | |||
template< | |||
typename X_future, | |||
typename X_lambda> | |||
inline and_then_impl( | |||
inline and_then_future( | |||
X_future&& p_outer, | |||
X_lambda&& p_lambda); | |||
inline and_then_future(and_then_future &&) = default; | |||
inline and_then_future(and_then_future const &) = default; | |||
public: /* future */ | |||
/** | |||
* @brief Poll the result from the future. | |||
@@ -1,11 +1,12 @@ | |||
#pragma once | |||
#include "map.h" | |||
#include "and_then.h" | |||
#include "../future.h" | |||
namespace asyncpp { | |||
namespace __future { | |||
/* and_then_impl */ | |||
/* and_then_future */ | |||
template< | |||
typename T_future, | |||
@@ -13,8 +14,8 @@ namespace __future { | |||
template< | |||
typename X_future, | |||
typename X_lambda> | |||
and_then_impl<T_future, T_lambda> | |||
::and_then_impl( | |||
and_then_future<T_future, T_lambda> | |||
::and_then_future( | |||
X_future&& p_first, | |||
X_lambda&& p_lambda) | |||
: _first (std::forward<X_future>(p_first)) | |||
@@ -24,8 +25,8 @@ namespace __future { | |||
template< | |||
typename T_future, | |||
typename T_lambda> | |||
typename and_then_impl<T_future, T_lambda>::result_type | |||
and_then_impl<T_future, T_lambda> | |||
typename and_then_future<T_future, T_lambda>::result_type | |||
and_then_future<T_future, T_lambda> | |||
::poll() | |||
{ | |||
while (true) | |||
@@ -45,4 +46,61 @@ namespace __future { | |||
} | |||
} | |||
/* and_then_impl */ | |||
template< | |||
chaining_mode X_mode, | |||
typename X_self, | |||
typename X_lambda> | |||
auto and_then_impl(X_self&& p_self, X_lambda&& p_lambda) | |||
{ | |||
using lambda_type = X_lambda; | |||
using self_type = X_self; | |||
using derived_type = typename std::decay_t<self_type>::derived_type; | |||
using derived_storage_type = storage_type_t<X_mode, derived_type>; | |||
using derived_ref_type = std::conditional_t< | |||
std::is_const_v<std::remove_reference_t<self_type>>, | |||
derived_type const &, | |||
derived_type &>; | |||
using derived_forward_type = forward_type_t<X_mode, derived_ref_type>; | |||
using and_then_future_type = __future::and_then_future<derived_storage_type, lambda_type>; | |||
static_assert( | |||
X_mode != ref || !std::is_rvalue_reference_v<self_type>, | |||
"Can not store rvalue reference as lvalue reference!"); | |||
auto& self = static_cast<derived_ref_type>(p_self); | |||
return and_then_future_type( | |||
std::forward<derived_forward_type>(self), | |||
std::forward<X_lambda> (p_lambda)); | |||
} | |||
} } | |||
namespace asyncpp | |||
{ | |||
/* future_base::and_then */ | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
chaining_mode X_mode, | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::and_then(X_lambda&& p_lambda) & | |||
{ return __future::and_then_impl<X_mode>(*this, std::forward<X_lambda>(p_lambda)); } | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
chaining_mode X_mode, | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::and_then(X_lambda&& p_lambda) && | |||
{ return __future::and_then_impl<X_mode>(std::move(*this), std::forward<X_lambda>(p_lambda)); } | |||
} |
@@ -9,16 +9,16 @@ namespace asyncpp | |||
{ | |||
template<typename T_lambda> | |||
struct lazy_impl final : | |||
struct lazy_future final : | |||
public base_future< | |||
decltype(std::declval<T_lambda>()()), | |||
lazy_impl<T_lambda> | |||
lazy_future<T_lambda> | |||
> | |||
{ | |||
public: | |||
using lambda_type = T_lambda; | |||
using value_type = decltype(std::declval<lambda_type>()()); | |||
using this_type = lazy_impl<lambda_type>; | |||
using this_type = lazy_future<lambda_type>; | |||
using base_future_type = base_future<value_type, this_type>; | |||
using result_type = typename base_future_type::result_type; | |||
@@ -30,9 +30,12 @@ namespace asyncpp | |||
* @brief Constructor. | |||
*/ | |||
template<typename X_lambda> | |||
inline lazy_impl( | |||
inline lazy_future( | |||
X_lambda&& p_lambda); | |||
inline lazy_future(lazy_future &&) = default; | |||
inline lazy_future(lazy_future const &) = default; | |||
public: /* future */ | |||
/** | |||
* @brief Poll the result from the future. | |||
@@ -8,18 +8,18 @@ namespace asyncpp | |||
namespace __future | |||
{ | |||
/* lazy_impl */ | |||
/* lazy_future */ | |||
template<typename T_lambda> | |||
template<typename X_lambda> | |||
lazy_impl<T_lambda>::lazy_impl( | |||
lazy_future<T_lambda>::lazy_future( | |||
X_lambda&& p_lambda) | |||
: _lambda(std::forward<X_lambda>(p_lambda)) | |||
{ } | |||
template<typename T_lambda> | |||
template<typename X> | |||
inline auto lazy_impl<T_lambda> | |||
inline auto lazy_future<T_lambda> | |||
::poll() | |||
-> std::enable_if_t< | |||
std::is_void_v<X>, | |||
@@ -31,7 +31,7 @@ namespace asyncpp | |||
template<typename T_lambda> | |||
template<typename X> | |||
inline auto lazy_impl<T_lambda> | |||
inline auto lazy_future<T_lambda> | |||
::poll() | |||
-> std::enable_if_t< | |||
!std::is_void_v<X>, | |||
@@ -45,7 +45,7 @@ namespace asyncpp | |||
inline auto lazy(X_lambda&& p_lambda) | |||
{ | |||
using lambda_type = X_lambda; | |||
using lazy_type = __future::lazy_impl<lambda_type>; | |||
using lazy_type = __future::lazy_future<lambda_type>; | |||
return lazy_type(std::forward<X_lambda>(p_lambda)); | |||
} | |||
@@ -8,10 +8,10 @@ namespace __future { | |||
template< | |||
typename T_future, | |||
typename T_lambda> | |||
struct map_impl final : | |||
struct map_future final : | |||
public base_future< | |||
typename std::decay_t<T_future>::value_type, | |||
map_impl<T_future, T_lambda> | |||
map_future<T_future, T_lambda> | |||
> | |||
{ | |||
public: | |||
@@ -19,7 +19,7 @@ namespace __future { | |||
using lambda_type = T_lambda; | |||
using future_value_type = typename std::decay_t<future_type>::value_type; | |||
using value_type = decltype(std::declval<lambda_type>()(std::declval<future_value_type>())); | |||
using this_type = map_impl<future_type, lambda_type>; | |||
using this_type = map_future<future_type, lambda_type>; | |||
using base_future_type = base_future<value_type, this_type>; | |||
using result_type = typename base_future_type::result_type; | |||
@@ -34,10 +34,13 @@ namespace __future { | |||
template< | |||
typename X_future, | |||
typename X_lambda> | |||
inline map_impl( | |||
inline map_future( | |||
X_future&& p_future, | |||
X_lambda&& p_lambda); | |||
inline map_future(map_future &&) = default; | |||
inline map_future(map_future const &) = default; | |||
public: /* future */ | |||
/** | |||
* @brief Poll the result from the future. | |||
@@ -5,7 +5,7 @@ | |||
namespace asyncpp { | |||
namespace __future { | |||
/* map_impl */ | |||
/* map_future */ | |||
template< | |||
typename T_future, | |||
@@ -13,8 +13,8 @@ namespace __future { | |||
template< | |||
typename X_future, | |||
typename X_lambda> | |||
map_impl<T_future, T_lambda> | |||
::map_impl( | |||
map_future<T_future, T_lambda> | |||
::map_future( | |||
X_future&& p_future, | |||
X_lambda&& p_lambda) | |||
: _future(std::forward<X_future>(p_future)) | |||
@@ -24,8 +24,8 @@ namespace __future { | |||
template< | |||
typename T_future, | |||
typename T_lambda> | |||
typename map_impl<T_future, T_lambda>::result_type | |||
map_impl<T_future, T_lambda> | |||
typename map_future<T_future, T_lambda>::result_type | |||
map_future<T_future, T_lambda> | |||
::poll() | |||
{ | |||
auto r = _future.poll(); | |||
@@ -34,4 +34,61 @@ namespace __future { | |||
: result_type::not_ready(); | |||
} | |||
/* map_impl */ | |||
template< | |||
chaining_mode X_mode, | |||
typename X_self, | |||
typename X_lambda> | |||
auto map_impl(X_self&& p_self, X_lambda&& p_lambda) | |||
{ | |||
using lambda_type = X_lambda; | |||
using self_type = X_self; | |||
using derived_type = typename std::decay_t<self_type>::derived_type; | |||
using derived_storage_type = storage_type_t<X_mode, derived_type>; | |||
using derived_ref_type = std::conditional_t< | |||
std::is_const_v<std::remove_reference_t<self_type>>, | |||
derived_type const &, | |||
derived_type &>; | |||
using derived_forward_type = forward_type_t<X_mode, derived_ref_type>; | |||
using map_future_type = __future::map_future<derived_storage_type, lambda_type>; | |||
static_assert( | |||
X_mode != ref || !std::is_rvalue_reference_v<self_type>, | |||
"Can not store rvalue reference as lvalue reference!"); | |||
auto& self = static_cast<derived_ref_type>(p_self); | |||
return map_future_type( | |||
std::forward<derived_forward_type>(self), | |||
std::forward<X_lambda> (p_lambda)); | |||
} | |||
} } | |||
namespace asyncpp | |||
{ | |||
/* future_base::map */ | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
chaining_mode X_mode, | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::map(X_lambda&& p_lambda) & | |||
{ return __future::map_impl<X_mode>(*this, std::forward<X_lambda>(p_lambda)); } | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
chaining_mode X_mode, | |||
typename X_lambda> | |||
auto base_future<T_value, T_derived> | |||
::map(X_lambda&& p_lambda) && | |||
{ return __future::map_impl<X_mode>(std::move(*this), std::forward<X_lambda>(p_lambda)); } | |||
} |
@@ -0,0 +1,63 @@ | |||
#pragma once | |||
#include "../future.h" | |||
namespace asyncpp { | |||
namespace __future { | |||
template< | |||
chaining_mode X_mode, | |||
typename X_self, | |||
typename X_base, | |||
typename X_ratio> | |||
auto helper_timeout( | |||
X_self&& p_self, | |||
const duration<X_base, X_ratio>& p_timeout) | |||
{ | |||
using self_type = X_self; | |||
using derived_type = typename std::decay_t<self_type>::derived_type; | |||
using derived_storage_type = storage_type_t<X_mode, derived_type>; | |||
using derived_ref_type = std::conditional_t< | |||
std::is_const_v<std::remove_reference_t<self_type>>, | |||
derived_type const &, | |||
derived_type &>; | |||
using derived_forward_type = forward_type_t<X_mode, derived_ref_type>; | |||
using timeout_type = timing::timeout<derived_storage_type>; | |||
auto& self = static_cast<derived_ref_type>(p_self); | |||
return timeout_type( | |||
std::forward<derived_forward_type>(self), | |||
p_timeout); | |||
} | |||
} } | |||
namespace asyncpp | |||
{ | |||
/* future_base::timeout */ | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
chaining_mode X_mode, | |||
typename X_base, | |||
typename X_ratio> | |||
auto base_future<T_value, T_derived> | |||
::timeout(const duration<X_base, X_ratio>& p_timeout) & | |||
{ return __future::helper_timeout<X_mode>(*this, p_timeout); } | |||
template< | |||
typename T_value, | |||
typename T_derived> | |||
template< | |||
chaining_mode X_mode, | |||
typename X_base, | |||
typename X_ratio> | |||
auto base_future<T_value, T_derived> | |||
::timeout(const duration<X_base, X_ratio>& p_timeout) && | |||
{ return __future::helper_timeout<X_mode>(std::move(*this), p_timeout); } | |||
} |
@@ -1,28 +1,7 @@ | |||
#pragma once | |||
#pragma | |||
#include <chrono> | |||
#include "misc/chaining.h" | |||
#include "misc/timing.h" | |||
namespace asyncpp | |||
{ | |||
using clock = std::chrono::steady_clock; | |||
using time_point = clock::time_point; | |||
template<typename T_base, typename T_ratio> | |||
using duration = std::chrono::duration<T_base ,T_ratio>; | |||
/** | |||
* @brief Get the current time point. | |||
*/ | |||
inline time_point now(); | |||
/** | |||
* @brief Returns the lowest of the two passed deadlines (if not null) | |||
* or nullptr if no deadline was passed. | |||
*/ | |||
inline const time_point * merge_deadlines( | |||
const time_point * p_deadline_0, | |||
const time_point * p_deadline_1); | |||
} | |||
#include "misc/chaining.inl" | |||
#include "misc/timing.inl" |
@@ -0,0 +1,39 @@ | |||
#pragma once | |||
namespace asyncpp | |||
{ | |||
enum chaining_mode | |||
{ | |||
move, | |||
copy, | |||
ref, | |||
}; | |||
/** | |||
* @brief Get the storage type of the passed type for the passed mode. | |||
* | |||
* move: T | |||
* copy: T | |||
* ref T & | |||
*/ | |||
template<chaining_mode X_mode, typename X_type, typename = void> | |||
struct storage_type; | |||
/** | |||
* @brief Get the forward type of the passed type for the passed mode. | |||
* | |||
* move: T && | |||
* copy: T const & | |||
* ref T & | |||
*/ | |||
template<chaining_mode X_mode, typename X_type, typename = void> | |||
struct forward_type; | |||
template<chaining_mode X_mode, typename X_type> | |||
using storage_type_t = typename storage_type<X_mode, X_type>::type; | |||
template<chaining_mode X_mode, typename X_type> | |||
using forward_type_t = typename forward_type<X_mode, X_type>::type; | |||
} |
@@ -0,0 +1,34 @@ | |||
#pragma once | |||
namespace asyncpp | |||
{ | |||
/* storage_type */ | |||
template<typename X_type> | |||
struct storage_type<move, X_type, void> | |||
{ using type = X_type; }; | |||
template<typename X_type> | |||
struct storage_type<copy, X_type, void> | |||
{ using type = X_type; }; | |||
template<typename X_type> | |||
struct storage_type<ref, X_type, void> | |||
{ using type = X_type&; }; | |||
/* forward_type */ | |||
template<typename X_type> | |||
struct forward_type<move, X_type, void> | |||
{ using type = std::decay_t<X_type> &&; }; | |||
template<typename X_type> | |||
struct forward_type<copy, X_type, void> | |||
{ using type = std::decay_t<X_type> const &; }; | |||
template<typename X_type> | |||
struct forward_type<ref, X_type, void> | |||
{ using type = std::remove_reference_t<X_type> &; }; | |||
} |
@@ -0,0 +1,28 @@ | |||
#pragma once | |||
#include <chrono> | |||
namespace asyncpp | |||
{ | |||
using clock = std::chrono::steady_clock; | |||
using time_point = clock::time_point; | |||
template<typename T_base, typename T_ratio> | |||
using duration = std::chrono::duration<T_base ,T_ratio>; | |||
/** | |||
* @brief Get the current time point. | |||
*/ | |||
inline time_point now(); | |||
/** | |||
* @brief Returns the lowest of the two passed deadlines (if not null) | |||
* or nullptr if no deadline was passed. | |||
*/ | |||
inline const time_point * merge_deadlines( | |||
const time_point * p_deadline_0, | |||
const time_point * p_deadline_1); | |||
} |
@@ -1,11 +1,11 @@ | |||
#pragma once | |||
#include "misc.h" | |||
#include "timing.h" | |||
namespace asyncpp | |||
{ | |||
#ifndef __asyncpp_has_impl_timer_now | |||
#ifndef __asyncpp_has_impl_timer_now | |||
time_point now() | |||
{ return clock::now(); } | |||
#endif |
@@ -80,7 +80,7 @@ namespace asyncpp | |||
::map(X_lambda&& p_lambda) const & | |||
{ | |||
using lambda_type = X_lambda; | |||
using map_type = __stream::map_impl<derived_type, lambda_type>; | |||
using map_type = __stream::map_future<derived_type, lambda_type>; | |||
auto& self = static_cast<derived_type const &>(*this); | |||
@@ -98,7 +98,7 @@ namespace asyncpp | |||
::map(X_lambda&& p_lambda) & | |||
{ | |||
using lambda_type = X_lambda; | |||
using map_type = __stream::map_impl<derived_type, lambda_type>; | |||
using map_type = __stream::map_future<derived_type, lambda_type>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
@@ -116,7 +116,7 @@ namespace asyncpp | |||
::map(X_lambda&& p_lambda) && | |||
{ | |||
using lambda_type = X_lambda; | |||
using map_type = __stream::map_impl<derived_type, lambda_type>; | |||
using map_type = __stream::map_future<derived_type, lambda_type>; | |||
auto& self = static_cast<derived_type &>(*this); | |||
@@ -8,10 +8,10 @@ namespace __stream { | |||
template< | |||
typename T_stream, | |||
typename T_lambda> | |||
struct map_impl final : | |||
struct map_future final : | |||
public base_stream< | |||
decltype(std::declval<T_lambda>()(std::declval<typename T_stream::value_type>())), | |||
map_impl<T_stream, T_lambda> | |||
map_future<T_stream, T_lambda> | |||
> | |||
{ | |||
public: | |||
@@ -19,7 +19,7 @@ namespace __stream { | |||
using lambda_type = T_lambda; | |||
using inner_value_type = typename stream_type::value_type; | |||
using value_type = decltype(std::declval<lambda_type>()(std::declval<inner_value_type>())); | |||
using this_type = map_impl<stream_type, lambda_type>; | |||
using this_type = map_future<stream_type, lambda_type>; | |||
using base_stream_type = base_stream<value_type, this_type>; | |||
using result_type = typename base_stream_type::result_type; | |||
@@ -34,7 +34,7 @@ namespace __stream { | |||
template< | |||
typename X_stream, | |||
typename X_lambda> | |||
inline map_impl( | |||
inline map_future( | |||
X_stream&& p_stream, | |||
X_lambda&& p_lambda); | |||
@@ -5,7 +5,7 @@ | |||
namespace asyncpp { | |||
namespace __stream { | |||
/* map_impl */ | |||
/* map_future */ | |||
template< | |||
typename T_stream, | |||
@@ -13,7 +13,7 @@ namespace __stream { | |||
template< | |||
typename X_stream, | |||
typename X_lambda> | |||
map_impl<T_stream, T_lambda>::map_impl( | |||
map_future<T_stream, T_lambda>::map_future( | |||
X_stream&& p_stream, | |||
X_lambda&& p_lambda) | |||
: _stream(std::forward<X_stream>(p_stream)) | |||
@@ -23,8 +23,8 @@ namespace __stream { | |||
template< | |||
typename T_stream, | |||
typename T_lambda> | |||
typename map_impl<T_stream, T_lambda>::result_type | |||
map_impl<T_stream, T_lambda> | |||
typename map_future<T_stream, T_lambda>::result_type | |||
map_future<T_stream, T_lambda> | |||
::poll() | |||
{ | |||
auto r = _stream.poll(); | |||
@@ -42,7 +42,7 @@ namespace timing { | |||
X_args&&... p_args); | |||
inline void idle( | |||
const asyncpp::time_point * p_deadline); | |||
const time_point * p_deadline); | |||
inline thread_lock_ptr_u init_thread(); | |||
}; | |||
@@ -70,7 +70,7 @@ namespace timing { | |||
owner_type& p_owner); | |||
inline void idle( | |||
const asyncpp::time_point * p_deadline); | |||
const time_point * p_deadline); | |||
inline thread_lock_ptr_u init_thread(); | |||
}; | |||
@@ -30,7 +30,7 @@ namespace __impl { | |||
{ } | |||
template<typename T_inner> | |||
void timer_impl<T_inner>::idle(const asyncpp::time_point * p_deadline) | |||
void timer_impl<T_inner>::idle(const time_point * p_deadline) | |||
{ | |||
{ | |||
auto r = owner._registrations.lock(); | |||
@@ -63,7 +63,7 @@ namespace __impl { | |||
{ } | |||
void timer_impl<void>::idle( | |||
const asyncpp::time_point * p_deadline) | |||
const time_point * p_deadline) | |||
{ } | |||
timer_impl<void>::thread_lock_ptr_u | |||
@@ -1,9 +1,8 @@ | |||
#pragma once | |||
#include <asyncpp/core/future.inl> | |||
#include "interval.h" | |||
#include "delay.inl" | |||
#include "interval.h" | |||
namespace asyncpp { | |||
namespace timing { | |||
@@ -12,7 +11,7 @@ namespace timing { | |||
template<typename T_base, typename T_ratio> | |||
interval::interval( | |||
const asyncpp::duration<T_base, T_ratio>& p_duration, | |||
const ::asyncpp::duration<T_base, T_ratio>& p_duration, | |||
time_point p_deadline) | |||
: interval(asyncpp::now() + p_duration, p_duration, p_deadline) | |||
{ } | |||
@@ -20,7 +19,7 @@ namespace timing { | |||
template<typename T_base, typename T_ratio> | |||
interval::interval( | |||
const time_point& p_at, | |||
const asyncpp::duration<T_base, T_ratio>& p_duration, | |||
const ::asyncpp::duration<T_base, T_ratio>& p_duration, | |||
time_point p_deadline) | |||
: _delay (p_at) | |||
, _duration(p_duration) | |||
@@ -36,7 +35,7 @@ namespace timing { | |||
{ | |||
if ( _deadline.time_since_epoch().count() | |||
&& _delay.deadline() >= _deadline | |||
&& asyncpp::now() >= _delay.deadline()) | |||
&& asyncpp::now() >= _delay.deadline()) | |||
return result_type::done(); | |||
auto ret = _delay.poll(); | |||
@@ -68,7 +68,7 @@ namespace timing { | |||
template<typename T_inner> | |||
struct timeout final | |||
: public __impl::timeout_impl<timeout<T_inner>> | |||
: public __impl::timeout_impl<timeout<T_inner>> | |||
{ | |||
public: | |||
using inner_type = T_inner; | |||
@@ -1,7 +1,5 @@ | |||
#pragma once | |||
#include <asyncpp/core/misc.inl> | |||
#include "timeout.h" | |||
namespace asyncpp { | |||
@@ -39,7 +39,7 @@ namespace timing { | |||
* This method is called as soon as the runtime has nothing to do. | |||
* The passed deadline is the timepoint the method should return (or null if not set). | |||
*/ | |||
inline void idle(const asyncpp::time_point * p_deadline); | |||
inline void idle(const time_point * p_deadline); | |||
/** | |||
* @brief This method is calld by the executor when a new thread needs to be initialized. | |||
@@ -1,7 +1,5 @@ | |||
#pragma once | |||
#include <asyncpp/core/misc.inl> | |||
#include "timer.h" | |||
#include "delay.inl" | |||
@@ -21,7 +19,7 @@ namespace timing { | |||
{ } | |||
template<typename T_inner> | |||
void timer<T_inner>::idle(const asyncpp::time_point * p_deadline) | |||
void timer<T_inner>::idle(const time_point * p_deadline) | |||
{ | |||
auto now = asyncpp::now(); | |||
@@ -33,6 +33,12 @@ public: | |||
} | |||
}; | |||
auto make_test_future(int i) | |||
{ | |||
test_future ret(i); | |||
return ret; | |||
} | |||
struct test_stream | |||
: public base_stream<int, test_stream> | |||
{ | |||
@@ -70,7 +76,7 @@ TEST(timeout_tests, poll_future_no_timeout) | |||
test_future t(0); | |||
auto f = t | |||
.timeout(std::chrono::seconds(5)); | |||
.timeout<ref>(std::chrono::seconds(5)); | |||
EXPECT_CALL(m, now()) | |||
.WillOnce(Return(time_point(std::chrono::seconds(0)))); | |||