Better test::enable_yield_to

This commit is contained in:
Vinnie Falco
2017-05-24 19:42:24 -07:00
parent aca14f6b2b
commit f62ac819f5
6 changed files with 57 additions and 46 deletions

View File

@@ -2,6 +2,7 @@ Version 45
* Workaround for boost::asio::basic_streambuf type check
* Fix message doc image
* Better test::enable_yield_to
--------------------------------------------------------------------------------

View File

@@ -10,7 +10,6 @@
#include <beast/core/async_result.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/buffer_prefix.hpp>
#include <beast/core/error.hpp>
#include <beast/websocket/teardown.hpp>
#include <boost/asio/buffer.hpp>
@@ -68,7 +67,7 @@ public:
error_code& ec)
{
auto const n = boost::asio::buffer_copy(
buffers, buffer_prefix(read_max_, cb_));
buffers, cb_, read_max_);
if(n > 0)
cb_ = cb_ + n;
else

View File

@@ -35,7 +35,7 @@ private:
std::thread thread_;
std::mutex m_;
std::condition_variable cv_;
bool running_ = false;
std::size_t running_ = 0;
public:
/// The type of yield context passed to functions.
@@ -65,61 +65,65 @@ public:
return ios_;
}
/** Run a function in a coroutine.
/** Run one or more functions, each in a coroutine.
This call will block until the coroutine terminates.
Function will be called with this signature:
This call will block until all coroutines terminate.
Each functions should have this signature:
@code
void f(args..., yield_context);
void f(yield_context);
@endcode
@param f The Callable object to invoke.
@param args Optional arguments forwarded to the callable object.
@param fn... One or more functions to invoke.
*/
#if BEAST_DOXYGEN
template<class F, class... Args>
template<class... FN>
void
yield_to(F&& f, Args&&... args);
yield_to(FN&&... fn)
#else
template<class F>
template<class F0, class... FN>
void
yield_to(F&& f);
template<class Function, class Arg, class... Args>
void
yield_to(Function&& f, Arg&& arg, Args&&... args)
{
yield_to(std::bind(f,
std::forward<Arg>(arg),
std::forward<Args>(args)...,
std::placeholders::_1));
}
yield_to(F0&& f0, FN&&... fn);
#endif
private:
void
spawn()
{
}
template<class F0, class... FN>
void
spawn(F0&& f, FN&&... fn);
};
template<class Function>
template<class F0, class... FN>
void
enable_yield_to::yield_to(Function&& f)
enable_yield_to::
yield_to(F0&& f0, FN&&... fn)
{
running_ = 1 + sizeof...(FN);
spawn(f0, fn...);
std::unique_lock<std::mutex> lock{m_};
cv_.wait(lock, [&]{ return running_ == 0; });
}
template<class F0, class... FN>
inline
void
enable_yield_to::
spawn(F0&& f, FN&&... fn)
{
{
std::lock_guard<std::mutex> lock(m_);
running_ = true;
}
boost::asio::spawn(ios_,
[&](boost::asio::yield_context do_yield)
[&](yield_context yield)
{
f(do_yield);
std::lock_guard<std::mutex> lock(m_);
running_ = false;
f(yield);
std::lock_guard<std::mutex> lock{m_};
if(--running_ == 0)
cv_.notify_all();
}
, boost::coroutines::attributes(2 * 1024 * 1024));
std::unique_lock<std::mutex> lock(m_);
cv_.wait(lock, [&]{ return ! running_; });
spawn(fn...);
}
} // test

View File

@@ -132,7 +132,8 @@ public:
{
testSpecialMembers();
yield_to(&self::testRead, this);
yield_to([&](yield_context yield){
testRead(yield);});
}
};

View File

@@ -319,9 +319,12 @@ public:
{
testThrow();
yield_to(&read_test::testFailures, this);
yield_to(&read_test::testRead, this);
yield_to(&read_test::testEof, this);
yield_to([&](yield_context yield){
testFailures(yield); });
yield_to([&](yield_context yield){
testRead(yield); });
yield_to([&](yield_context yield){
testEof(yield); });
testIoService();
}

View File

@@ -666,9 +666,12 @@ public:
void run() override
{
yield_to(&write_test::testAsyncWriteHeaders, this);
yield_to(&write_test::testAsyncWrite, this);
yield_to(&write_test::testFailures, this);
yield_to([&](yield_context yield){
testAsyncWriteHeaders(yield); });
yield_to([&](yield_context yield){
testAsyncWrite(yield); });
yield_to([&](yield_context yield){
testFailures(yield); });
testOutput();
test_std_ostream();
testOstream();