Одним из классических подходов к уведомлению о завершении является определение абстрактного базового класса с помощью методов<success()
>и<error()
>. Код, желающий выполнить I/O асинка, должен вывести подкласс, переопределить каждый из этих методов и передать операцию асинка указателем на экземпляр подкласса. Абстрактный базовый класс может выглядеть так:
struct Response {
typedef std::shared_ptr< Response > ptr;
virtual void success( std::string const& data) = 0;
virtual void error( AsyncAPIBase::errorcode ec) = 0;
};
Теперь операция<AsyncAPI
>может выглядеть следующим образом:
void init_read( Response::ptr);
Мы можем решить эту проблему, написав универсальный<PromiseResponse
>:
class PromiseResponse: public Response {
public:
virtual void success( std::string const& data) {
promise_.set_value( data);
}
virtual void error( AsyncAPIBase::errorcode ec) {
promise_.set_exception(
std::make_exception_ptr(
make_exception("read", ec) ) );
}
boost::fibers::future< std::string > get_future() {
return promise_.get_future();
}
private:
boost::fibers::promise< std::string > promise_;
};
Теперь мы можем просто получить<future<>
>от этого<PromiseResponse
>и ждать его.<get()
>:
std::string read( AsyncAPI & api) {
auto promisep( std::make_shared< PromiseResponse >() );
boost::fibers::future< std::string > future( promisep->get_future() );
api.init_read( promisep);
return future.get();
}
Приведенный выше исходный код содержится вadapt_callbacks.cppиadapt_method_calls.cpp..