Typically each function would execute async_read or async_write with the next function to be called registered as the callback. They daisy-chain together. In case of errors the error handling callback is used instead. I don't know how well this scales but it's fine for medium sized programs.