stasher::process_request() template function

The example in previous chapter, updatethread.C uses similar code in two cases of setting up a destructor callback for an asynchronous request's mcguffin. Each case, a separate destructor callback class gets defined, instantiated, and attached as a destructor callback for an asynchronous request's mcguffin.

updatethread2.C is a modified version of updatethread.C. It does the same thing, but uses stasher::process_request():

stasher::process_request(client->get_request(req),
                         []
                         (const stasher::getresults &res)
                         {
                            // functor
                         });

The stasher::process_request() template function takes two parameters. The first parameter is a return value from an asynchronous request such as stasher::get_request() or stasher::put_request(). The second parameter is a functor with a single parameter that's consistent with the final result of the request. For stasher::get_request() it's stasher::getresults, for stasher::put_request() it's stasher::putresults.

stasher::process_request() installs a destructor callback for the request's mcguffin that invokes the functor, with the results of the request. stasher::process_request() uses LIBCXX's x::destroyCallback::create(), which logs any exceptions thrown in the callback.

Quite a bit of code from updatethread.C gets replaced with just a short functor in updatethread2.C. The functor can capture variables, but in most cases they must be captured by value; the functor works the same way that a manually-installed destructor callback does, here; and it usually ends up getting invoked by the client connection thread, so variables need to be captured by value. The limitations of destructor callback described in the section called “What asynchronous C++ API methods can and cannot do” apply here too.