class LongRequestHandler
{
public :
void Handle()
{
// read client request parameters
// mysql request 1
// mysql request 2
HttpRequestExecutor::GetInstance()->Execute(
"example.com?x=1" ,
boost::bind( this , &LongRequestHandler::HandleStage2)
);
}
void HandleStage2( const std:: string & http_request_result)
{
// mysql request 3
// write response to client
}
};
* This source code was highlighted with Source Code Highlighter .
template <typename Handler> void async_echo(
tcp::socket& socket,
mutable_buffer working_buffer,
Handler handler,
// coroutine state:
coroutine coro = coroutine(),
error_code ec = error_code(),
size_t length = 0)
{
reenter (coro)
{
entry:
while (!ec)
{
yield socket.async_read_some(
buffer(working_buffer),
bind(&async_echo<handler>,
ref (socket), working_buffer,
box(handler), coro, _1, _2));
if (ec) break ;
yield async_write(socket,
buffer(working_buffer, length),
bind(&async_echo<handler>,
ref (socket), working_buffer,
box(handler), coro, _1, _2));
}
handler(ec);
}
}
* This source code was highlighted with Source Code Highlighter .
Coroutine and yield in C ++ look unusually;) This is implemented on the define , you can read the blog how the author did it.
mysql request 1 mysql request 2 http request 1 mysql request 3 http request 2 mysql request 4 mysql request 5
mysql request 2 http request 1
mysql request 3 http request 2 mysql request 4
mysql request 1 x = run (func1) y = run (func2) wait (x, y) mysql request 5 func1: mysql request 2 http request 1 func2: mysql request 3 http request 2 mysql request 4
mysql request 1 mysql request 2 http request 1 mysql request 3 http request 2 mysql request 4 mysql request 5
boost::this_thread::sleep(boost::posix_time::milliseconds(rand()%100 + 10));
boost::this_thread::sleep(boost::posix_time::milliseconds(rand()%100 + 10));
class Request
{
public :
Request( const std:: string & data);
const std:: string & Read() const ;
void Write( const std:: string & answer);
};
* This source code was highlighted with Source Code Highlighter .
class RequestHandler
{
public :
RequestHandler(boost::asio::io_service & io_service, const RequestPtr & request);
void Process() const ;
};
* This source code was highlighted with Source Code Highlighter .
boost::tasks::static_pool< boost::tasks::unbounded_fifo > pool( boost::tasks::poolsize( 5) );
* This source code was highlighted with Source Code Highlighter .
boost::asio::io_service io_service;
* This source code was highlighted with Source Code Highlighter .
boost::asio::deadline_timer dummy_timer(io_service);
dummy_timer.expires_from_now(boost::posix_time::seconds(10));
// void dummy_handler(const boost::system::error_code&) {}
dummy_timer.async_wait(&dummy_handler);
* This source code was highlighted with Source Code Highlighter .
boost::thread_group io_service_thread_pool;
for ( int i = 0; i < 3; ++i)
io_service_thread_pool.create_thread(
boost::bind(&boost::asio::io_service::run, &io_service)
);
* This source code was highlighted with Source Code Highlighter .
Next, create a query:
RequestPtr request( new Request( "some data" ));
RequestHandlerPtr handler( new RequestHandler(io_service, request));
* This source code was highlighted with Source Code Highlighter .
boost::tasks::handle< void > request_processing(
boost::tasks::async(
boost::tasks::make_task( &RequestHandler::Process, handler ),
pool));
* This source code was highlighted with Source Code Highlighter .
boost :: tasks :: make_task (& RequestHandler :: Process, handler) - creates a task to invoke a Process on the handler object that can be executed. boost :: tasks :: async initiates an asynchronous execution of the task. boost :: tasks :: handle an object by which you can track the status of the completion of the task, get the result if it is.
request_processing.wait();
* This source code was highlighted with Source Code Highlighter .
io_service.stop();
io_service_thread_pool.join_all();
* This source code was highlighted with Source Code Highlighter .
void Subtask1() const
{
Request( "query2" );
ExternalRequest( "extquery1" );
}
void Subtask2() const
{
Request( "query3" );
ExternalRequest( "extquery2" );
Request( "query4" );
}
void Process() const
{
std:: string data = request_->Read();
Request( "query1" );
boost::tasks::handle< void > subtask1(
boost::tasks::async(
boost::tasks::make_task( &RequestHandler::Subtask1, this )));
boost::tasks::handle< void > subtask2(
boost::tasks::async(
boost::tasks::make_task( &RequestHandler::Subtask2, this )));
boost::tasks::waitfor_all( subtask1, subtask2);
Request( "query5" );
request_->Write( "some answer" );
}
* This source code was highlighted with Source Code Highlighter .
void ExternalRequest( const std:: string & what) const
{
ExternalRequestHandler external_handler(io_service_);
boost::tasks::spin::auto_reset_event ev;
external_handler.PerformExternalReqeust(what, &ev);
ev.wait();
}
* This source code was highlighted with Source Code Highlighter .
A handler is created, as well as an event with automatic reset - boost :: tasks :: spin :: auto_reset_event. This event is passed to the external request handler and upon its completion ev.set () will be called, and until then ev.wait () blocks the task.
Source: https://habr.com/ru/post/88288/