From 8289b4b235682748dbc908228ed78145cfe1ab01 Mon Sep 17 00:00:00 2001 From: bergmann Date: Sun, 24 Nov 2019 23:57:32 +0100 Subject: [PATCH] * refactored/simplified 'future' class --- include/asyncpp/core/future.h | 81 ++++--- include/asyncpp/core/future.inl | 215 ++++++++++-------- include/asyncpp/core/future.pre.h | 42 +--- include/asyncpp/core/future/and_then.h | 44 ++-- include/asyncpp/core/future/and_then.inl | 24 +- include/asyncpp/core/future/map.h | 46 ++-- include/asyncpp/core/future/map.inl | 20 +- include/asyncpp/core/stream.inl | 4 +- include/asyncpp/core/stream/for_each.h | 44 ++-- include/asyncpp/core/stream/for_each.inl | 20 +- include/asyncpp/timing/delay.h | 31 +-- include/asyncpp/timing/delay.inl | 21 +- include/asyncpp/timing/interval.h | 7 +- include/asyncpp/timing/interval.inl | 10 +- include/asyncpp/timing/timeout.h | 47 ++-- include/asyncpp/timing/timeout.inl | 58 ++--- test/asyncpp/core/future_tests.cpp | 51 +---- test/asyncpp/core/task_tests.cpp | 34 +-- .../asyncpp/executor/current_thread_tests.cpp | 47 ++-- test/asyncpp/timing/delay_tests.cpp | 3 +- test/asyncpp/timing/timeout_tests.cpp | 42 ++-- test/asyncpp/timing/timer_tests.cpp | 12 +- test/helper/test_delay.h | 33 +++ 23 files changed, 433 insertions(+), 503 deletions(-) create mode 100644 test/helper/test_delay.h diff --git a/include/asyncpp/core/future.h b/include/asyncpp/core/future.h index ca5d0ef..b2f6357 100644 --- a/include/asyncpp/core/future.h +++ b/include/asyncpp/core/future.h @@ -12,61 +12,84 @@ namespace asyncpp { template< - typename T_object, - typename T_impl> - struct future + typename T_value, + typename T_derived> + struct base_future + : public tag_future { - using object_type = T_object; - using clean_object_type = std::decay_t; - using trait_type = future_trait; - using value_type = typename trait_type::value_type; - using result_type = future_result; - using reference = clean_object_type&; - using pointer = clean_object_type*; - using const_reference = const clean_object_type&; - using const_pointer = const clean_object_type*; - - object_type ref; + public: + using value_type = T_value; + using result_type = future_result; + using derived_type = T_derived; + using this_type = base_future; + public: /** - * @brief Value constructor. + * @brief Transform the result of this future. */ - template - inline future(X_object&& p_ref); + template + inline auto map(X_lambda&& p_lambda) const &; /** - * @brief Function that will be called repeatedly to check if the future is ready. + * @brief Transform the result of this future. */ - inline result_type poll(); + template + inline auto map(X_lambda&& p_lambda) &; /** * @brief Transform the result of this future. */ template - inline auto map(X_lambda&& p_lambda); + inline auto map(X_lambda&& p_lambda) &&; + + public: + /** + * @brief Execute the given lambda after the future is finished and + * wait for the future returned by the lambda. + */ + template + 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 - inline auto and_then(X_lambda&& p_lambda); + inline auto and_then(X_lambda&& p_lambda) &; - #ifdef asyncpp_timing + /** + * @brief Execute the given lambda after the future is finished and + * wait for the future returned by the lambda. + */ + template + inline auto and_then(X_lambda&& p_lambda) &&; + + #ifdef asyncpp_timing + public: /** * @brief Throw an execption if the timeout has passed. * * This method is only enabled if timer.h is included before. */ template - inline auto timeout(const duration& p_timeout); - #endif + inline auto timeout(const duration& p_timeout) const &; - public: - inline pointer operator->(); - inline reference operator*(); - inline const_pointer operator->() const; - inline const_reference operator*() const; + /** + * @brief Throw an execption if the timeout has passed. + * + * This method is only enabled if timer.h is included before. + */ + template + inline auto timeout(const duration& p_timeout) &; + + /** + * @brief Throw an execption if the timeout has passed. + * + * This method is only enabled if timer.h is included before. + */ + template + inline auto timeout(const duration& p_timeout) &&; + #endif }; } diff --git a/include/asyncpp/core/future.inl b/include/asyncpp/core/future.inl index 1659aa5..274a3d9 100644 --- a/include/asyncpp/core/future.inl +++ b/include/asyncpp/core/future.inl @@ -12,143 +12,174 @@ namespace asyncpp { - /* future_base */ + /* future::map */ - template - template - auto future_base - ::map(X_future&& self, X_lambda&& p_lambda) + template< + typename T_value, + typename T_derived> + template< + typename X_lambda> + auto base_future + ::map(X_lambda&& p_lambda) const & { - using future_type = X_future; - using lambda_type = X_lambda; - using map_type = __future::map_impl; + using lambda_type = X_lambda; + using map_type = __future::map_impl; + + auto& self = static_cast(*this); - return as_future(map_type( - std::forward(self), - std::forward(p_lambda))); + return map_type( + std::forward(self), + std::forward(p_lambda)); } - template - template - auto future_base - ::and_then(X_future&& self, X_lambda&& p_lambda) + template< + typename T_value, + typename T_derived> + template< + typename X_lambda> + auto base_future + ::map(X_lambda&& p_lambda) & { - using future_type = X_future; - using lambda_type = X_lambda; - using and_then_type = __future::and_then_impl; + using lambda_type = X_lambda; + using map_type = __future::map_impl; + + auto& self = static_cast(*this); - return as_future(and_then_type( - std::forward(self), - std::forward(p_lambda))); + return map_type( + std::forward(self), + std::forward(p_lambda)); } - #ifdef asyncpp_timing - template - template - auto future_base - ::timeout(X_future&& self, const duration& p_timeout) + template< + typename T_value, + typename T_derived> + template< + typename X_lambda> + auto base_future + ::map(X_lambda&& p_lambda) && { - using future_type = X_future; - using timeout_type = timing::timeout; + using lambda_type = X_lambda; + using map_type = __future::map_impl; - return as_future(timeout_type( - std::forward(self), - p_timeout)); + auto& self = static_cast(*this); + + return map_type( + std::forward(self), + std::forward(p_lambda)); } - #endif - /* future */ + /* future::and_then */ template< typename T_value, - typename T_impl> + typename T_derived> template< - typename X_object> - future - ::future(X_object&& p_ref) - : ref(std::forward(p_ref)) - { } + typename X_lambda> + auto base_future + ::and_then(X_lambda&& p_lambda) const & + { + using lambda_type = X_lambda; + using and_then_type = __future::and_then_impl; - template< - typename T_value, - typename T_impl> - typename future::result_type - future - ::poll() - { return trait_type::poll(*this); } + auto& self = static_cast(*this); + + return and_then_type( + std::forward(self), + std::forward(p_lambda)); + } template< typename T_value, - typename T_impl> + typename T_derived> template< typename X_lambda> - auto future - ::map(X_lambda&& p_lambda) - { return trait_type::map(std::move(*this), std::forward(p_lambda)); } + auto base_future + ::and_then(X_lambda&& p_lambda) & + { + using lambda_type = X_lambda; + using and_then_type = __future::and_then_impl; + + auto& self = static_cast(*this); + + return and_then_type( + std::forward(self), + std::forward(p_lambda)); + } template< typename T_value, - typename T_impl> + typename T_derived> template< typename X_lambda> - auto future - ::and_then(X_lambda&& p_lambda) - { return trait_type::and_then(std::move(*this), std::forward(p_lambda)); } + auto base_future + ::and_then(X_lambda&& p_lambda) && + { + using lambda_type = X_lambda; + using and_then_type = __future::and_then_impl; + + auto& self = static_cast(*this); + + return and_then_type( + std::forward(self), + std::forward(p_lambda)); + } + + /* future::timeout */ #ifdef asyncpp_timing template< typename T_value, - typename T_impl> + typename T_derived> template< typename X_base, typename X_ratio> - auto future - ::timeout(const duration& p_timeout) - { return trait_type::timeout(std::move(*this), p_timeout); } - #endif + auto base_future + ::timeout(const duration& p_timeout) const & + { + using timeout_type = timing::timeout; - template< - typename T_value, - typename T_impl> - typename future::pointer - future::operator->() - { return &ref; } + auto& self = static_cast(*this); - template< - typename T_value, - typename T_impl> - typename future::reference - future::operator*() - { return ref; } + return timeout_type( + std::forward(self), + p_timeout); + } template< typename T_value, - typename T_impl> - typename future::const_pointer - future::operator->() const - { return &ref; } - + typename T_derived> template< - typename T_value, - typename T_impl> - typename future::const_reference - future::operator*() const - { return ref; } + typename X_base, + typename X_ratio> + auto base_future + ::timeout(const duration& p_timeout) & + { + using timeout_type = timing::timeout; - /* misc */ + auto& self = static_cast(*this); - template - constexpr future as_future(X_value&& value) + return timeout_type( + std::forward(self), + p_timeout); + } + + template< + typename T_value, + typename T_derived> + template< + typename X_base, + typename X_ratio> + auto base_future + ::timeout(const duration& p_timeout) && { - using value_type = X_value; - using future_type = future; + using timeout_type = timing::timeout; - return future_type(std::forward(value)); - } + auto& self = static_cast(*this); - template - struct is_future, void> - : public std::true_type - { }; + return timeout_type( + std::forward(self), + p_timeout); + } + #endif } diff --git a/include/asyncpp/core/future.pre.h b/include/asyncpp/core/future.pre.h index c61db97..8902d35 100644 --- a/include/asyncpp/core/future.pre.h +++ b/include/asyncpp/core/future.pre.h @@ -5,48 +5,20 @@ namespace asyncpp { - template - struct future_base - { - public: - using impl_type = T_impl; - - public: - template - static inline auto poll(X_future& self) = delete; - - template - static inline auto map(X_future&& self, X_lambda&& p_lambda); - - template - static inline auto and_then(X_future&& self, X_lambda&& p_lambda); - - #ifdef asyncpp_timing - template - static inline auto timeout(X_future&& self, const duration& p_timeout); - #endif - }; - - template - struct future_trait; + struct tag_future + { }; template< - typename T_object, - typename T_impl = future_trait>> - struct future; + typename T_value, + typename T_derived> + struct base_future; - template + template struct is_future - : public std::false_type + : public std::is_base_of { }; template constexpr decltype(auto) is_future_v = is_future::value; - /** - * @brief Construct a future from the given value. - */ - template - constexpr future as_future(X_value&& value); - } diff --git a/include/asyncpp/core/future/and_then.h b/include/asyncpp/core/future/and_then.h index fd31566..8cf2ce2 100644 --- a/include/asyncpp/core/future/and_then.h +++ b/include/asyncpp/core/future/and_then.h @@ -2,7 +2,7 @@ #include -#include +#include "../future.pre.h" namespace asyncpp { namespace __future { @@ -10,14 +10,22 @@ namespace __future { template< typename T_future, typename T_lambda> - struct and_then_impl + struct and_then_impl final : + public base_future< + decltype(std::declval()(std::declval::value_type>())), + and_then_impl + > { public: using lambda_type = T_lambda; using first_future_type = T_future; - using first_value_type = typename first_future_type::value_type; - using second_future_type = decltype(as_future(std::declval()(std::declval()))); + using first_value_type = typename std::decay_t::value_type; + using second_future_type = decltype(std::declval()(std::declval())); using second_future_type_ptr = std::unique_ptr; + using value_type = typename second_future_type::value_type; + using this_type = and_then_impl; + using base_future_type = base_future; + using result_type = typename base_future_type::result_type; public: lambda_type lambda; @@ -34,28 +42,12 @@ namespace __future { inline and_then_impl( X_future&& p_outer, X_lambda&& p_lambda); - }; - -} } - -namespace asyncpp -{ - /* future_trait for and_then_impl */ - - template< - typename T_future, - typename T_lambda> - struct future_trait<__future::and_then_impl, void> - : public future_base, void>> - { - using and_then_type = __future::and_then_impl; - using second_future_type = typename and_then_type::second_future_type; - using value_type = typename second_future_type::value_type; - using result_type = typename second_future_type::result_type; - - template - static inline auto poll(X_future& self); + public: /* future */ + /** + * @brief Poll the result from the future. + */ + inline result_type poll(); }; -} +} } diff --git a/include/asyncpp/core/future/and_then.inl b/include/asyncpp/core/future/and_then.inl index 81f3c26..df34ba7 100644 --- a/include/asyncpp/core/future/and_then.inl +++ b/include/asyncpp/core/future/and_then.inl @@ -21,36 +21,28 @@ namespace __future { , lambda(std::forward(p_lambda)) { } -} } - -namespace asyncpp -{ - - /* future_trait for ant_then_impl */ - template< typename T_future, typename T_lambda> - template< - typename X_future> - auto future_trait<__future::and_then_impl, void> - ::poll(X_future& self) + typename and_then_impl::result_type + and_then_impl + ::poll() { while (true) { - if (self->second) + if (second) { - return self->second->poll(); + return second->poll(); } else { - auto r = self->first.poll(); + auto r = first.poll(); if (!r) return result_type::not_ready(); - self->second = std::make_unique(as_future(r.call(self->lambda))); + second = std::make_unique(r.call(lambda)); } } } -} +} } diff --git a/include/asyncpp/core/future/map.h b/include/asyncpp/core/future/map.h index f3e026b..eed3ede 100644 --- a/include/asyncpp/core/future/map.h +++ b/include/asyncpp/core/future/map.h @@ -1,16 +1,27 @@ #pragma once +#include "../future.pre.h" + namespace asyncpp { namespace __future { template< typename T_future, typename T_lambda> - struct map_impl + struct map_impl final : + public base_future< + typename std::decay_t::value_type, + map_impl + > { public: - using future_type = T_future; - using lambda_type = T_lambda; + using future_type = T_future; + using lambda_type = T_lambda; + using future_value_type = typename std::decay_t::value_type; + using value_type = decltype(std::declval()(std::declval())); + using this_type = map_impl; + using base_future_type = base_future; + using result_type = typename base_future_type::result_type; public: future_type future; @@ -26,29 +37,12 @@ namespace __future { inline map_impl( X_future&& p_future, X_lambda&& p_lambda); - }; - -} } - -namespace asyncpp -{ - - /* future_trait for map_impl */ - - template< - typename T_future, - typename T_lambda> - struct future_trait<__future::map_impl, void> - : public future_base, void>> - { - using future_type = T_future; - using inner_value_type = typename future_type::value_type; - using lambda_type = T_lambda; - using value_type = decltype(std::declval()(std::declval())); - using result_type = future_result; - template - static inline auto poll(X_future& self); + public: /* future */ + /** + * @brief Poll the result from the future. + */ + inline result_type poll(); }; -} +} } diff --git a/include/asyncpp/core/future/map.inl b/include/asyncpp/core/future/map.inl index 34074e8..bdc6c39 100644 --- a/include/asyncpp/core/future/map.inl +++ b/include/asyncpp/core/future/map.inl @@ -21,25 +21,17 @@ namespace __future { , lambda(std::forward(p_lambda)) { } -} } - -namespace asyncpp -{ - - /* future_trait for map_impl */ - template< typename T_future, typename T_lambda> - template< - typename X_future> - auto future_trait<__future::map_impl, void> - ::poll(X_future& self) + typename map_impl::result_type + map_impl + ::poll() { - auto r = self->future.poll(); + auto r = future.poll(); return r - ? result_type::ready(r.call(self->lambda)) + ? result_type::ready(r.call(lambda)) : result_type::not_ready(); } -} +} } diff --git a/include/asyncpp/core/stream.inl b/include/asyncpp/core/stream.inl index ed1c88f..1fce400 100644 --- a/include/asyncpp/core/stream.inl +++ b/include/asyncpp/core/stream.inl @@ -22,9 +22,9 @@ namespace asyncpp using lambda_type = X_lambda; using for_each_type = __stream::for_each_impl; - return as_future(for_each_type( + return for_each_type( std::forward(self), - std::forward(p_lambda))); + std::forward(p_lambda)); } #ifdef asyncpp_timing diff --git a/include/asyncpp/core/stream/for_each.h b/include/asyncpp/core/stream/for_each.h index a4e9050..491dfed 100644 --- a/include/asyncpp/core/stream/for_each.h +++ b/include/asyncpp/core/stream/for_each.h @@ -8,11 +8,19 @@ namespace __stream { template< typename T_stream, typename T_lambda> - struct for_each_impl + struct for_each_impl final : + public base_future< + void, + for_each_impl + > { public: - using stream_type = T_stream; - using lambda_type = T_lambda; + using stream_type = T_stream; + using lambda_type = T_lambda; + using value_type = void; + using this_type = for_each_impl; + using base_future_type = base_future; + using result_type = typename base_future_type::result_type; public: stream_type stream; @@ -28,30 +36,12 @@ namespace __stream { inline for_each_impl( X_stream&& p_stream, X_lambda&& p_lambda); - }; - -} } -namespace asyncpp -{ - - /* future_trait for map_impl */ - - template< - typename T_stream, - typename T_lambda> - struct future_trait<__stream::for_each_impl, void> - : public future_base, void>> - { - using stream_type = T_stream; - using inner_value_type = typename stream_type::value_type; - using inner_result_type = future_result; - using lambda_type = T_lambda; - using value_type = decltype(std::declval().call(std::declval())); - using result_type = future_result; - - template - static inline auto poll(X_future& self); + public: /* future */ + /** + * @brief Poll the result from the future. + */ + inline result_type poll(); }; -} +} } diff --git a/include/asyncpp/core/stream/for_each.inl b/include/asyncpp/core/stream/for_each.inl index 2d2dfc7..1ad6581 100644 --- a/include/asyncpp/core/stream/for_each.inl +++ b/include/asyncpp/core/stream/for_each.inl @@ -21,32 +21,24 @@ namespace __stream { , lambda(std::forward(p_lambda)) { } -} } - -namespace asyncpp -{ - - /* future_trait for for_each_impl */ - template< typename T_stream, typename T_lambda> - template< - typename X_stream> - auto future_trait<__stream::for_each_impl, void> - ::poll(X_stream& self) + typename for_each_impl::result_type + for_each_impl + ::poll() { while (true) { - auto r = self->stream.poll(); + auto r = stream.poll(); if (r.is_done()) return result_type::ready(); if (r.is_not_ready()) return result_type::not_ready(); - r.call(self->lambda); + r.call(lambda); } } -} +} } diff --git a/include/asyncpp/timing/delay.h b/include/asyncpp/timing/delay.h index 116f560..fda6241 100644 --- a/include/asyncpp/timing/delay.h +++ b/include/asyncpp/timing/delay.h @@ -9,10 +9,13 @@ namespace asyncpp { namespace timing { - struct delay + struct delay final + : public base_future { public: - friend struct future_trait; + using value_type = void; + using base_future_type = base_future; + using result_type = typename base_future_type::result_type; private: time_point _deadline; @@ -50,24 +53,12 @@ namespace timing { */ template inline void reset(const duration& p_duration); - }; - -} } - -namespace asyncpp -{ - - /* future_impl for timing::delay */ - template<> - struct future_trait - : public future_base> - { - using value_type = void; - using result_type = future_result; - - template - static inline auto poll(X_future& self); + public: /* future */ + /** + * @brief Poll the result from the future. + */ + inline result_type poll(); }; -} +} } diff --git a/include/asyncpp/timing/delay.inl b/include/asyncpp/timing/delay.inl index d3b7f4f..95d158e 100644 --- a/include/asyncpp/timing/delay.inl +++ b/include/asyncpp/timing/delay.inl @@ -43,26 +43,19 @@ namespace timing { _deadline = asyncpp::now() + p_duration; } -} } - -namespace asyncpp -{ - - /* future_impl for timing::delay */ - - template - auto future_trait - ::poll(X_future& self) + typename delay::result_type + delay + ::poll() { auto now = asyncpp::now(); - if (self->_deadline <= now) + if (_deadline <= now) return result_type::ready(); - if (self->_registration.expired()) - self->_registration = timing::__impl::timer_base::register_resource(self->_deadline); + if (_registration.expired()) + _registration = timing::__impl::timer_base::register_resource(_deadline); return result_type::not_ready(); } -} +} } diff --git a/include/asyncpp/timing/interval.h b/include/asyncpp/timing/interval.h index 5ba811a..c8ac674 100644 --- a/include/asyncpp/timing/interval.h +++ b/include/asyncpp/timing/interval.h @@ -9,16 +9,13 @@ namespace asyncpp { namespace timing { - struct interval + struct interval final { - public: - using delay_future_type = future; - public: friend struct stream_trait; private: - delay_future_type _delay; //!< Delay future + delay _delay; //!< Delay future clock::duration _duration; //!< Interval duration. time_point _deadline; //!< Deadline after the interval should end. diff --git a/include/asyncpp/timing/interval.inl b/include/asyncpp/timing/interval.inl index 4f26dac..898ec88 100644 --- a/include/asyncpp/timing/interval.inl +++ b/include/asyncpp/timing/interval.inl @@ -22,7 +22,7 @@ namespace timing { const time_point& p_at, const asyncpp::duration& p_duration, time_point p_deadline) - : _delay (as_future(delay(p_at))) + : _delay (p_at) , _duration(p_duration) , _deadline(p_deadline) { } @@ -43,17 +43,17 @@ namespace asyncpp ::poll(X_stream& self) { if ( self->_deadline.time_since_epoch().count() - && self->_delay->deadline() >= self->_deadline - && asyncpp::now() >= self->_delay->deadline()) + && self->_delay.deadline() >= self->_deadline + && asyncpp::now() >= self->_delay.deadline()) return result_type::done(); auto ret = self->_delay.poll(); if (ret.is_not_ready()) return result_type::not_ready(); - auto now = self->_delay->deadline(); + auto now = self->_delay.deadline(); auto new_deadline = now + self->_duration; - self->_delay->reset(new_deadline); + self->_delay.reset(new_deadline); return result_type::ready(); } diff --git a/include/asyncpp/timing/timeout.h b/include/asyncpp/timing/timeout.h index c4260d6..82cdcfd 100644 --- a/include/asyncpp/timing/timeout.h +++ b/include/asyncpp/timing/timeout.h @@ -21,21 +21,27 @@ namespace timing { inline timeout_exception(); }; + struct tag_timeout + { }; + template - struct timeout + struct timeout final + : public std::conditional_t< + is_future_v, + base_future::value_type, timeout>, + tag_timeout> { public: - using inner_type = T_inner; - using delay_future_type = future; + using inner_type = T_inner; + using value_type = typename std::decay_t::value_type; public: friend struct stream_trait; - friend struct future_trait; private: - inner_type _inner; //!< Inner future / stream. - clock::duration _timeout; //!< Timeout. - delay_future_type _delay; //!< Delay future. + inner_type _inner; //!< Inner future / stream. + clock::duration _timeout; //!< Timeout. + delay _delay; //!< Delay future. public: /** @@ -52,6 +58,15 @@ namespace timing { template inline void reset( const duration& p_timeout); + + public: /* future */ + /** + * @brief Poll the result from the future. + */ + template< + typename X = std::decay_t, + typename = std::enable_if_t>> + inline auto poll(); }; } } @@ -59,24 +74,6 @@ namespace timing { namespace asyncpp { - /* future_trait for timing::timeout */ - - template - struct future_trait< - timing::timeout, - std::enable_if_t> - > - : public future_base, void>> - { - using inner_type = T_inner; - using timeout_type = timing::timeout; - using value_type = typename inner_type::value_type; - using result_type = typename inner_type::result_type; - - template - static inline result_type poll(X_future& self); - }; - /* stream_trait for timing::timeout */ template diff --git a/include/asyncpp/timing/timeout.inl b/include/asyncpp/timing/timeout.inl index 9f99a47..14b6a4e 100644 --- a/include/asyncpp/timing/timeout.inl +++ b/include/asyncpp/timing/timeout.inl @@ -15,55 +15,59 @@ namespace timing { /* timer */ - template - template + template< + typename T_inner> + template< + typename X_inner, + typename X_base, + typename X_ratio> timeout ::timeout( X_inner&& p_inner, const duration& p_duration) : _inner (std::forward(p_inner)) , _timeout (p_duration) - , _delay (as_future(delay(asyncpp::now() + p_duration))) + , _delay (asyncpp::now() + p_duration) { } - template - template + template< + typename T_inner> + template< + typename X_base, + typename X_ratio> void timeout ::reset(const duration& p_duration) { _timeout = p_duration; - _delay->reset(asyncpp::now() + p_duration); + _delay.reset(asyncpp::now() + p_duration); } -} } - -namespace asyncpp -{ - - /* future_trait for timing::timeout */ - - template - template - typename T_inner::result_type - future_trait< - timing::timeout, - std::enable_if_t> - > - ::poll(X_future& self) + template< + typename T_inner> + template< + typename X, + typename> + auto timeout + ::poll() { - auto r = self->_inner.poll(); + auto r = _inner.poll(); if ( r.is_not_ready() - && self->_delay.poll()) + && _delay.poll()) { - auto new_deadline = self->_delay->deadline() + self->_timeout; - self->_delay->reset(new_deadline); + auto new_deadline = _delay.deadline() + _timeout; + _delay.reset(new_deadline); throw timing::timeout_exception(); } return r; } +} } + +namespace asyncpp +{ + /* stream_trait for timing::timeout */ template @@ -81,13 +85,13 @@ namespace asyncpp { if (self->_delay.poll()) { - self->_delay->reset(self->_timeout); + self->_delay.reset(self->_timeout); throw timing::timeout_exception(); } } else { - self->_delay->reset(self->_timeout); + self->_delay.reset(self->_timeout); } return r; diff --git a/test/asyncpp/core/future_tests.cpp b/test/asyncpp/core/future_tests.cpp index 78c8b7f..3901406 100644 --- a/test/asyncpp/core/future_tests.cpp +++ b/test/asyncpp/core/future_tests.cpp @@ -2,43 +2,14 @@ #include +#include "../../helper/test_delay.h" + using namespace ::testing; using namespace ::asyncpp; -struct delay -{ - int const delay { 5 }; - int count { 0 }; -}; - -namespace asyncpp -{ - - template<> - struct future_trait - : public future_base> - { - using value_type = int&; - - template - static inline auto poll(T_future& self) - { - using result_type = future_result; - - if (self->count >= self->delay) - return result_type::ready(self->count); - - ++self->count; - return result_type::not_ready(); - } - }; - -} - TEST(future_tests, poll) { - delay d { 5, 0 }; - auto f = as_future(d); + test_delay f(5, 0); auto r0 = f.poll(); ASSERT_FALSE(r0); @@ -58,14 +29,14 @@ TEST(future_tests, poll) auto r = f.poll(); ASSERT_TRUE (r); ASSERT_EQ (5, *r); - ASSERT_EQ (5, d.count); - ASSERT_EQ (&*r, &d.count); + ASSERT_EQ (5, f._count); + ASSERT_EQ (&*r, &f._count); } TEST(future_tests, map) { - delay d { 1, 1 }; - auto f = as_future(d) + test_delay d(1, 1); + auto f = d .map([](int& i){ return 10 + i; }); @@ -77,10 +48,10 @@ TEST(future_tests, map) TEST(future_tests, and_then) { - delay d { 2, 0 }; - auto f = as_future(d) + test_delay d(2, 0); + auto f = d .and_then([](int& i){ - return delay { 5, i }; + return test_delay { 5, i }; }); auto r0 = f.poll(); @@ -101,5 +72,5 @@ TEST(future_tests, and_then) auto r = f.poll(); ASSERT_TRUE(r); ASSERT_EQ (5, *r); - ASSERT_EQ (2, d.count); + ASSERT_EQ (2, f.first._count); } diff --git a/test/asyncpp/core/task_tests.cpp b/test/asyncpp/core/task_tests.cpp index e1ead2e..90ae885 100644 --- a/test/asyncpp/core/task_tests.cpp +++ b/test/asyncpp/core/task_tests.cpp @@ -2,42 +2,14 @@ #include +#include "../../helper/test_delay.h" + using namespace ::testing; using namespace ::asyncpp; -struct delay -{ - int const delay { 5 }; - int count { 0 }; -}; - -namespace asyncpp -{ - - template<> - struct future_trait - : public future_base> - { - using value_type = int&; - - template - static inline auto poll(T_future& self) - { - using result_type = future_result; - - if (self->count >= self->delay) - return result_type::ready(self->count); - - ++self->count; - return result_type::not_ready(); - } - }; - -} - TEST(task_tests, poll) { - auto t = make_task(as_future(delay { 5, 0 })); + auto t = make_task(test_delay { 5, 0 }); ASSERT_FALSE(t->poll()); ASSERT_FALSE(t->poll()); diff --git a/test/asyncpp/executor/current_thread_tests.cpp b/test/asyncpp/executor/current_thread_tests.cpp index 6d66761..c564d97 100644 --- a/test/asyncpp/executor/current_thread_tests.cpp +++ b/test/asyncpp/executor/current_thread_tests.cpp @@ -11,9 +11,29 @@ using namespace ::testing; using namespace ::asyncpp; struct test + : public base_future { +public: + using value_type = void; + using this_type = test; + using base_future_type = base_future; + using result_type = typename base_future_type::result_type; + +public: bool done { false }; task_ptr_w task; + +public: + inline test() = default; + +public: + inline auto poll() + { + task = task::current(); + return done + ? result_type::ready() + : result_type::not_ready(); + } }; struct mock @@ -21,30 +41,8 @@ struct mock MOCK_METHOD0(call, void()); }; -namespace asyncpp -{ - - template<> - struct future_trait - : public future_base> - { - using value_type = void; - using result_type = future_result; - - template - static inline auto poll(X_future& self) - { - self->task = task::current(); - return self->done - ? result_type::ready() - : result_type::not_ready(); - } - }; - -} - TEST(current_thread_tests, run) -{/* +{ Sequence s; StrictMock m; executor::current_thread&> e(m); @@ -52,7 +50,6 @@ TEST(current_thread_tests, run) EXPECT_CALL(m, init_thread()); test t; - auto f = as_future(t); EXPECT_CALL(m, idle(nullptr)) .InSequence(s) @@ -68,7 +65,7 @@ TEST(current_thread_tests, run) s->notify(); }));; - e.run(f); */ + e.run(t); } TEST(current_thread_tests, interval) diff --git a/test/asyncpp/timing/delay_tests.cpp b/test/asyncpp/timing/delay_tests.cpp index 4f4bc5d..40cd8d3 100644 --- a/test/asyncpp/timing/delay_tests.cpp +++ b/test/asyncpp/timing/delay_tests.cpp @@ -22,8 +22,7 @@ TEST(delay_tests, poll) t.make_current(); { - delay d(time_point(std::chrono::seconds(1000))); - auto f = as_future(d); + delay f(time_point(std::chrono::seconds(1000))); EXPECT_EQ(0, t.resource_count()); diff --git a/test/asyncpp/timing/timeout_tests.cpp b/test/asyncpp/timing/timeout_tests.cpp index 1bae92c..439db09 100644 --- a/test/asyncpp/timing/timeout_tests.cpp +++ b/test/asyncpp/timing/timeout_tests.cpp @@ -10,28 +10,31 @@ using namespace ::asyncpp; using namespace ::asyncpp::timing; struct test + : public base_future { +public: + using value_type = int; + using this_type = test; + using base_future_type = base_future; + +public: int i; -}; -namespace asyncpp -{ + inline test(int p_i) + : i(p_i) + { } - template<> - struct future_trait - : public future_base> +public: + inline result_type poll() { - using value_type = int; - using result_type = future_result; + return i + ? result_type::ready(i) + : result_type::not_ready(); + } +}; - template - static inline result_type poll(X_future& self) - { - return self->i - ? result_type::ready(self->i) - : result_type::not_ready(); - } - }; +namespace asyncpp +{ template<> struct stream_trait @@ -62,8 +65,8 @@ TEST(timeout_tests, poll_future_no_timeout) EXPECT_CALL(m, now()) .WillOnce(Return(time_point(std::chrono::seconds(0)))); - auto t = test { 0 }; - auto f = as_future(t) + test t(0); + auto f = t .timeout(std::chrono::seconds(5)); EXPECT_CALL(m, now()) @@ -95,8 +98,7 @@ TEST(timeout_tests, poll_future_timeout) EXPECT_CALL(m, now()) .WillOnce(Return(time_point(std::chrono::seconds(0)))); - auto t = test { 0 }; - auto f = as_future(t) + auto f = test(0) .timeout(std::chrono::seconds(5)); EXPECT_CALL(m, now()) diff --git a/test/asyncpp/timing/timer_tests.cpp b/test/asyncpp/timing/timer_tests.cpp index 87c2a11..9189641 100644 --- a/test/asyncpp/timing/timer_tests.cpp +++ b/test/asyncpp/timing/timer_tests.cpp @@ -38,14 +38,12 @@ TEST(timer_tests, resource_registration) EXPECT_CALL(m, now) .WillRepeatedly(Return(time_point(std::chrono::seconds(0)))); - using delay_future_type = decltype(as_future(timing::delay(std::chrono::seconds(10)))); - timing::timer t; t.make_current(); - auto f1 = std::make_unique(timing::delay(std::chrono::seconds(10))); - auto f2 = std::make_unique(timing::delay(std::chrono::seconds(20))); - auto f3 = std::make_unique(timing::delay(std::chrono::seconds(30))); + auto f1 = std::make_unique(std::chrono::seconds(10)); + auto f2 = std::make_unique(std::chrono::seconds(20)); + auto f3 = std::make_unique(std::chrono::seconds(30)); EXPECT_EQ(0, t.resource_count()); @@ -80,8 +78,6 @@ TEST(timer_tests, resource_registration) TEST(timer_tests, idle) { - using delay_future_type = decltype(as_future(std::declval())); - time_point x; InSequence seq; StrictMock nm; @@ -102,7 +98,7 @@ TEST(timer_tests, idle) EXPECT_CALL(nm, now); - auto f = std::make_unique(timing::delay(time_point(std::chrono::seconds(10)))); + auto f = std::make_unique(time_point(std::chrono::seconds(10))); f->poll(); EXPECT_CALL(nm, now); diff --git a/test/helper/test_delay.h b/test/helper/test_delay.h new file mode 100644 index 0000000..cd53c79 --- /dev/null +++ b/test/helper/test_delay.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +struct test_delay final + : public asyncpp::base_future +{ +public: + using value_type = int&; + using this_type = test_delay; + using base_future_type = base_future; + using result_type = typename base_future_type::result_type; + +public: + int const _delay { 5 }; + int _count { 0 }; + +public: + test_delay(int p_delay, int p_count) + : _delay(p_delay) + , _count(p_count) + { } + + inline result_type poll() + { + if (_count >= _delay) + return result_type::ready(_count); + + ++_count; + + return result_type::not_ready(); + } +};