| Home | Libraries | People | FAQ | More

### Success/Error Virtual Methods

One classic approach to completion notification is to define an abstract base class with `success()` and `error()` methods. Code wishing to perform async I/O must derive a subclass, override each of these methods and pass the async operation a pointer to a subclass instance. The abstract base class might look like this:

    // every async operation receives a subclass instance of this abstract base
    // class through which to communicate its result
    struct Response {
        typedef std::shared_ptr< Response > ptr;

        // called if the operation succeeds
        virtual void success( std::string const& data) = 0;

        // called if the operation fails
        virtual void error( AsyncAPIBase::errorcode ec) = 0;
    };

Now the `AsyncAPI` operation might look more like this:

    // derive Response subclass, instantiate, pass Response::ptr
    void init_read( Response::ptr);

We can address this by writing a one-size-fits-all `PromiseResponse`:

    class PromiseResponse: public Response {
    public:
        // called if the operation succeeds
        virtual void success( std::string const& data) {
            promise_.set_value( data);
        }

        // called if the operation fails
        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_;
    };

Now we can simply obtain the `future<>` from that `PromiseResponse` and wait on its `get()`:

    std::string read( AsyncAPI & api) {
        // Because init_read() requires a shared_ptr, we must allocate our
        // ResponsePromise on the heap, even though we know its lifespan.
        auto promisep( std::make_shared< PromiseResponse >() );
        boost::fibers::future< std::string > future( promisep->get_future() );
        // Both 'promisep' and 'future' will survive until our lambda has been
        // called.
        api.init_read( promisep);
        return future.get();
    }

The source code above is found in adapt_callbacks.cpp and adapt_method_calls.cpp.