* Refactored namespaces (trait classes are postfixed with '_trait'; internal namespaces are prefixed with __)master
@@ -17,9 +17,9 @@ namespace asyncpp | |||
{ | |||
using object_type = T_object; | |||
using clean_object_type = std::decay_t<object_type>; | |||
using impl_type = impl::future<clean_object_type>; | |||
using value_type = typename impl_type::value_type; | |||
using result_type = result<value_type>; | |||
using trait_type = future_trait<clean_object_type>; | |||
using value_type = typename trait_type::value_type; | |||
using result_type = future_result<value_type>; | |||
object_type ref; | |||
@@ -8,37 +8,34 @@ | |||
namespace asyncpp | |||
{ | |||
namespace impl | |||
/* future_base */ | |||
template<typename T_impl> | |||
template<typename X_future, typename X_lambda> | |||
auto future_base<T_impl> | |||
::map(X_future&& self, X_lambda&& p_lambda) | |||
{ | |||
using future_type = X_future; | |||
using lambda_type = X_lambda; | |||
using map_type = __future::map_impl<future_type, lambda_type>; | |||
return as_future(map_type( | |||
std::forward<X_future>(self), | |||
std::forward<X_lambda>(p_lambda))); | |||
} | |||
template<typename T_impl> | |||
template<typename X_future, typename X_lambda> | |||
auto future_base<T_impl> | |||
::map(X_future&& self, X_lambda&& p_lambda) | |||
{ | |||
using future_type = X_future; | |||
using lambda_type = X_lambda; | |||
using map_type = future_impl::map_impl<future_type, lambda_type>; | |||
return as_future(map_type( | |||
std::forward<X_future>(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) | |||
{ | |||
using future_type = X_future; | |||
using lambda_type = X_lambda; | |||
using and_then_type = future_impl::and_then_impl<future_type, lambda_type>; | |||
return as_future(and_then_type( | |||
std::forward<X_future>(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) | |||
{ | |||
using future_type = X_future; | |||
using lambda_type = X_lambda; | |||
using and_then_type = __future::and_then_impl<future_type, lambda_type>; | |||
return as_future(and_then_type( | |||
std::forward<X_future>(self), | |||
std::forward<X_lambda>(p_lambda))); | |||
} | |||
/* future */ | |||
@@ -59,7 +56,7 @@ namespace asyncpp | |||
typename future<T_value, T_impl>::result_type | |||
future<T_value, T_impl> | |||
::poll() | |||
{ return impl_type::poll(*this); } | |||
{ return trait_type::poll(*this); } | |||
template< | |||
typename T_value, | |||
@@ -68,7 +65,7 @@ namespace asyncpp | |||
typename X_lambda> | |||
auto future<T_value, T_impl> | |||
::map(X_lambda&& p_lambda) | |||
{ return impl_type::map(std::move(*this), std::forward<X_lambda>(p_lambda)); } | |||
{ return trait_type::map(std::move(*this), std::forward<X_lambda>(p_lambda)); } | |||
template< | |||
typename T_value, | |||
@@ -77,7 +74,7 @@ namespace asyncpp | |||
typename X_lambda> | |||
auto future<T_value, T_impl> | |||
::and_then(X_lambda&& p_lambda) | |||
{ return impl_type::and_then(std::move(*this), std::forward<X_lambda>(p_lambda)); } | |||
{ return trait_type::and_then(std::move(*this), std::forward<X_lambda>(p_lambda)); } | |||
/* misc */ | |||
@@ -3,30 +3,25 @@ | |||
namespace asyncpp | |||
{ | |||
namespace impl | |||
template<typename T_impl> | |||
struct future_base | |||
{ | |||
template<typename T_future> | |||
static inline auto poll(T_future& self) = delete; | |||
template<typename T_impl> | |||
struct future_base | |||
{ | |||
template<typename T_future> | |||
static inline auto poll(T_future& self) = delete; | |||
template<typename T_future, typename T_lambda> | |||
static inline auto map(T_future&& self, T_lambda&& p_lambda); | |||
template<typename T_future, typename T_lambda> | |||
static inline auto map(T_future&& self, T_lambda&& p_lambda); | |||
template<typename T_future, typename T_lambda> | |||
static inline auto and_then(T_future&& self, T_lambda&& p_lambda); | |||
}; | |||
template<typename T_future, typename T_lambda> | |||
static inline auto and_then(T_future&& self, T_lambda&& p_lambda); | |||
}; | |||
template<typename T, typename = void> | |||
struct future; | |||
} | |||
template<typename T, typename = void> | |||
struct future_trait; | |||
template< | |||
typename T_object, | |||
typename T_impl = impl::future<std::decay_t<T_object>>> | |||
typename T_impl = future_trait<std::decay_t<T_object>>> | |||
struct future; | |||
/** | |||
@@ -3,7 +3,7 @@ | |||
#include <memory> | |||
namespace asyncpp { | |||
namespace future_impl { | |||
namespace __future { | |||
template< | |||
typename T_future, | |||
@@ -5,47 +5,46 @@ | |||
namespace asyncpp | |||
{ | |||
namespace impl | |||
/* future_trait for ant_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 inner_future_type = typename and_then_type::inner_future_type; | |||
using value_type = typename inner_future_type::value_type; | |||
using result_type = typename inner_future_type::result_type; | |||
template< | |||
typename T_future, | |||
typename T_lambda> | |||
struct future<future_impl::and_then_impl<T_future, T_lambda>, void> | |||
: public future_base<future<future_impl::and_then_impl<T_future, T_lambda>, void>> | |||
template<typename X_future> | |||
static inline auto poll(X_future& self) | |||
{ | |||
using and_then_type = future_impl::and_then_impl<T_future, T_lambda>; | |||
using inner_future_type = typename and_then_type::inner_future_type; | |||
using value_type = typename inner_future_type::value_type; | |||
using result_type = typename inner_future_type::result_type; | |||
template<typename X_future> | |||
static inline auto poll(X_future& self) | |||
while (true) | |||
{ | |||
while (true) | |||
if (self.ref.inner) | |||
{ | |||
if (self.ref.inner) | |||
{ | |||
return self.ref.inner->poll(); | |||
} | |||
else | |||
{ | |||
auto r = self.ref.outer.poll(); | |||
if (!r) | |||
return result_type::not_ready(); | |||
return self.ref.inner->poll(); | |||
} | |||
else | |||
{ | |||
auto r = self.ref.outer.poll(); | |||
if (!r) | |||
return result_type::not_ready(); | |||
self.ref.inner = std::make_unique<inner_future_type>(as_future(self.ref.lambda(*r))); | |||
} | |||
self.ref.inner = std::make_unique<inner_future_type>(as_future(self.ref.lambda(*r))); | |||
} | |||
} | |||
}; | |||
} | |||
} | |||
}; | |||
} | |||
namespace asyncpp { | |||
namespace future_impl { | |||
namespace __future { | |||
/* and_then_impl */ | |||
template< | |||
typename T_future, | |||
@@ -1,7 +1,7 @@ | |||
#pragma once | |||
namespace asyncpp { | |||
namespace future_impl { | |||
namespace __future { | |||
template< | |||
typename T_future, | |||
@@ -5,38 +5,37 @@ | |||
namespace asyncpp | |||
{ | |||
namespace impl | |||
/* 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>())); | |||
template< | |||
typename T_future, | |||
typename T_lambda> | |||
struct future<future_impl::map_impl<T_future, T_lambda>, void> | |||
: public future_base<future<future_impl::map_impl<T_future, T_lambda>, void>> | |||
template<typename X_future> | |||
static inline auto poll(X_future& self) | |||
{ | |||
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) | |||
{ | |||
using result_type = result<value_type>; | |||
auto r = self.ref.future.poll(); | |||
return r | |||
? result_type::ready(self.ref.lambda(*r)) | |||
: result_type::not_ready(); | |||
} | |||
}; | |||
} | |||
auto r = self.ref.future.poll(); | |||
return r | |||
? result_type::ready(self.ref.lambda(*r)) | |||
: result_type::not_ready(); | |||
} | |||
}; | |||
} | |||
namespace asyncpp { | |||
namespace future_impl { | |||
namespace __future { | |||
/* map_impl */ | |||
template< | |||
typename T_future, | |||
@@ -5,7 +5,15 @@ | |||
namespace asyncpp | |||
{ | |||
namespace impl | |||
enum class result_status | |||
{ | |||
unknown = 0, | |||
not_ready, | |||
ready, | |||
done, | |||
}; | |||
namespace __impl | |||
{ | |||
struct result_not_ready | |||
@@ -25,94 +33,104 @@ namespace asyncpp | |||
inline result_ready(T_args&&... p_args); | |||
}; | |||
template<bool for_stream, typename T_value> | |||
struct result | |||
{ | |||
public: | |||
using value_type = T_value; | |||
using not_ready_type = result_not_ready; | |||
using ready_type = result_ready<value_type>; | |||
using done_type = result_done; | |||
using storage_type = std::conditional_t< | |||
for_stream, | |||
std::variant<not_ready_type, ready_type, done_type>, | |||
std::variant<not_ready_type, ready_type>>; | |||
using clean_value_type = std::remove_reference_t<value_type>; | |||
using pointer_type = clean_value_type*; | |||
using reference_type = clean_value_type&; | |||
using const_pointer_type = clean_value_type const *; | |||
using const_reference_type = clean_value_type const &; | |||
private: | |||
storage_type _storage; //!< Stores the actual result. | |||
private: | |||
/** | |||
* @brief Constructor. | |||
*/ | |||
inline result(storage_type&& p_storage); | |||
public: | |||
/** | |||
* @brief returns a result that is not ready. | |||
*/ | |||
static inline auto& not_ready(); | |||
/** | |||
* @brief returns a result that is not ready. | |||
*/ | |||
template<typename... X_args> | |||
static inline auto ready(X_args&&... p_args); | |||
/** | |||
* @brief returns a result that is not ready. | |||
*/ | |||
template< | |||
bool X = for_stream, | |||
typename = std::enable_if_t<X>> | |||
static inline auto& done(); | |||
public: | |||
/** | |||
* @brief Get the status of the result. | |||
*/ | |||
template< | |||
bool X = for_stream, | |||
typename = std::enable_if_t<X>> | |||
inline result_status status() const; | |||
/** | |||
* @brief Check if the result is not ready (is pending). | |||
*/ | |||
inline bool is_not_ready() const; | |||
/** | |||
* @brief Check if the result is ready (has a value). | |||
*/ | |||
inline bool is_ready() const; | |||
/** | |||
* @brief Check if the result is done (stream is finished). | |||
*/ | |||
template< | |||
bool X = for_stream, | |||
typename = std::enable_if_t<X>> | |||
inline bool is_done() const; | |||
/** | |||
* @brief Get the value of the result. | |||
*/ | |||
inline reference_type value(); | |||
/** | |||
* @brief Get the value of the result. | |||
*/ | |||
inline const_reference_type value() const; | |||
public: | |||
inline operator bool() const; | |||
inline pointer_type operator-> (); | |||
inline reference_type operator* (); | |||
inline const_pointer_type operator-> () const; | |||
inline const_reference_type operator* () const; | |||
}; | |||
} | |||
enum class result_status | |||
{ | |||
unknown = 0, | |||
not_ready, | |||
ready, | |||
done, | |||
}; | |||
template<typename T_value> | |||
using future_result = __impl::result<false, T_value>; | |||
template<typename T_value> | |||
struct result | |||
{ | |||
public: | |||
using value_type = T_value; | |||
using not_ready_type = impl::result_not_ready; | |||
using ready_type = impl::result_ready<value_type>; | |||
using done_type = impl::result_done; | |||
using storage_type = std::variant<not_ready_type, ready_type, done_type>; | |||
using clean_value_type = std::remove_reference_t<value_type>; | |||
using pointer_type = clean_value_type*; | |||
using reference_type = clean_value_type&; | |||
using const_pointer_type = clean_value_type const *; | |||
using const_reference_type = clean_value_type const &; | |||
private: | |||
storage_type _storage; //!< Stores the actual result. | |||
private: | |||
/** | |||
* @brief Constructor. | |||
*/ | |||
inline result(storage_type&& p_storage); | |||
public: | |||
/** | |||
* @brief returns a result that is not ready. | |||
*/ | |||
static inline auto& not_ready(); | |||
/** | |||
* @brief returns a result that is not ready. | |||
*/ | |||
template<typename... X_args> | |||
static inline auto ready(X_args&&... p_args); | |||
/** | |||
* @brief returns a result that is not ready. | |||
*/ | |||
static inline auto& done(); | |||
public: | |||
/** | |||
* @brief Get the status of the result. | |||
*/ | |||
inline result_status status() const; | |||
/** | |||
* @brief Check if the result is not ready (is pending). | |||
*/ | |||
inline bool is_not_ready() const; | |||
/** | |||
* @brief Check if the result is ready (has a value). | |||
*/ | |||
inline bool is_ready() const; | |||
/** | |||
* @brief Check if the result is done (stream is finished). | |||
*/ | |||
inline bool is_done() const; | |||
/** | |||
* @brief Get the value of the result. | |||
*/ | |||
inline reference_type value(); | |||
/** | |||
* @brief Get the value of the result. | |||
*/ | |||
inline const_reference_type value() const; | |||
public: | |||
inline operator bool() const; | |||
inline pointer_type operator-> (); | |||
inline reference_type operator* (); | |||
inline const_pointer_type operator-> () const; | |||
inline const_reference_type operator* () const; | |||
}; | |||
using stream_result = __impl::result<true, T_value>; | |||
} |
@@ -5,7 +5,7 @@ | |||
namespace asyncpp | |||
{ | |||
namespace impl | |||
namespace __impl | |||
{ | |||
/* result_ready */ | |||
@@ -17,163 +17,175 @@ namespace asyncpp | |||
: value(std::forward<T_args>(p_args)...) | |||
{ } | |||
} | |||
/* result */ | |||
template<typename T_value> | |||
result<T_value> | |||
::result(storage_type&& p_storage) | |||
: _storage(std::move(p_storage)) | |||
{ } | |||
template<typename T_value> | |||
auto& result<T_value> | |||
::not_ready() | |||
{ | |||
static const result ret(storage_type(not_ready_type { })); | |||
return ret; | |||
} | |||
template<typename T_value> | |||
template<typename... X_args> | |||
auto result<T_value> | |||
::ready(X_args&&... p_args) | |||
{ return result(storage_type(ready_type(std::forward<X_args>(p_args)...))); } | |||
template<typename T_value> | |||
auto& result<T_value> | |||
::done() | |||
{ | |||
static const result ret(storage_type(done_type { })); | |||
return ret; | |||
} | |||
template<typename T_value> | |||
result_status result<T_value> | |||
::status() const | |||
{ | |||
if (is_not_ready()) | |||
return result_status::not_ready; | |||
else if (is_ready()) | |||
return result_status::ready; | |||
else if (is_done()) | |||
return result_status::done; | |||
else | |||
return result_status::unknown; | |||
} | |||
template<typename T_value> | |||
bool result<T_value> | |||
::is_not_ready() const | |||
{ return std::holds_alternative<not_ready_type>(_storage); } | |||
template<typename T_value> | |||
bool result<T_value> | |||
::is_ready() const | |||
{ return std::holds_alternative<ready_type>(_storage); } | |||
template<typename T_value> | |||
bool result<T_value> | |||
::is_done() const | |||
{ return std::holds_alternative<done_type>(_storage); } | |||
template<typename T_value> | |||
typename result<T_value>::reference_type | |||
result<T_value> | |||
::value() | |||
{ return std::get<ready_type>(_storage).value; } | |||
template<typename T_value> | |||
typename result<T_value>::const_reference_type | |||
result<T_value> | |||
::value() const | |||
{ return std::get<ready_type>(_storage).value; } | |||
template<typename T_value> | |||
result<T_value> | |||
::operator bool() const | |||
{ return is_ready(); } | |||
template<typename T_value> | |||
typename result<T_value>::pointer_type | |||
result<T_value> | |||
::operator-> () | |||
{ return &value(); } | |||
template<typename T_value> | |||
typename result<T_value>::reference_type | |||
result<T_value> | |||
::operator* () | |||
{ return value(); } | |||
template<typename T_value> | |||
typename result<T_value>::const_pointer_type | |||
result<T_value> | |||
::operator-> () const | |||
{ return &value(); } | |||
template<typename T_value> | |||
typename result<T_value>::const_reference_type | |||
result<T_value> | |||
::operator* () const | |||
{ return value(); } | |||
template<> | |||
struct result<void> | |||
{ | |||
public: | |||
using value_type = void; | |||
private: | |||
result_status _status; | |||
/* result */ | |||
private: | |||
inline result(result_status p_status) | |||
: _status(p_status) | |||
template<bool for_stream, typename T_value> | |||
result<for_stream, T_value> | |||
::result(storage_type&& p_storage) | |||
: _storage(std::move(p_storage)) | |||
{ } | |||
public: | |||
static inline auto& not_ready() | |||
template<bool for_stream, typename T_value> | |||
auto& result<for_stream, T_value> | |||
::not_ready() | |||
{ | |||
static const result ret { result_status::not_ready }; | |||
static const result ret(storage_type(not_ready_type { })); | |||
return ret; | |||
} | |||
template<bool for_stream, typename T_value> | |||
template<typename... X_args> | |||
static inline auto& ready(X_args&&... p_args) | |||
auto result<for_stream, T_value> | |||
::ready(X_args&&... p_args) | |||
{ return result(storage_type(ready_type(std::forward<X_args>(p_args)...))); } | |||
template<bool for_stream, typename T_value> | |||
template<bool X, typename> | |||
auto& result<for_stream, T_value> | |||
::done() | |||
{ | |||
static const result ret { result_status::ready }; | |||
static const result ret(storage_type(done_type { })); | |||
return ret; | |||
} | |||
static inline auto& done() | |||
template<bool for_stream, typename T_value> | |||
template<bool X, typename> | |||
result_status result<for_stream, T_value> | |||
::status() const | |||
{ | |||
static const result ret { result_status::done }; | |||
return ret; | |||
if (is_not_ready()) | |||
return result_status::not_ready; | |||
else if (is_ready()) | |||
return result_status::ready; | |||
else if (is_done()) | |||
return result_status::done; | |||
else | |||
return result_status::unknown; | |||
} | |||
public: | |||
inline result_status status() const | |||
{ return _status; } | |||
inline bool is_not_ready() const | |||
{ return _status == result_status::not_ready; } | |||
inline bool is_ready() const | |||
{ return _status == result_status::ready; } | |||
template<bool for_stream, typename T_value> | |||
bool result<for_stream, T_value> | |||
::is_not_ready() const | |||
{ return std::holds_alternative<not_ready_type>(_storage); } | |||
template<bool for_stream, typename T_value> | |||
bool result<for_stream, T_value> | |||
::is_ready() const | |||
{ return std::holds_alternative<ready_type>(_storage); } | |||
template<bool for_stream, typename T_value> | |||
template<bool X, typename> | |||
bool result<for_stream, T_value> | |||
::is_done() const | |||
{ return std::holds_alternative<done_type>(_storage); } | |||
template<bool for_stream, typename T_value> | |||
typename result<for_stream, T_value>::reference_type | |||
result<for_stream, T_value> | |||
::value() | |||
{ return std::get<ready_type>(_storage).value; } | |||
template<bool for_stream, typename T_value> | |||
typename result<for_stream, T_value>::const_reference_type | |||
result<for_stream, T_value> | |||
::value() const | |||
{ return std::get<ready_type>(_storage).value; } | |||
template<bool for_stream, typename T_value> | |||
result<for_stream, T_value> | |||
::operator bool() const | |||
{ return is_ready(); } | |||
template<bool for_stream, typename T_value> | |||
typename result<for_stream, T_value>::pointer_type | |||
result<for_stream, T_value> | |||
::operator-> () | |||
{ return &value(); } | |||
template<bool for_stream, typename T_value> | |||
typename result<for_stream, T_value>::reference_type | |||
result<for_stream, T_value> | |||
::operator* () | |||
{ return value(); } | |||
template<bool for_stream, typename T_value> | |||
typename result<for_stream, T_value>::const_pointer_type | |||
result<for_stream, T_value> | |||
::operator-> () const | |||
{ return &value(); } | |||
template<bool for_stream, typename T_value> | |||
typename result<for_stream, T_value>::const_reference_type | |||
result<for_stream, T_value> | |||
::operator* () const | |||
{ return value(); } | |||
template<bool for_stream> | |||
struct result<for_stream, void> | |||
{ | |||
public: | |||
using value_type = void; | |||
inline bool is_done() const | |||
{ return _status == result_status::done; } | |||
private: | |||
result_status _status; | |||
inline void value() | |||
{ throw std::runtime_error("'void' result does not store any value!"); } | |||
private: | |||
inline result(result_status p_status) | |||
: _status(p_status) | |||
{ } | |||
inline operator bool() const | |||
{ return _status == result_status::ready; } | |||
public: | |||
static inline auto& not_ready() | |||
{ | |||
static const result ret { result_status::not_ready }; | |||
return ret; | |||
} | |||
template<typename... X_args> | |||
static inline auto& ready(X_args&&... p_args) | |||
{ | |||
static const result ret { result_status::ready }; | |||
return ret; | |||
} | |||
template< | |||
bool X = for_stream, | |||
typename = std::enable_if_t<X>> | |||
static inline auto& done() | |||
{ | |||
static const result ret { result_status::done }; | |||
return ret; | |||
} | |||
public: | |||
template< | |||
bool X = for_stream, | |||
typename = std::enable_if_t<X>> | |||
inline result_status status() const | |||
{ return _status; } | |||
inline bool is_not_ready() const | |||
{ return _status == result_status::not_ready; } | |||
inline bool is_ready() const | |||
{ return _status == result_status::ready; } | |||
template< | |||
bool X = for_stream, | |||
typename = std::enable_if_t<X>> | |||
inline bool is_done() const | |||
{ return _status == result_status::done; } | |||
inline void value() | |||
{ throw std::runtime_error("'void' result does not store any value!"); } | |||
inline operator bool() const | |||
{ return _status == result_status::ready; } | |||
inline void operator* () | |||
{ value(); } | |||
}; | |||
inline void operator* () | |||
{ value(); } | |||
}; | |||
} | |||
} |
@@ -14,29 +14,24 @@ struct delay | |||
namespace asyncpp | |||
{ | |||
namespace impl | |||
template<> | |||
struct future_trait<delay, void> | |||
: public future_base<future<delay, void>> | |||
{ | |||
using value_type = int&; | |||
template<> | |||
struct future<delay, void> | |||
: public future_base<future<delay, void>> | |||
template<typename T_future> | |||
static inline auto poll(T_future& self) | |||
{ | |||
using value_type = int&; | |||
using result_type = future_result<value_type>; | |||
template<typename T_future> | |||
static inline auto poll(T_future& self) | |||
{ | |||
using result_type = result<value_type>; | |||
if (self.ref.count >= self.ref.delay) | |||
return result_type::ready(self.ref.count); | |||
if (self.ref.count >= self.ref.delay) | |||
return result_type::ready(self.ref.count); | |||
++self.ref.count; | |||
return result_type::not_ready(); | |||
} | |||
}; | |||
} | |||
++self.ref.count; | |||
return result_type::not_ready(); | |||
} | |||
}; | |||
} | |||
@@ -46,26 +41,25 @@ TEST(future_tests, poll) | |||
auto f = as_future(d); | |||
auto r0 = f.poll(); | |||
ASSERT_EQ(result_status::not_ready, r0.status()); | |||
ASSERT_FALSE(r0); | |||
auto r1 = f.poll(); | |||
ASSERT_EQ(result_status::not_ready, r1.status()); | |||
ASSERT_FALSE(r1); | |||
auto r2 = f.poll(); | |||
ASSERT_EQ(result_status::not_ready, r2.status()); | |||
ASSERT_FALSE(r2); | |||
auto r3 = f.poll(); | |||
ASSERT_EQ(result_status::not_ready, r3.status()); | |||
ASSERT_FALSE(r3); | |||
auto r4 = f.poll(); | |||
ASSERT_EQ(result_status::not_ready, r4.status()); | |||
ASSERT_FALSE(r4); | |||
auto r = f.poll(); | |||
ASSERT_TRUE(r); | |||
ASSERT_EQ (result_status::ready, r.status()); | |||
ASSERT_EQ (5, *r); | |||
ASSERT_EQ (5, d.count); | |||
ASSERT_EQ (&*r, &d.count); | |||
ASSERT_TRUE (r); | |||
ASSERT_EQ (5, *r); | |||
ASSERT_EQ (5, d.count); | |||
ASSERT_EQ (&*r, &d.count); | |||
} | |||
TEST(future_tests, map) | |||
@@ -5,9 +5,34 @@ | |||
using namespace ::testing; | |||
using namespace ::asyncpp; | |||
TEST(result_tests, not_ready) | |||
TEST(result_tests, future_result___not_ready) | |||
{ | |||
using result_type = result<int>; | |||
using result_type = future_result<int>; | |||
auto r = result_type::not_ready(); | |||
EXPECT_TRUE (r.is_not_ready()); | |||
EXPECT_FALSE (r.is_ready()); | |||
EXPECT_FALSE (r); | |||
EXPECT_ANY_THROW(*r); | |||
} | |||
TEST(result_tests, future_result___ready) | |||
{ | |||
using result_type = future_result<int&>; | |||
int i; | |||
auto r = result_type::ready(i); | |||
EXPECT_FALSE (r.is_not_ready()); | |||
EXPECT_TRUE (r.is_ready()); | |||
EXPECT_TRUE (r); | |||
EXPECT_EQ (&*r, &i); | |||
} | |||
TEST(result_tests, stream_result___not_ready) | |||
{ | |||
using result_type = stream_result<int>; | |||
auto r = result_type::not_ready(); | |||
@@ -19,9 +44,9 @@ TEST(result_tests, not_ready) | |||
EXPECT_ANY_THROW(*r); | |||
} | |||
TEST(result_tests, ready) | |||
TEST(result_tests, stream_result___ready) | |||
{ | |||
using result_type = result<int&>; | |||
using result_type = stream_result<int&>; | |||
int i; | |||
auto r = result_type::ready(i); | |||
@@ -34,9 +59,9 @@ TEST(result_tests, ready) | |||
EXPECT_EQ (&*r, &i); | |||
} | |||
TEST(result_tests, done) | |||
TEST(result_tests, stream_result___done) | |||
{ | |||
using result_type = result<void>; | |||
using result_type = stream_result<void>; | |||
auto r = result_type::done(); | |||