Browse Source

boost::any作为可选,用来替换std::any

进一步减少使用C++17的语法
tags/v2.9.7
tearshark 5 years ago
parent
commit
ec11d549ef
5 changed files with 101 additions and 40 deletions
  1. 1
    1
      librf/librf.h
  2. 1
    1
      librf/src/when.cpp
  3. 88
    27
      librf/src/when.h
  4. 10
    10
      tutorial/test_async_when_all.cpp
  5. 1
    1
      vs_proj/librf.vcxproj

+ 1
- 1
librf/librf.h View File

#include "src/channel.h" #include "src/channel.h"
#include "src/scheduler.h" #include "src/scheduler.h"
#include "src/sleep.h" #include "src/sleep.h"
#if _HAS_CXX17
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
#include "src/when.h" #include "src/when.h"
#endif #endif

+ 1
- 1
librf/src/when.cpp View File

#include "_awaker.h" #include "_awaker.h"
#if _HAS_CXX17
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
#include "when.h" #include "when.h"
#include <assert.h> #include <assert.h>

+ 88
- 27
librf/src/when.h View File

#pragma once #pragma once
#include "_awaker.h" #include "_awaker.h"
#if RESUMEF_USE_BOOST_ANY
#include <boost/any.hpp>
namespace resumef
{
using any_t = boost::any;
using boost::any_cast;
}
#else
#include <any> #include <any>
namespace resumef
{
using any_t = std::any;
using std::any_cast;
}
#endif
//纠结过when_any的返回值,是选用index + std::any,还是选用std::variant<>。最终选择了std::any。 //纠结过when_any的返回值,是选用index + std::any,还是选用std::variant<>。最终选择了std::any。
//std::variant<>存在第一个元素不能默认构造的问题,需要使用std::monostate来占位,导致下标不是从0开始。 //std::variant<>存在第一个元素不能默认构造的问题,需要使用std::monostate来占位,导致下标不是从0开始。
inline future_vt operator ()() const inline future_vt operator ()() const
{ {
if constexpr(std::is_same_v<future_type, future_vt>)
{
co_await _f;
_val.get() = std::ignore;
}
else
{
_val.get() = co_await _f;
}
_val.get() = co_await _f;
_e->signal();
}
};
template<class _Ty>
struct when_all_functor<future_vt, _Ty>
{
using value_type = _Ty;
using future_type = future_vt;
when_impl_ptr _e;
mutable future_type _f;
mutable std::reference_wrapper<value_type> _val;
when_all_functor(const detail::when_impl_ptr & e, future_type f, value_type & v)
: _e(e)
, _f(std::move(f))
, _val(v)
{}
when_all_functor(when_all_functor &&) noexcept = default;
when_all_functor & operator = (const when_all_functor &) = default;
when_all_functor & operator = (when_all_functor &&) = default;
inline future_vt operator ()() const
{
co_await _f;
_val.get() = std::ignore;
_e->signal(); _e->signal();
} }
}; };
return awaitable.get_future(); return awaitable.get_future();
} }
using when_any_pair = std::pair<intptr_t, std::any>;
using when_any_pair = std::pair<intptr_t, any_t>;
using when_any_result_ptr = std::shared_ptr<when_any_pair>; using when_any_result_ptr = std::shared_ptr<when_any_pair>;
template<class _Fty> template<class _Fty>
{ {
if (_val->first < 0) if (_val->first < 0)
{ {
if constexpr(std::is_same_v<future_type, future_vt>)
auto tval = co_await _f;
if (_val->first < 0)
{ {
co_await _f;
if (_val->first < 0)
{
_val->first = _Idx;
_e->signal();
}
_val->first = _Idx;
_val->second = std::move(tval);
_e->signal();
} }
else
}
else
{
co_await _f;
}
}
};
template<>
struct when_any_functor<future_vt>
{
using value_type = when_any_pair;
using future_type = future_vt;
when_impl_ptr _e;
mutable future_type _f;
mutable when_any_result_ptr _val;
intptr_t _Idx;
when_any_functor(const when_impl_ptr & e, future_type f, const when_any_result_ptr & v, intptr_t idx)
: _e(e)
, _f(std::move(f))
, _val(v)
, _Idx(idx)
{
assert(idx >= 0);
}
when_any_functor(when_any_functor &&) noexcept = default;
when_any_functor & operator = (const when_any_functor &) = default;
when_any_functor & operator = (when_any_functor &&) = default;
inline future_vt operator ()() const
{
if (_val->first < 0)
{
co_await _f;
if (_val->first < 0)
{ {
auto tval = co_await _f;
if (_val->first < 0)
{
_val->first = _Idx;
_val->second = std::move(tval);
_e->signal();
}
_val->first = _Idx;
_e->signal();
} }
} }
else else
template<class... _Fty> template<class... _Fty>
auto when_any(scheduler & s, _Fty&&... f) -> future_t<detail::when_any_pair> auto when_any(scheduler & s, _Fty&&... f) -> future_t<detail::when_any_pair>
{ {
auto vals = std::make_shared<detail::when_any_pair>(-1, std::any{});
auto vals = std::make_shared<detail::when_any_pair>(-1, any_t{});
return detail::when_any_count(sizeof...(_Fty) ? 1 : 0, vals, s, std::forward<_Fty>(f)...); return detail::when_any_count(sizeof...(_Fty) ? 1 : 0, vals, s, std::forward<_Fty>(f)...);
} }
template<class _Iter, typename _Fty = decltype(*std::declval<_Iter>())> template<class _Iter, typename _Fty = decltype(*std::declval<_Iter>())>
auto when_any(scheduler & s, _Iter begin, _Iter end) -> future_t<detail::when_any_pair> auto when_any(scheduler & s, _Iter begin, _Iter end) -> future_t<detail::when_any_pair>
{ {
auto vals = std::make_shared<detail::when_any_pair>(-1, std::any{});
auto vals = std::make_shared<detail::when_any_pair>(-1, any_t{});
return detail::when_any_range((begin != end) ? 1 : 0, vals, s, begin, end); return detail::when_any_range((begin != end) ? 1 : 0, vals, s, begin, end);
} }

+ 10
- 10
tutorial/test_async_when_all.cpp View File

#include "librf.h" #include "librf.h"
#if _HAS_CXX17
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
using namespace resumef; using namespace resumef;
}()); }());
if (vals.first == 0) if (vals.first == 0)
std::cout << "first done! value is " << std::any_cast<int>(vals.second) << std::endl;
std::cout << "first done! value is " << resumef::any_cast<int>(vals.second) << std::endl;
else else
std::cout << "any done! index is " << vals.first << std::endl; std::cout << "any done! index is " << vals.first << std::endl;
std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") }; std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") };
vals = co_await when_any(std::begin(v), std::end(v)); vals = co_await when_any(std::begin(v), std::end(v));
std::cout << "any range done! index is " << vals.first << ", valus is " << std::any_cast<int>(vals.second) << std::endl;
std::cout << "any range done! index is " << vals.first << ", valus is " << resumef::any_cast<int>(vals.second) << std::endl;
}; };
this_scheduler()->run_until_notask(); this_scheduler()->run_until_notask();
} }
co_await when_all(); co_await when_all();
std::cout << "when all: zero!" << std::endl << std::endl; std::cout << "when all: zero!" << std::endl << std::endl;
auto [a, b] = co_await when_all(my_sleep("a"), my_sleep_v("b"));
(void)b; //b is std::ignore
std::cout << "when all:" << a << std::endl << std::endl;
auto ab = co_await when_all(my_sleep("a"), my_sleep_v("b"));
//ab.1 is std::ignore
std::cout << "when all:" << std::get<0>(ab) << std::endl << std::endl;
auto c = co_await my_sleep("c"); auto c = co_await my_sleep("c");
std::cout << "when all:" << c << std::endl << std::endl; std::cout << "when all:" << c << std::endl << std::endl;
auto [d, e, f] = co_await when_all(my_sleep("d"), my_sleep_v("e"), my_sleep("f"));
(void)e; //e is std::ignore
std::cout << "when all:" << d << "," << f << std::endl << std::endl;
auto def = co_await when_all(my_sleep("d"), my_sleep_v("e"), my_sleep("f"));
//def.1 is std::ignore
std::cout << "when all:" << std::get<0>(def) << "," << std::get<2>(def) << std::endl << std::endl;
std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") }; std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") };
auto vals = co_await when_all(std::begin(v), std::end(v)); auto vals = co_await when_all(std::begin(v), std::end(v));
void resumable_main_when_all() void resumable_main_when_all()
{ {
#if _HAS_CXX17
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
srand((uint32_t)time(nullptr)); srand((uint32_t)time(nullptr));
test_when_any(); test_when_any();

+ 1
- 1
vs_proj/librf.vcxproj View File

<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_DEBUG_COUNTER=0;RESUMEF_ENABLE_MULT_SCHEDULER=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_DEBUG_COUNTER=0;RESUMEF_ENABLE_MULT_SCHEDULER=1;RESUMEF_USE_BOOST_ANY=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions> <AdditionalOptions>/await</AdditionalOptions>

Loading…
Cancel
Save