瀏覽代碼

* refactored/simplified 'future' class

master
bergmann 6 年之前
父節點
當前提交
8289b4b235
共有 23 個檔案被更改,包括 433 行新增503 行删除
  1. +52
    -29
      include/asyncpp/core/future.h
  2. +123
    -92
      include/asyncpp/core/future.inl
  3. +7
    -35
      include/asyncpp/core/future.pre.h
  4. +18
    -26
      include/asyncpp/core/future/and_then.h
  5. +8
    -16
      include/asyncpp/core/future/and_then.inl
  6. +20
    -26
      include/asyncpp/core/future/map.h
  7. +6
    -14
      include/asyncpp/core/future/map.inl
  8. +2
    -2
      include/asyncpp/core/stream.inl
  9. +17
    -27
      include/asyncpp/core/stream/for_each.h
  10. +6
    -14
      include/asyncpp/core/stream/for_each.inl
  11. +11
    -20
      include/asyncpp/timing/delay.h
  12. +7
    -14
      include/asyncpp/timing/delay.inl
  13. +2
    -5
      include/asyncpp/timing/interval.h
  14. +5
    -5
      include/asyncpp/timing/interval.inl
  15. +22
    -25
      include/asyncpp/timing/timeout.h
  16. +31
    -27
      include/asyncpp/timing/timeout.inl
  17. +11
    -40
      test/asyncpp/core/future_tests.cpp
  18. +3
    -31
      test/asyncpp/core/task_tests.cpp
  19. +22
    -25
      test/asyncpp/executor/current_thread_tests.cpp
  20. +1
    -2
      test/asyncpp/timing/delay_tests.cpp
  21. +22
    -20
      test/asyncpp/timing/timeout_tests.cpp
  22. +4
    -8
      test/asyncpp/timing/timer_tests.cpp
  23. +33
    -0
      test/helper/test_delay.h

+ 52
- 29
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<object_type>;
using trait_type = future_trait<clean_object_type>;
using value_type = typename trait_type::value_type;
using result_type = future_result<value_type>;
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<value_type>;
using derived_type = T_derived;
using this_type = base_future<value_type, derived_type>;

public:
/**
* @brief Value constructor.
* @brief Transform the result of this future.
*/
template<typename X_object>
inline future(X_object&& p_ref);
template<typename X_lambda>
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<typename X_lambda>
inline auto map(X_lambda&& p_lambda) &;

/**
* @brief Transform the result of this future.
*/
template<typename X_lambda>
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<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>
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<typename X_lambda>
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<typename X_base, typename X_ratio>
inline auto timeout(const duration<X_base, X_ratio>& p_timeout);
#endif
inline auto timeout(const duration<X_base, X_ratio>& 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<typename X_base, typename X_ratio>
inline auto timeout(const duration<X_base, X_ratio>& p_timeout) &;

/**
* @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>
inline auto timeout(const duration<X_base, X_ratio>& p_timeout) &&;
#endif
};

}

+ 123
- 92
include/asyncpp/core/future.inl 查看文件

@@ -12,143 +12,174 @@
namespace asyncpp
{

/* future_base */
/* future::map */

template<typename T_impl>
template<typename X_future, typename X_lambda>
auto future_base<T_impl>
::map(X_future&& self, 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) const &
{
using future_type = X_future;
using lambda_type = X_lambda;
using map_type = __future::map_impl<future_type, lambda_type>;
using lambda_type = X_lambda;
using map_type = __future::map_impl<derived_type, lambda_type>;

auto& self = static_cast<derived_type const &>(*this);

return as_future(map_type(
std::forward<X_future>(self),
std::forward<X_lambda>(p_lambda)));
return map_type(
std::forward<derived_type const>(self),
std::forward<X_lambda>(p_lambda));
}

template<typename T_impl>
template<typename X_future, typename X_lambda>
auto future_base<T_impl>
::and_then(X_future&& self, 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 future_type = X_future;
using lambda_type = X_lambda;
using and_then_type = __future::and_then_impl<future_type, lambda_type>;
using lambda_type = X_lambda;
using map_type = __future::map_impl<derived_type&, lambda_type>;

auto& self = static_cast<derived_type &>(*this);

return as_future(and_then_type(
std::forward<X_future>(self),
std::forward<X_lambda>(p_lambda)));
return map_type(
std::forward<derived_type &>(self),
std::forward<X_lambda>(p_lambda));
}

#ifdef asyncpp_timing
template<typename T_impl>
template<typename X_future, typename X_base, typename X_ratio>
auto future_base<T_impl>
::timeout(X_future&& self, const duration<X_base, X_ratio>& p_timeout)
template<
typename T_value,
typename T_derived>
template<
typename X_lambda>
auto base_future<T_value, T_derived>
::map(X_lambda&& p_lambda) &&
{
using future_type = X_future;
using timeout_type = timing::timeout<future_type>;
using lambda_type = X_lambda;
using map_type = __future::map_impl<derived_type, lambda_type>;

return as_future(timeout_type(
std::forward<X_future>(self),
p_timeout));
auto& self = static_cast<derived_type &>(*this);

return map_type(
std::forward<derived_type &&>(self),
std::forward<X_lambda>(p_lambda));
}
#endif

/* future */
/* future::and_then */

template<
typename T_value,
typename T_impl>
typename T_derived>
template<
typename X_object>
future<T_value, T_impl>
::future(X_object&& p_ref)
: ref(std::forward<X_object>(p_ref))
{ }
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>;

template<
typename T_value,
typename T_impl>
typename future<T_value, T_impl>::result_type
future<T_value, T_impl>
::poll()
{ return trait_type::poll(*this); }
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_impl>
typename T_derived>
template<
typename X_lambda>
auto future<T_value, T_impl>
::map(X_lambda&& p_lambda)
{ return trait_type::map(std::move(*this), std::forward<X_lambda>(p_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_impl>
typename T_derived>
template<
typename X_lambda>
auto future<T_value, T_impl>
::and_then(X_lambda&& p_lambda)
{ return trait_type::and_then(std::move(*this), std::forward<X_lambda>(p_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));
}

/* future::timeout */

#ifdef asyncpp_timing
template<
typename T_value,
typename T_impl>
typename T_derived>
template<
typename X_base,
typename X_ratio>
auto future<T_value, T_impl>
::timeout(const duration<X_base, X_ratio>& p_timeout)
{ return trait_type::timeout(std::move(*this), p_timeout); }
#endif
auto base_future<T_value, T_derived>
::timeout(const duration<X_base, X_ratio>& p_timeout) const &
{
using timeout_type = timing::timeout<derived_type>;

template<
typename T_value,
typename T_impl>
typename future<T_value, T_impl>::pointer
future<T_value, T_impl>::operator->()
{ return &ref; }
auto& self = static_cast<derived_type const &>(*this);

template<
typename T_value,
typename T_impl>
typename future<T_value, T_impl>::reference
future<T_value, T_impl>::operator*()
{ return ref; }
return timeout_type(
std::forward<derived_type const>(self),
p_timeout);
}

template<
typename T_value,
typename T_impl>
typename future<T_value, T_impl>::const_pointer
future<T_value, T_impl>::operator->() const
{ return &ref; }

typename T_derived>
template<
typename T_value,
typename T_impl>
typename future<T_value, T_impl>::const_reference
future<T_value, T_impl>::operator*() const
{ return ref; }
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&>;

/* misc */
auto& self = static_cast<derived_type &>(*this);

template<typename X_value>
constexpr future<X_value> as_future(X_value&& value)
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 value_type = X_value;
using future_type = future<value_type>;
using timeout_type = timing::timeout<derived_type>;

return future_type(std::forward<X_value>(value));
}
auto& self = static_cast<derived_type &>(*this);

template<typename T>
struct is_future<future<T>, void>
: public std::true_type
{ };
return timeout_type(
std::forward<derived_type &&>(self),
p_timeout);
}
#endif

}

+ 7
- 35
include/asyncpp/core/future.pre.h 查看文件

@@ -5,48 +5,20 @@
namespace asyncpp
{

template<typename T_impl>
struct future_base
{
public:
using impl_type = T_impl;

public:
template<typename X_future>
static inline auto poll(X_future& self) = delete;

template<typename X_future, typename X_lambda>
static inline auto map(X_future&& self, X_lambda&& p_lambda);

template<typename X_future, typename X_lambda>
static inline auto and_then(X_future&& self, X_lambda&& p_lambda);

#ifdef asyncpp_timing
template<typename X_future, typename X_base, typename X_ratio>
static inline auto timeout(X_future&& self, const duration<X_base, X_ratio>& p_timeout);
#endif
};

template<typename T, typename = void>
struct future_trait;
struct tag_future
{ };

template<
typename T_object,
typename T_impl = future_trait<std::decay_t<T_object>>>
struct future;
typename T_value,
typename T_derived>
struct base_future;

template<typename T, typename = void>
template<typename T>
struct is_future
: public std::false_type
: public std::is_base_of<tag_future, T>
{ };

template<typename T>
constexpr decltype(auto) is_future_v = is_future<T>::value;

/**
* @brief Construct a future from the given value.
*/
template<typename X_value>
constexpr future<X_value> as_future(X_value&& value);

}

+ 18
- 26
include/asyncpp/core/future/and_then.h 查看文件

@@ -2,7 +2,7 @@

#include <memory>

#include <asyncpp/core/future.pre.h>
#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<T_lambda>()(std::declval<typename std::decay_t<T_future>::value_type>())),
and_then_impl<T_future, T_lambda>
>
{
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<lambda_type>()(std::declval<first_value_type>())));
using first_value_type = typename std::decay_t<first_future_type>::value_type;
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 base_future_type = base_future<value_type, this_type>;
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<T_future, T_lambda>, void>
: public future_base<future<__future::and_then_impl<T_future, T_lambda>, void>>
{
using and_then_type = __future::and_then_impl<T_future, T_lambda>;
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<typename X_future>
static inline auto poll(X_future& self);
public: /* future */
/**
* @brief Poll the result from the future.
*/
inline result_type poll();
};

}
} }

+ 8
- 16
include/asyncpp/core/future/and_then.inl 查看文件

@@ -21,36 +21,28 @@ namespace __future {
, lambda(std::forward<X_lambda>(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<T_future, T_lambda>, void>
::poll(X_future& self)
typename and_then_impl<T_future, T_lambda>::result_type
and_then_impl<T_future, T_lambda>
::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<second_future_type>(as_future(r.call(self->lambda)));
second = std::make_unique<second_future_type>(r.call(lambda));
}
}
}

}
} }

+ 20
- 26
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<T_future>::value_type,
map_impl<T_future, T_lambda>
>
{
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<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 base_future_type = base_future<value_type, this_type>;
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<T_future, T_lambda>, void>
: public future_base<future<__future::map_impl<T_future, T_lambda>, 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<lambda_type>()(std::declval<inner_value_type>()));
using result_type = future_result<value_type>;

template<typename X_future>
static inline auto poll(X_future& self);
public: /* future */
/**
* @brief Poll the result from the future.
*/
inline result_type poll();
};

}
} }

+ 6
- 14
include/asyncpp/core/future/map.inl 查看文件

@@ -21,25 +21,17 @@ namespace __future {
, lambda(std::forward<X_lambda>(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<T_future, T_lambda>, void>
::poll(X_future& self)
typename map_impl<T_future, T_lambda>::result_type
map_impl<T_future, T_lambda>
::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();
}

}
} }

+ 2
- 2
include/asyncpp/core/stream.inl 查看文件

@@ -22,9 +22,9 @@ namespace asyncpp
using lambda_type = X_lambda;
using for_each_type = __stream::for_each_impl<stream_type, lambda_type>;

return as_future(for_each_type(
return for_each_type(
std::forward<X_stream>(self),
std::forward<X_lambda>(p_lambda)));
std::forward<X_lambda>(p_lambda));
}

#ifdef asyncpp_timing


+ 17
- 27
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<T_stream, T_lambda>
>
{
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<stream_type, lambda_type>;
using base_future_type = base_future<value_type, this_type>;
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<T_stream, T_lambda>, void>
: public future_base<future<__stream::for_each_impl<T_stream, T_lambda>, void>>
{
using stream_type = T_stream;
using inner_value_type = typename stream_type::value_type;
using inner_result_type = future_result<inner_value_type>;
using lambda_type = T_lambda;
using value_type = decltype(std::declval<inner_result_type>().call(std::declval<lambda_type>()));
using result_type = future_result<value_type>;

template<typename X_future>
static inline auto poll(X_future& self);
public: /* future */
/**
* @brief Poll the result from the future.
*/
inline result_type poll();
};

}
} }

+ 6
- 14
include/asyncpp/core/stream/for_each.inl 查看文件

@@ -21,32 +21,24 @@ namespace __stream {
, lambda(std::forward<X_lambda>(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<T_stream, T_lambda>, void>
::poll(X_stream& self)
typename for_each_impl<T_stream, T_lambda>::result_type
for_each_impl<T_stream, T_lambda>
::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);
}
}

}
} }

+ 11
- 20
include/asyncpp/timing/delay.h 查看文件

@@ -9,10 +9,13 @@
namespace asyncpp {
namespace timing {

struct delay
struct delay final
: public base_future<void, delay>
{
public:
friend struct future_trait<delay, void>;
using value_type = void;
using base_future_type = base_future<void, delay>;
using result_type = typename base_future_type::result_type;

private:
time_point _deadline;
@@ -50,24 +53,12 @@ namespace timing {
*/
template<typename T_base, typename T_ratio>
inline void reset(const duration<T_base, T_ratio>& p_duration);
};

} }

namespace asyncpp
{

/* future_impl for timing::delay */

template<>
struct future_trait<timing::delay, void>
: public future_base<future<timing::delay, void>>
{
using value_type = void;
using result_type = future_result<value_type>;

template<typename X_future>
static inline auto poll(X_future& self);
public: /* future */
/**
* @brief Poll the result from the future.
*/
inline result_type poll();
};

}
} }

+ 7
- 14
include/asyncpp/timing/delay.inl 查看文件

@@ -43,26 +43,19 @@ namespace timing {
_deadline = asyncpp::now() + p_duration;
}

} }

namespace asyncpp
{

/* future_impl for timing::delay */

template<typename X_future>
auto future_trait<timing::delay, void>
::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();
}

}
} }

+ 2
- 5
include/asyncpp/timing/interval.h 查看文件

@@ -9,16 +9,13 @@
namespace asyncpp {
namespace timing {

struct interval
struct interval final
{
public:
using delay_future_type = future<delay>;

public:
friend struct stream_trait<interval, void>;

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.



+ 5
- 5
include/asyncpp/timing/interval.inl 查看文件

@@ -22,7 +22,7 @@ namespace timing {
const time_point& p_at,
const asyncpp::duration<T_base, T_ratio>& 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();
}


+ 22
- 25
include/asyncpp/timing/timeout.h 查看文件

@@ -21,21 +21,27 @@ namespace timing {
inline timeout_exception();
};

struct tag_timeout
{ };

template<typename T_inner>
struct timeout
struct timeout final
: public std::conditional_t<
is_future_v<T_inner>,
base_future<typename std::decay_t<T_inner>::value_type, timeout<T_inner>>,
tag_timeout>
{
public:
using inner_type = T_inner;
using delay_future_type = future<delay>;
using inner_type = T_inner;
using value_type = typename std::decay_t<inner_type>::value_type;

public:
friend struct stream_trait<timeout, void>;
friend struct future_trait<timeout, void>;

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<typename X_base, typename X_ratio>
inline void reset(
const duration<X_base, X_ratio>& p_timeout);

public: /* future */
/**
* @brief Poll the result from the future.
*/
template<
typename X = std::decay_t<inner_type>,
typename = std::enable_if_t<is_future_v<X>>>
inline auto poll();
};

} }
@@ -59,24 +74,6 @@ namespace timing {
namespace asyncpp
{

/* future_trait for timing::timeout */

template<typename T_inner>
struct future_trait<
timing::timeout<T_inner>,
std::enable_if_t<is_future_v<T_inner>>
>
: public future_base<future<timing::timeout<T_inner>, void>>
{
using inner_type = T_inner;
using timeout_type = timing::timeout<inner_type>;
using value_type = typename inner_type::value_type;
using result_type = typename inner_type::result_type;

template<typename X_future>
static inline result_type poll(X_future& self);
};

/* stream_trait for timing::timeout */

template<typename T_inner>


+ 31
- 27
include/asyncpp/timing/timeout.inl 查看文件

@@ -15,55 +15,59 @@ namespace timing {

/* timer */

template<typename T_inner>
template<typename X_inner, typename X_base, typename X_ratio>
template<
typename T_inner>
template<
typename X_inner,
typename X_base,
typename X_ratio>
timeout<T_inner>
::timeout(
X_inner&& p_inner,
const duration<X_base, X_ratio>& p_duration)
: _inner (std::forward<X_inner>(p_inner))
, _timeout (p_duration)
, _delay (as_future(delay(asyncpp::now() + p_duration)))
, _delay (asyncpp::now() + p_duration)
{ }

template<typename T_inner>
template<typename X_base, typename X_ratio>
template<
typename T_inner>
template<
typename X_base,
typename X_ratio>
void timeout<T_inner>
::reset(const duration<X_base, X_ratio>& 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<typename T_inner>
template<typename X_future>
typename T_inner::result_type
future_trait<
timing::timeout<T_inner>,
std::enable_if_t<is_future_v<T_inner>>
>
::poll(X_future& self)
template<
typename T_inner>
template<
typename X,
typename>
auto timeout<T_inner>
::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<typename T_inner>
@@ -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;


+ 11
- 40
test/asyncpp/core/future_tests.cpp 查看文件

@@ -2,43 +2,14 @@

#include <asyncpp.h>

#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<delay, void>
: public future_base<future<delay, void>>
{
using value_type = int&;

template<typename T_future>
static inline auto poll(T_future& self)
{
using result_type = future_result<value_type>;

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);
}

+ 3
- 31
test/asyncpp/core/task_tests.cpp 查看文件

@@ -2,42 +2,14 @@

#include <asyncpp.h>

#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<delay, void>
: public future_base<future<delay, void>>
{
using value_type = int&;

template<typename T_future>
static inline auto poll(T_future& self)
{
using result_type = future_result<value_type>;

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());


+ 22
- 25
test/asyncpp/executor/current_thread_tests.cpp 查看文件

@@ -11,9 +11,29 @@ using namespace ::testing;
using namespace ::asyncpp;

struct test
: public base_future<void, test>
{
public:
using value_type = void;
using this_type = test;
using base_future_type = base_future<void, this_type>;
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<test, void>
: public future_base<future<test, void>>
{
using value_type = void;
using result_type = future_result<value_type>;

template<typename X_future>
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<runtime_mock> m;
executor::current_thread<StrictMock<runtime_mock>&> 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)


+ 1
- 2
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());



+ 22
- 20
test/asyncpp/timing/timeout_tests.cpp 查看文件

@@ -10,28 +10,31 @@ using namespace ::asyncpp;
using namespace ::asyncpp::timing;

struct test
: public base_future<int, test>
{
public:
using value_type = int;
using this_type = test;
using base_future_type = base_future<value_type, this_type>;

public:
int i;
};

namespace asyncpp
{
inline test(int p_i)
: i(p_i)
{ }

template<>
struct future_trait<test, void>
: public future_base<future<test, void>>
public:
inline result_type poll()
{
using value_type = int;
using result_type = future_result<value_type>;
return i
? result_type::ready(i)
: result_type::not_ready();
}
};

template<typename X_future>
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<test, void>
@@ -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())


+ 4
- 8
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<delay_future_type>(timing::delay(std::chrono::seconds(10)));
auto f2 = std::make_unique<delay_future_type>(timing::delay(std::chrono::seconds(20)));
auto f3 = std::make_unique<delay_future_type>(timing::delay(std::chrono::seconds(30)));
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));

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<timing::delay>()));

time_point x;
InSequence seq;
StrictMock<now_mock> nm;
@@ -102,7 +98,7 @@ TEST(timer_tests, idle)

EXPECT_CALL(nm, now);

auto f = std::make_unique<delay_future_type>(timing::delay(time_point(std::chrono::seconds(10))));
auto f = std::make_unique<timing::delay>(time_point(std::chrono::seconds(10)));
f->poll();

EXPECT_CALL(nm, now);


+ 33
- 0
test/helper/test_delay.h 查看文件

@@ -0,0 +1,33 @@
#pragma once

#include <asyncpp.h>

struct test_delay final
: public asyncpp::base_future<int&, test_delay>
{
public:
using value_type = int&;
using this_type = test_delay;
using base_future_type = base_future<value_type, this_type>;
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();
}
};

Loading…
取消
儲存