Well, Boost.Thread has the future / promise mechanism, that's where it was taken from. What std::async accomplished under-the-hood to run a thread with the given callable and attaches a future to it is quite simple, at least for the non-deferred launch version. The deferred version is also quite simple to implement in boost.
If you look at the two examples of using a packaged_task / future from the Boost.Thread documentation page, you will find exactly two examples: one async and one deferred (or lazy-future). If you need to give parameters to the function, just use boost::bind . You could even wrap all this in a async() function template that exactly replicates the standard one, it's easy.