How to compose asynchronous operations? - c++

I'm looking for a way to compose asynchronous operations. The ultimate goal is to execute an asynchronous operation, and either have it run to completion, or return after a user-defined timeout.
For exemplary purposes, assume that I'm looking for a way to combine the following coroutines1:
IAsyncOperation<IBuffer> read(IBuffer buffer, uint32_t count)
{
auto&& result{ co_await socket_.InputStream().ReadAsync(buffer, count, InputStreamOptions::None) };
co_return result;
}
with socket_ being a StreamSocket instance.
And the timeout coroutine:
IAsyncAction timeout()
{
co_await 5s;
}
I'm looking for a way to combine these coroutines in a way, that returns as soon as possible, either once the data has been read, or the timeout has expired.
These are the options I have evaluated so far:
C++20 coroutines: As far as I understand P1056R0, there is currently no library or language feature "to enable creation and composition of coroutines".
Windows Runtime supplied asynchronous task types, ultimately derived from IAsyncInfo: Again, I didn't find any facilities that would allow me to combine the tasks the way I need.
Concurrency Runtime: This looks promising, particularly the when_any function template looks to be exactly what I need.
From that it looks like I need to go with the Concurrency Runtime. However, I'm having a hard time bringing all the pieces together. I'm particularly confused about how to handle exceptions, and whether cancellation of the respective other concurrent task is required.
The question is two-fold:
Is the Concurrency Runtime the only option (UWP application)?
What would an implementation look like?
1 The methods are internal to the application. It is not required to have them return Windows Runtime compatible types.

I think the easiest would be to use the concurrency library. You need to modify your timeout to return the same type as the first method, even if it returns null.
(I realize this is only a partial answer...)
My C++ sucks, but I think this is close...
array<task<IBuffer>, 2> tasks =
{
concurrency::create_task([]{return read(buffer, count).get();}),
concurrency::create_task([]{return modifiedTimeout.get();})
};
concurrency::when_any(begin(tasks), end(tasks)).then([](IBuffer buffer)
{
//do something
});

As suggested by Lee McPherson in another answer, the Concurrency Runtime looks like a viable option. It provides tasks, that can be combined with others, chained up using continuations, as well as seamlessly integrate with the Windows Runtime asynchronous model (see Creating Asynchronous Operations in C++ for UWP Apps). As a bonus, including the <pplawait.h> header provides adapters for concurrency::task class template instantiations to be used as C++20 coroutine awaitables.
I wasn't able to answer all of the questions, but this is what I eventually came up with. For simplicity (and ease of verification) I'm using Sleep in place of the actual read operation, and return an int instead of an IBuffer.
Composition of tasks
The ConcRT provides several ways to combine tasks. Given the requirements concurrency::when_any can be used to create a task that returns, when any of the supplied tasks completes. When only 2 tasks are supplied as input, there's also a convenience operator (operator||) available.
Exception propagation
Exceptions raised from either of the input tasks do not count as a successful completion. When used with the when_any task, throwing an exception will not suffice the wait condition. As a consequence, exceptions cannot be used to break out of combined tasks. To deal with this I opted to return a std::optional, and raise appropriate exceptions in a then continuation.
Task cancellation
This is still a mystery to me. It appears that once a task satisfies the wait condition of the when_any task, there is no requirement to cancel the respective other outstanding tasks. Once those complete (successfully or otherwise), they are silently dealt with.
Following is the code, using the simplifications mentioned earlier. It creates a task consisting of the actual workload and a timeout task, both returning a std::optional. The then continuation examines the return value, and throws an exception in case there isn't one (i.e. the timeout_task finished first).
#include <Windows.h>
#include <cstdint>
#include <iostream>
#include <optional>
#include <ppltasks.h>
#include <stdexcept>
using namespace concurrency;
task<int> read_with_timeout(uint32_t read_duration, uint32_t timeout)
{
auto&& read_task
{
create_task([read_duration]
{
::Sleep(read_duration);
return std::optional<int>{42};
})
};
auto&& timeout_task
{
create_task([timeout]
{
::Sleep(timeout);
return std::optional<int>{};
})
};
auto&& task
{
(read_task || timeout_task)
.then([](std::optional<int> result)
{
if (!result.has_value())
{
throw std::runtime_error("timeout");
}
return result.value();
})
};
return task;
}
The following test code
int main()
{
try
{
auto res1{ read_with_timeout(3000, 5000).get() };
std::cout << "Succeeded. Result = " << res1 << std::endl;
auto res2{ read_with_timeout(5000, 3000).get() };
std::cout << "Succeeded. Result = " << res2 << std::endl;
}
catch( std::runtime_error const& e )
{
std::cout << "Failed. Exception = " << e.what() << std::endl;
}
}
produces this output:
Succeeded. Result = 42
Failed. Exception = timeout

Related

C++ Coroutine - When, How to use? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 12 months ago.
This post was edited and submitted for review 12 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
As a novice C++ programmer who is very new to the concept of coroutines, I am trying to study and utilize the feature. Although there is explanation of coroutine here: What is a coroutine?
I am not yet sure when and how to use the coroutine. There was several example use cases provided, but those use cases had alternative solutions which could be implemented by pre- C++20 features: (ex:lazy computation of infinite sequence can be done by a class with private internal state variable).
Therefore I am seeking for any usecases that coroutines are particularly useful.
(From the image posted by Izana)
The word "coroutine" in this context is somewhat overloaded.
The general programming concept called a "coroutine" is what is described in the question you're referring to. C++20 added a language feature called "coroutines". While C++20's coroutines are somewhat similar to the programming concept, they're not all that similar.
At the ground level, both concepts are built on the ability of a function (or call stack of functions) to halt its execution and transfer control of execution to someone else. This is done with the expectation that control will eventually be given back to the function which has surrendered execution for the time being.
Where C++ coroutines diverge from the general concept is in their limitations and designed application.
co_await <expr> as a language construct does the following (in very broad strokes). It asks the expression <expr> if it has a result value to provide at the present time. If it does have a result, then the expression extracts the value and execution in the current function continues as normal.
If the expression cannot be resolved at the present time (perhaps because <expr> is waiting on an external resource or asynchronous process or something), then the current function suspends its execution and returns control to the function that called it. The coroutine also attaches itself to the <expr> object such that, once <expr> has the value, it should resume the coroutine's execution with said value. This resumption may or may not happen on the current thread.
So we see the pattern of C++20 coroutines. Control on the current thread returns to the caller, but resumption of the coroutine is determined by the nature of the value being co_awaited on. The caller gets an object that represents the future value the coroutine will produce but has not yet. The caller can wait on it to be ready or go do something else. It may also be able to itself co_await on the future value, creating a chain of coroutines to be resumed once a value is computed.
We also see the primary limitation: suspension applies only to the immediate function. You cannot suspend an entire stack of function calls unless each one of them individually does their own co_awaits.
C++ coroutines are a complex dance between 3 parties: the expression being awaited on, the code doing the awaiting, and the caller of the coroutine. Using co_yield essentially removes one of these three parties. Namely, the yielded expression is not expected to be involved. It's just a value which is going to be dumped to the caller. So yielding coroutines only involve the coroutine function and the caller. Yielding C++ coroutines are a bit closer to the conceptual idea of "coroutines".
Using a yielding coroutine to serve a number of values to the caller is generally called a "generator". How "simple" this makes your code depends on your generator framework (ie: the coroutine return type and its associated coroutine machinery). But good generator frameworks can expose range interfaces to the generation, allowing you to apply C++20 ranges to them and do all sorts of interesting compositions.
coroutine makes asynchronous programing more readable.
if there is no coroutine, we will use callback in asynchronous programing.
void callback(int data1, int data2)
{
// do something with data1, data2 after async op
// ...
}
void async_op(std::function<void()> callback)
{
// do some async operation
}
int main()
{
// do something
int data1;
int data2;
async_op(std::bind(callback, data1, data2));
return 0;
}
if there is a lot of callback, the code will very hard to read.
if we use coroutine the code will be
#include <coroutine>
#include <functional>
struct promise;
struct coroutine : std::coroutine_handle<promise>
{
using promise_type = struct promise;
};
struct promise
{
coroutine get_return_object() { return {coroutine::from_promise(*this)}; }
std::suspend_always initial_suspend() noexcept { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
struct awaitable
{
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<promise> h)
{
func();
}
void await_resume() { }
std::function<void()> func;
};
void async_op()
{
// do some async operation
}
coroutine callasync()
{
// do somethine
int data1;
int data2;
co_await awaitable(async_op);
// do something with data1, data2 after async op
// ...
}
int main()
{
callasync();
return 0;
}
it seems to me that those cases can be achieved by more simpler way: (ex:lazy computation of infinite sequence can be done by a class with private internal state variable).
Say you're writing a function that should interact with a remote server, creating a TCP connection, logging in with some multi-stage challenge/response protocol, making queries and getting replies (often in dribs and drabs over TCP), eventually disconnecting.... If you were writing a dedicated function to synchronously do that - as you might if you had a dedicated thread for this - then your code could very naturally reflect the stages of connection, request and response processing and disconnecting, just by the order of statements in your function and the use of flow control (for, while, switch, if). The data needed at various points would be localised in a scope reflecting its use, so it's easier for the programmer to know what's relevant at each point. This is easy to write, maintain and understand.
If, however, you wanted the interactions with the remote host to be non-blocking and to do other work in the thread while they were happening, you could make it event driven, using a class with private internal state variable[s] to track the state of your connection, as you suggest. But, your class would need not only the same variables the synchronous-function version would need (e.g. a buffer for assembling incoming messages), but also variables to track where in the overall connection/processing steps you left off (e.g. enum state { tcp_connection_pending, awaiting_challenge, awaiting_login_confirmation, awaiting_reply_to_message_x, awaiting_reply_to_message_y }, counters, an output buffer), and you'd need more complex code to jump back in to the right processing step. You no longer have localisation of data with its use in specific statement blocks - and instead have a flat hodge-podge of class data members and additional mental overhead in understanding which parts of the code care about them, when they're valid or not etc.. It's all spaghetti. (The State/Strategy design pattern can help structure this better, but sometimes with runtime for virtual dispatch, dynamic allocation etc..)
Co-routines provide a best-of-both-worlds solution: you can think of them as providing an additional stack for the call to what looks very much like the concise and easy/fast-to-write/maintain/understand synchronous-processing function initially explained above, but with the ability to suspend and resume instead of blocking, so the same thread can progress the connection handling as well as do other work (it could even invoke the coroutine thousands of times to handle thousands of remote connections, switching efficiently between them to keep work happening as network I/O happens).
Harkening back to your "lazy computation of infinite sequence" - in one sense, a coroutine may be overkill for this, as there may not be multiple processing stages/states, or subsets of data members that are relevant therein. There are some benefits to consistency though - if providing e.g. pipelines of coroutines.
Just as lambda in C++ avoid you to define classes and function when you want to capture the context, coroutines also avoid you to define a class and a relatively complex function or set of functions when you want to be able to suspend and resume the execution of a function.
But contrarily to lambda, to use and define coroutines, you need a support library, and C++20 is missing that aspect in the standard library. That has for consequence that most if not all explanations of C++ coroutines target a low level interface and explain as much if not more how to build the support library as how to use it, giving the impression that the usage will be more complex than it is. You get a "how to implement std::vector" kind of description when you want a "how to use std::vector".
To take the example of cppreference.com, coroutines allows you to write
Generator<uint64_t>
fibonacci_sequence(unsigned n)
{
if (n==0)
co_return;
if (n>94)
throw std::runtime_error("Too big Fibonacci sequence. Elements would overflow.");
co_yield 0;
if (n==1)
co_return;
co_yield 1;
if (n==2)
co_return;
uint64_t a=0;
uint64_t b=1;
for (unsigned i = 2; i < n;i++)
{
uint64_t s=a+b;
co_yield s;
a=b;
b=s;
}
}
instead (I didn't pass that to a compiler, there must be errors in it) of
class FibonacciSequence {
public:
FibonacciSequence(unsigned n);
bool done() const;
void next();
uint64_t value() const;
private:
unsigned n;
unsigned state;
unsigned i;
uint64_t mValue;
uint64_t a;
uint64_t b;
uint64_t s;
};
FibonacciSequence::FibonacciSequence(unsigned pN)
: n(pN), state(1)
{}
bool FibonacciSequence::done() const
{
return state == 0;
}
uint64_t FibonacciSequence::value() const
{
return mValue;
}
void FibonacciSequence::next() const
{
for (;;) {
switch (state) {
case 0:
return;
case 1:
if (n==0) {
state = 0;
return;
}
if (n>94)
throw std::runtime_error("Too big Fibonacci sequence. Elements would overflow.");
mValue = 0;
state = 2;
return;
case 2:
if (n==1) {
state = 0;
return;
}
mValue = 1;
state = 3;
return;
case 3:
if (n==2) {
state = 0;
return;
}
a=0;
b=1;
i=2;
state = 4;
break;
case 4:
if (i < n) {
s=a+b;
value = s;
state = 5;
return;
} else {
state = 6;
}
break;
case 5:
a=b;
b=s;
state = 4;
break;
case 6:
state = 0;
return;
}
}
}
FibonacciSequence fibonacci_sequence(unsigned n) {
return FibonacciSequence(n);
}
Obviously something simpler could be used, but I wanted to show how the mapping could be done automatically, without any kind of optimization. And I've side stepped the additional complexity of allocation and deallocation.
That transformation is useful for generators like here. It is more generally useful when you want a kind of collaborative concurrency, with or without parallelism. Sadly, for such things, you need even more library support (including a scheduler to chose the coroutine which will be executed next in a given context) and I've not see relatively simple examples of that showing the underlying concepts while avoiding to be drown in implementation details.

Any case of std::promise that can't be replaced by a single thread running sequential produce-then-consume?

Update 9th June 2020:
Consolidating all the comments and answers here, and putting some more thought to this, I have created a flowchart below (click to zoom) to help decide when to use std::promise/future, and what are the trade-offs.
Original post is as follows:
I have been thinking about the real benefit of the std::promise/future mechanism. Examples almost everywhere tout this pattern - a single producer, single producer scenario where the producer notifies the consumer one-time that the resource in question is ready for consumption:
#include <iostream>
#include <future>
#include <thread>
using namespace std::chrono_literals;
struct StewableFood {
int tenderness;
};
void slow_cook_for_12_hours(std::promise<StewableFood>& promise_of_stew) {
std::cout << "\nChef: Starting to cook ...";
// Cook till 100% tender
StewableFood food{ 0 };
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(10ms);
food.tenderness = (i + 1) * 10;
std::cout << "\nChef: Stewing ... " << food.tenderness << "%";
}
// Notify person waiting on the promise of stew that the promise has been fulfilled.
promise_of_stew.set_value(food);
std::cout << "\nChef: Stew is ready!";
}
void wait_to_eat_stew(std::future<StewableFood>& potenial_fulfilment_of_stew) {
std::cout << "\nJoe: Waiting for stew ...";
auto food = potenial_fulfilment_of_stew.get();
std::cout << "\nJoe: I have been notified that stew is ready. Tenderness " << food.tenderness << "%! Eat!";
}
int main()
{
std::promise<StewableFood> promise_of_stew;
auto potenial_fulfilment_of_stew = promise_of_stew.get_future();
std::thread async_cook(slow_cook_for_12_hours, std::ref(promise_of_stew));
std::thread async_eat(wait_to_eat_stew, std::ref(potenial_fulfilment_of_stew));
async_cook.join();
async_eat.join();
return 0;
}
To me, all this asynchronicity serves no purpose, because ultimately, the consumer's blocking wait on future::get makes this kind of usage equivalent to a single-threaded one with sequential produce-then-consume. I initially thought my example above is contrived. But if we look at the one-time use only constraint of a std::promise/future pair (i.e. you cannot re-write to the original promise nor re-read from the original future), it then follows that the above example becomes the only viable use case, since:
The set-once constraint means there can be only one producer, and
The get-once constraint means there can be only one consumer, and
Inferred from the above 2 set/get-once constraints, there shall be no looping that causes re-use on the same promise/future.
If the usage pattern in the above example is indeed the only viable use case, it then follows that there is no advantage in using std::promise, compared to doing just:
void cook_stew_then_eat() {
auto stew = slow_cook_for_12_hours();
// wait 12 hours
eat_stew(stew);
}
int main() {
std::thread t(cook_stew_then_eat);
t.join();
return 0;
}
Now, this conclusion seems suspicious. I am quite sure there is a good use case for std::promise which cannot be replaced by a single threaded sequential-produce-then-consume version which doesn't involve std::promise.
Question: What is that use case(s)?
Note: It is tempting to speculate that perhaps std::promise/future somehow allows us to asynchronously do something else without waiting on the fulfilment - might that be the advantage? Definitely not, because we can achieve the identical effect by putting that "something else" (e.g. some important work) in another thread. To illustrate:
// cook and eat threads use std::promise/future
std::thread cook(...);
std::thread eat(...);
// Let's do important work on another thread
std::thread important_work(...);
cook.join();
eat.join();
important_work.join();
is identical to this solution that doesn't use std::promise/future:
// sequentially cook then eat, NO NEED to use std::promise/future
std::thread cook_then_eat(...);
// Let's do important work on another thread
std::thread important_work(...);
cook_then_eat.join();
important_work.join();
No, you are actually correct, future/promise pattern can always be replaced with manual thread management (via thread joins, condition variables and mutexes) if you are careful about synchronization and object lifetimes.
The primary benefit of future/promise pattern is abstraction. It hides lifetime management and synchronization of the shared state from you, freeing you from the burden of doing it yourself.
Once the producer has a promise it doesn't need to know anything else about the consuming side, and likewise for the consumer and future. This makes it possible to write more concise, less error prone, and less coupled code.
Also keep in mind that as of C++20 std::future still lacks continuations, which makes it a lot less powerful than it could be.
What is that use case(s)?
Any work that doesn't depend on the result of the promise can be done on other threads before waiting on the promise.
Let's extend your example to a stew competition
extern void slow_cook_for_12_hours(std::promise<StewableFood>& promise_of_stew);
extern Grade rate_stew(const StewableFood &);
std::map<Chef, Grade> judge_stew_competition(std::map<Chef, std::future<StewableFood>>& entries)
{
std::map<Chef, Grade> results;
for (auto & [chef, fut] : entries) { results[chef] = rate_stew(fut.get()); }
return results;
}
int main()
{
std::map<Chef, std::promise<StewableFood>> promises_of_stew = { ... };
std::map<Chef, std::future<StewableFood>> fulfilment_of_stews;
std::vector<std::thread> async_cook;
for (auto & [chef, promise] : promises_of_stew)
{
fulfilment_of_stews[chef] = promise.get_future();
async_cook.emplace(slow_cook_for_12_hours, std::ref(promise));
}
std::thread async_judge(judge_stew_competition, std::ref(fulfilment_of_stews));
for (auto & thread : async_cook) { thread.join(); }
async_judge.join();
return 0;
}
Examples almost everywhere tout this pattern - a single producer, single producer scenario where the producer notifies the consumer one-time that the resource in question is ready for consumption.
May be that is not a good example.
Another example is a task that requires resources/datasets from different providers and there are only blocking calls available to fetch resources (or non-blocking calls cannot easily be integrated into one event loop in your application). In this case your consumer thread launches all resources requests as std::async and waits till they all complete in parallel, rather than sequentially. In this case it takes max(times) rather than sum(times) to fetch all the datasets, where times is an array of each provider response time.

future composability, and boost::wait_for_all

I just read the article 'Futures Done Right', and the main thing that c++11 promises are lacking seems to be that creating composite futures from existing ones
I'm looking right now at the documentation of boost::wait_for_any
but consider the following example:
int calculate_the_answer_to_life_the_universe_and_everything()
{
return 42;
}
int calculate_the_answer_to_death_and_anything_in_between()
{
return 121;
}
boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
boost:: future<int> fi=pt.get_future();
boost::packaged_task<int> pt2(calculate_the_answer_to_death_and_anything_in_between);
boost:: future<int> fi2=pt2.get_future();
....
int calculate_the_oscillation_of_barzoom(boost::future<int>& a, boost::future<int>& b)
{
boost::wait_for_all(a,b);
return a.get() + b.get();
}
boost::packaged_task<int> pt_composite(boost::bind(calculate_the_oscillation_of_barzoom, fi , fi2));
boost:: future<int> fi_composite=pt_composite.get_future();
What is wrong with this approach to composability? is this a valid way to achieve composability? do we need some elegant syntactic edulcorant over this pattern?
when_any and when_all are perfectly valid ways to compose futures. They both correspond to parallel composition, where the composite operation waits for either one or all the composed operations.
We also need sequential composition (which is not in Boost.Thread). This could be, for example, a future<T>::then function that allows you to queue up an operation that uses the future's value and runs when the future is ready. It is possible to implement this yourself, but with an efficiency tradeoff. Herb Sutter talks about this in his recent Channel9 video.
N3428 is a draft proposal for adding these features (and more) to the C++ standard library. They are all library features and don't add any new syntax to the language. Additionally, N3328 is a proposal to add syntax for resumable functions (like using async/await in C#) which will use future<T>::then internally.
Points for the use of the word edulcorant. :)
The problem with your sample code is that you package everything up into tasks, but you never schedule those tasks for execution!
int calculate_the_answer_to_life() { ... }
int calculate_the_answer_to_death() { ... }
std::packaged_task<int()> pt(calculate_the_answer_to_life);
std::future<int> fi = pt.get_future();
std::packaged_task<int()> pt2(calculate_the_answer_to_death);
std::future<int> fi2 = pt2.get_future();
int calculate_barzoom(std::future<int>& a, std::future<int>& b)
{
boost::wait_for_all(a, b);
return a.get() + b.get();
}
std::packaged_task<int()> pt_composite([]{ return calculate_barzoom(fi, fi2); });
std::future<int> fi_composite = pt_composite.get_future();
If at this point I write
pt_composite();
int result = fi_composite.get();
my program will block forever. It will never complete, because pt_composite is blocked on calculate_barzoom, which is blocked on wait_for_all, which is blocked on both fi and fi2, neither of which will ever complete until somebody executes pt or pt2 respectively. And nobody will ever execute them, because my program is blocked!
You probably meant me to write something like this:
std::async(pt);
std::async(pt2);
std::async(pt_composite);
int result = fi_composite.get();
This will work. But it's extremely inefficient — we spawn three worker threads (via three calls to async), in order to perform two threads' worth of work. That third thread — the one running pt_composite — will be spawned immediately, and then just sit there asleep until pt and pt2 have finished running. That's better than spinning, but it's significantly worse than not existing: it means that our thread pool has one fewer worker than it ought to have. In a plausible thread-pool implementation with only one thread per CPU core, and a lot of tasks coming in all the time, that means that we've got one CPU core just sitting idle, because the worker thread who was meant to be running on that core is currently blocked inside wait_for_all.
What we want to do is declare our intentions declaratively:
int calculate_the_answer_to_life() { ... }
int calculate_the_answer_to_death() { ... }
std::future<int> fi = std::async(calculate_the_answer_to_life);
std::future<int> fi2 = std::async(calculate_the_answer_to_death);
std::future<int> fi_composite = std::when_all(fi, fi2).then([](auto a, auto b) {
assert(a.is_ready() && b.is_ready());
return a.get() + b.get();
});
int result = fi_composite.get();
and then have the library and the scheduler work together to Do The Right Thing: don't spawn any worker thread that can't immediately proceed with its task. If the end-user has to write even a single line of code that explicitly sleeps, waits, or blocks, some performance is definitely being lost.
In other words: Spawn no worker thread before its time.
Obviously it's possible to do all this in standard C++, without library support; that's how the library itself is implemented! But it's a huge pain to implement from scratch, with many subtle pitfalls; so that's why it's a good thing that library support seems to be coming soon.
The ISO proposal N3428 mentioned in Roshan Shariff's answer has been updated as N3857, and N3865 provides even more convenience functions.

Are futures a safe way to check for individual thread completion?

I've been toying around with Boost's futures and was wondering if they were an acceptable and safe way to check if an individual thread has completed.
I had never used them before so most of the code I wrote was based off of Boost's Synchronization documentation.
#include <iostream>
#include <boost/thread.hpp>
#include <boost/thread/future.hpp>
int calculate_the_answer_to_life_the_universe_and_everything()
{
boost::this_thread::sleep(boost::posix_time::seconds(10));
return 42;
}
int main()
{
boost::packaged_task<int> task(calculate_the_answer_to_life_the_universe_and_everything);
boost::unique_future<int> f(task.get_future());
boost::thread th(boost::move(task));
while(!f.is_ready())
{
std::cout << "waiting!" << std::endl;
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
std::cout << f.get() << std::endl;
th.join();
}
This appears to wait for the calculate_the_answer_to_life_the_universe_and_everything() thread to return 42. Could something possibly go wrong with this?
Thanks!
Yes, futures are safe to use in that way, and the code is (at a quick glance) safe and correct.
There are other ways to do the same thing (e.g. using an atomic_flag, or mutex-protected data, or many others) but your code is a valid way to do it.
N.B. instead of f.is_ready() and this_thread::sleep(seconds(1)) you could use f.wait_for(seconds(1)), which would wake as soon as the result is made ready. That waits directly on the future, instead of checking the future, then waiting using a separate mechanism, then checking, then waiting with a separate mechanism etc.
And instead of packaged_task and thread you could use async.
Using C++11 names instead of boost ...
int main()
{
auto f = std::async(std::launch::async, calculate_the_answer_to_life_the_universe_and_everything);
while(f.wait_for(std::chrono::seconds(1)) == std::future_status::timeout)
std::cout << "waiting!" << std::endl;
std::cout << f.get() << std::endl;
}
I've been toying around with Boost's futures and was wondering if they were an acceptable and safe way to check if an individual thread has completed.
Futures are a mechanism for asynchronous evaluation, not a synchronization mechanism. Although some of the primitives do have synchronization properties (future<>::get), the library is not designed to synchronize, but rather to fire a task and ignore it until the result is needed.

How do I make a function asynchronous in C++?

I want to call a function which will be asynchronous (I will give a callback when this task is done).
I want to do this in single thread.
This can be done portably with modern C++ or even with old C++ and some boost. Both boost and C++11 include sophisticated facilities to obtain asynchronous values from threads, but if all you want is a callback, just launch a thread and call it.
1998 C++/boost approach:
#include <iostream>
#include <string>
#include <boost/thread.hpp>
void callback(const std::string& data)
{
std::cout << "Callback called because: " << data << '\n';
}
void task(int time)
{
boost::this_thread::sleep(boost::posix_time::seconds(time));
callback("async task done");
}
int main()
{
boost::thread bt(task, 1);
std::cout << "async task launched\n";
boost::this_thread::sleep(boost::posix_time::seconds(5));
std::cout << "main done\n";
bt.join();
}
2011 C++ approach (using gcc 4.5.2, which needs this #define)
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream>
#include <string>
#include <thread>
void callback(const std::string& data)
{
std::cout << "Callback called because: " << data << '\n';
}
void task(int time)
{
std::this_thread::sleep_for(std::chrono::seconds(time));
callback("async task done");
}
int main()
{
std::thread bt(task, 1);
std::cout << "async task launched\n";
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "main done\n";
bt.join();
}
As of C++11, plain c++ does have a concept of threads, but the most concise way to call a function asynchronously is to use the C++11 async command along with futures. This ends up looking a lot like the way you'd do the same thing in pthreads, but it's 100% portable to all OSes and platforms:
Say your function has a return value... int = MyFunc(int x, int y)
#include <future>
Just do:
// This function is called asynchronously
std::future<int> EventualValue = std::async(std::launch::async, MyFunc, x, y);
Catch? How do you know when it's done? (The barrier.)
Eventually, do:
int MyReturnValue = EventualValue.get(); // block until MyFunc is done
Note it's easy to do a parallel for loop this way - just create an array of futures.
You can't in plain C++. You'll need to use an OS-specific mechanism, and you need a point where execution is suspended in a way that allows the OS to execute the callback. E.g. for Windows, QueueUserAPC - the callback will be executed when you e.g. SleepEx or WaitForSingleObjectEx
The long answer involves implementing your own task scheduler and wrapping your "function" up into one or more tasks. I'm not sure you want the long answer. It certainly doesn't allow you to call something, completely forget about it, and then be notified when that thing is done; however if you are feeling ambitious, it will allow you to simulate coroutines on some level without reaching outside of standard C++.
The short answer is that this isn't possible. Use multiple threads or multiple processes. I can give you more specific information if you divulge what OS/platform you're developing for.
There are two bits to doing this.
Firstly, packing up the function call so that it can be executed later.
Secondly, scheduling it.
It is the scheduling which depends on other aspects of the implementation. If you know "when this task is done", then that's all you need - to go back and retrieve the "function call" and call it. So I am not sure this is necessarily a big problem.
The first part is then really about function objects, or even function pointers. The latter are the traditional callback mechanism from C.
For a FO, you might have:
class Callback
{
public:
virtual void callMe() = 0;
};
You derive from this and implement that as you see fit for your specific problem. The asyncronous event queue is then nothing more than a list<> of callbacks:
std::list<Callback*> asyncQ; // Or shared_ptr or whatever.
I'm not sure I understand what you want, but if it's how to make use of a callback: It works by defining a function pointer, like this (untested):
// Define callback signature.
typedef void (*DoneCallback) (int reason, char *explanation);
// A method that takes a callback as argument.
void doSomeWorkWithCallback(DoneCallback done)
{
...
if (done) {
done(1, "Finished");
}
}
//////
// A callback
void myCallback(int reason, char *explanation)
{
printf("Callback called with reason %d: %s", reason, explanation);
}
/////
// Put them together
doSomeWortkWithCallback(myCallback);
As others have said, you technically can't in plain C++.
However, you can create a manager that takes your task and does time-slicing or time scheduling; with each function call, the manager uses a timer to measure the amount of time the process took; if the process took less time than scheduled, and it thinks it can finish another call and use up the remaining time without going over, it can call it again; if the function does go over the alloted time, it means the function has less time next update to run. So, this will involve creating a somewhat complex system to handle it for you.
Or, if you have a specific platform in mind, you could use threading, or create another process to handle the work.