Skip to content

Commit ec11d54

Browse files
author
tearshark
committed
boost::any作为可选,用来替换std::any
进一步减少使用C++17的语法
1 parent 48532d7 commit ec11d54

File tree

5 files changed

+101
-40
lines changed

5 files changed

+101
-40
lines changed

librf/librf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
#include "src/channel.h"
2222
#include "src/scheduler.h"
2323
#include "src/sleep.h"
24-
#if _HAS_CXX17
24+
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
2525
#include "src/when.h"
2626
#endif

librf/src/when.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "_awaker.h"
22

3-
#if _HAS_CXX17
3+
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
44

55
#include "when.h"
66
#include <assert.h>

librf/src/when.h

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
#pragma once
22

33
#include "_awaker.h"
4+
#if RESUMEF_USE_BOOST_ANY
5+
#include <boost/any.hpp>
6+
namespace resumef
7+
{
8+
using any_t = boost::any;
9+
using boost::any_cast;
10+
}
11+
#else
412
#include <any>
13+
namespace resumef
14+
{
15+
using any_t = std::any;
16+
using std::any_cast;
17+
}
18+
#endif
519

620
//纠结过when_any的返回值,是选用index + std::any,还是选用std::variant<>。最终选择了std::any。
721
//std::variant<>存在第一个元素不能默认构造的问题,需要使用std::monostate来占位,导致下标不是从0开始。
@@ -97,16 +111,34 @@ namespace resumef
97111

98112
inline future_vt operator ()() const
99113
{
100-
if constexpr(std::is_same_v<future_type, future_vt>)
101-
{
102-
co_await _f;
103-
_val.get() = std::ignore;
104-
}
105-
else
106-
{
107-
_val.get() = co_await _f;
108-
}
114+
_val.get() = co_await _f;
115+
_e->signal();
116+
}
117+
};
109118

119+
template<class _Ty>
120+
struct when_all_functor<future_vt, _Ty>
121+
{
122+
using value_type = _Ty;
123+
using future_type = future_vt;
124+
125+
when_impl_ptr _e;
126+
mutable future_type _f;
127+
mutable std::reference_wrapper<value_type> _val;
128+
129+
when_all_functor(const detail::when_impl_ptr & e, future_type f, value_type & v)
130+
: _e(e)
131+
, _f(std::move(f))
132+
, _val(v)
133+
{}
134+
when_all_functor(when_all_functor &&) noexcept = default;
135+
when_all_functor & operator = (const when_all_functor &) = default;
136+
when_all_functor & operator = (when_all_functor &&) = default;
137+
138+
inline future_vt operator ()() const
139+
{
140+
co_await _f;
141+
_val.get() = std::ignore;
110142
_e->signal();
111143
}
112144
};
@@ -180,7 +212,7 @@ namespace resumef
180212
return awaitable.get_future();
181213
}
182214

183-
using when_any_pair = std::pair<intptr_t, std::any>;
215+
using when_any_pair = std::pair<intptr_t, any_t>;
184216
using when_any_result_ptr = std::shared_ptr<when_any_pair>;
185217

186218
template<class _Fty>
@@ -210,24 +242,53 @@ namespace resumef
210242
{
211243
if (_val->first < 0)
212244
{
213-
if constexpr(std::is_same_v<future_type, future_vt>)
245+
auto tval = co_await _f;
246+
if (_val->first < 0)
214247
{
215-
co_await _f;
216-
if (_val->first < 0)
217-
{
218-
_val->first = _Idx;
219-
_e->signal();
220-
}
248+
_val->first = _Idx;
249+
_val->second = std::move(tval);
250+
_e->signal();
221251
}
222-
else
252+
}
253+
else
254+
{
255+
co_await _f;
256+
}
257+
}
258+
};
259+
260+
template<>
261+
struct when_any_functor<future_vt>
262+
{
263+
using value_type = when_any_pair;
264+
using future_type = future_vt;
265+
266+
when_impl_ptr _e;
267+
mutable future_type _f;
268+
mutable when_any_result_ptr _val;
269+
intptr_t _Idx;
270+
271+
when_any_functor(const when_impl_ptr & e, future_type f, const when_any_result_ptr & v, intptr_t idx)
272+
: _e(e)
273+
, _f(std::move(f))
274+
, _val(v)
275+
, _Idx(idx)
276+
{
277+
assert(idx >= 0);
278+
}
279+
when_any_functor(when_any_functor &&) noexcept = default;
280+
when_any_functor & operator = (const when_any_functor &) = default;
281+
when_any_functor & operator = (when_any_functor &&) = default;
282+
283+
inline future_vt operator ()() const
284+
{
285+
if (_val->first < 0)
286+
{
287+
co_await _f;
288+
if (_val->first < 0)
223289
{
224-
auto tval = co_await _f;
225-
if (_val->first < 0)
226-
{
227-
_val->first = _Idx;
228-
_val->second = std::move(tval);
229-
_e->signal();
230-
}
290+
_val->first = _Idx;
291+
_e->signal();
231292
}
232293
}
233294
else
@@ -340,7 +401,7 @@ namespace resumef
340401
template<class... _Fty>
341402
auto when_any(scheduler & s, _Fty&&... f) -> future_t<detail::when_any_pair>
342403
{
343-
auto vals = std::make_shared<detail::when_any_pair>(-1, std::any{});
404+
auto vals = std::make_shared<detail::when_any_pair>(-1, any_t{});
344405

345406
return detail::when_any_count(sizeof...(_Fty) ? 1 : 0, vals, s, std::forward<_Fty>(f)...);
346407
}
@@ -352,7 +413,7 @@ namespace resumef
352413
template<class _Iter, typename _Fty = decltype(*std::declval<_Iter>())>
353414
auto when_any(scheduler & s, _Iter begin, _Iter end) -> future_t<detail::when_any_pair>
354415
{
355-
auto vals = std::make_shared<detail::when_any_pair>(-1, std::any{});
416+
auto vals = std::make_shared<detail::when_any_pair>(-1, any_t{});
356417

357418
return detail::when_any_range((begin != end) ? 1 : 0, vals, s, begin, end);
358419
}

tutorial/test_async_when_all.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#include "librf.h"
1010

11-
#if _HAS_CXX17
11+
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
1212

1313
using namespace resumef;
1414

@@ -43,7 +43,7 @@ void test_when_any()
4343
}());
4444

4545
if (vals.first == 0)
46-
std::cout << "first done! value is " << std::any_cast<int>(vals.second) << std::endl;
46+
std::cout << "first done! value is " << resumef::any_cast<int>(vals.second) << std::endl;
4747
else
4848
std::cout << "any done! index is " << vals.first << std::endl;
4949

@@ -61,7 +61,7 @@ void test_when_any()
6161

6262
std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") };
6363
vals = co_await when_any(std::begin(v), std::end(v));
64-
std::cout << "any range done! index is " << vals.first << ", valus is " << std::any_cast<int>(vals.second) << std::endl;
64+
std::cout << "any range done! index is " << vals.first << ", valus is " << resumef::any_cast<int>(vals.second) << std::endl;
6565
};
6666
this_scheduler()->run_until_notask();
6767
}
@@ -92,16 +92,16 @@ void test_when_all()
9292
co_await when_all();
9393
std::cout << "when all: zero!" << std::endl << std::endl;
9494

95-
auto [a, b] = co_await when_all(my_sleep("a"), my_sleep_v("b"));
96-
(void)b; //b is std::ignore
97-
std::cout << "when all:" << a << std::endl << std::endl;
95+
auto ab = co_await when_all(my_sleep("a"), my_sleep_v("b"));
96+
//ab.1 is std::ignore
97+
std::cout << "when all:" << std::get<0>(ab) << std::endl << std::endl;
9898

9999
auto c = co_await my_sleep("c");
100100
std::cout << "when all:" << c << std::endl << std::endl;
101101

102-
auto [d, e, f] = co_await when_all(my_sleep("d"), my_sleep_v("e"), my_sleep("f"));
103-
(void)e; //e is std::ignore
104-
std::cout << "when all:" << d << "," << f << std::endl << std::endl;
102+
auto def = co_await when_all(my_sleep("d"), my_sleep_v("e"), my_sleep("f"));
103+
//def.1 is std::ignore
104+
std::cout << "when all:" << std::get<0>(def) << "," << std::get<2>(def) << std::endl << std::endl;
105105

106106
std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") };
107107
auto vals = co_await when_all(std::begin(v), std::end(v));
@@ -115,7 +115,7 @@ void test_when_all()
115115

116116
void resumable_main_when_all()
117117
{
118-
#if _HAS_CXX17
118+
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY
119119
srand((uint32_t)time(nullptr));
120120

121121
test_when_any();

vs_proj/librf.vcxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
<ClCompile>
105105
<WarningLevel>Level3</WarningLevel>
106106
<Optimization>Disabled</Optimization>
107-
<PreprocessorDefinitions>_DEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_DEBUG_COUNTER=0;RESUMEF_ENABLE_MULT_SCHEDULER=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
107+
<PreprocessorDefinitions>_DEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_DEBUG_COUNTER=0;RESUMEF_ENABLE_MULT_SCHEDULER=1;RESUMEF_USE_BOOST_ANY=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
108108
<SDLCheck>true</SDLCheck>
109109
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
110110
<AdditionalOptions>/await</AdditionalOptions>

0 commit comments

Comments
 (0)