winrt/c++: await result from dispatched task - c++

I want to dispatch a job to the UI thread, then wait for the result and use it from another thread. Like this, but co_await does not work inside the lambda:
dispatcher.RunAsync(CoreDispatcherPriority::Normal, [&]() {
auto res = co_await mStoreContext.RequestPurchaseAsync(L"");
});
Or even waiting for the whole RunAsync operation, if I could get my result out from it

That's because void can not be used as a return value from a coroutine (I can be if you use my my library).
try returning a std::future<void> instead:
dispatcher.RunAsync(CoreDispatcherPriority::Normal, [&]() -> std::future<void> {
auto res = co_await mStoreContext.RequestPurchaseAsync(L"");
});

Related

Awaiting a predicate with C++20 coroutines

We started using the modern C++20 coroutines on our project recently. There is a list of coroutines referred to as Tasks in the Executor, which steps through them one by one resuming them. All of this is done on a single thread. Sometimes coroutines need not to be resumed until some predicate is satisfied. In some cases it may be satisfied by another coroutine, which makes suspending for later execution just fine.
Here are the types in use:
struct Task : std::coroutine_handle<task_promise_t> {
using promise_type = task_promise_t;
};
struct task_promise_t {
Task get_return_object() { return {Task::from_promise(*this)}; }
std::suspend_always initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
struct Executor {
/* snip */
void enqueue_task(Task &&task) { tasks.push_back(task); }
void tick() {
while (!tasks.empty())
this->step();
}
void step() {
Task task = std::move(tasks.front());
tasks.pop_front();
task.resume();
if (!task.done())
tasks.push_back(task);
}
std::deque<Task> tasks;
/* snip */
}
Example of how I expect it to be used:
auto exec = Executor();
static bool global_predicate = false;
exec.enqueue_task([](Executor* exec) -> Task {
co_await WaitFor(/* bool(void) */ []() -> bool { return global_predicate; });
/* prerequisite satisfied, other logic goes here */
std::cout << "Hello, world" << std::endl;
}(&exec));
exec.step(); // no output, predicate false
exec.step(); // no output, predicate false
global_predicate = true;
exec.step(); // predicate true, "Hello, world!", coroutine is also done
I did manage to get the implementation going, this seems to work fine.
static bool example_global_predicate;
auto coro = []() -> Task {
while (!example_global_predicate)
co_await std::suspend_always();
/* example_global_predicate is now true, do stuff */
co_return;
}();
But I can't a good way to generalize and abstract it into it's own class. How would one go about it? I would expect to see that functionality in the standard library, but seeing how customizable the coroutines are I doubt there is a way to implement a one-size-fits-all solution.
The "await" style of coroutines is intended for doing asynchronous processing in a way that mirrors the synchronous equivalent. In sinchronous code, you might write:
int func(float f)
{
auto value = compute_stuff(f);
auto val2 = compute_more_stuff(value, 23);
return val2 + value;
}
If one or both of these functions is asychronous, you would rewrite it as follows (assuming the presence of appropriate co_await machinery):
task<int> func(float f)
{
auto value = compute_stuff(f);
auto val2 = co_await async_compute_more_stuff(value, 23);
co_return val2 + value;
}
It's structurally the same code except that in one case, func will halt halfway through until async_compute_more_stuff has finished its computation, then be resumed and return its value through Task<int>. The async nature of the code is as implicit as possible; it largely looks like synchronous code.
If you already have some extant async process, and you just want a function to get called when that process concludes, and there is no direct relationship between them, you don't need a coroutine. This code:
static atomic<bool> example_global_predicate;
auto coro = []() -> Task {
while (!example_global_predicate)
co_await std::suspend_always();
/* example_global_predicate is now true, do stuff */
co_return;
}();
Is not meaningfully different from this:
static atomic<bool> example_global_predicate;
register_polling_task([]() -> bool
{
if(!example_global_predicate)
return false;
/* example_global_predicate is now true, do stuff */
return true;
});
register_polling_task represents some global construct which will at regular intervals call your function until it returns true, at which point it assumes that it has done its job and removes the task. Your coroutine version might hide this global construct, but it still needs to be there because somebody has to wake the coroutine up.
Overall, this is not an async circumstance where using coroutines buys you anything in particular.
However, it could still be theoretically useful to attach coroutine resumption to a polling task. The most reasonable way to do this is to put the polling in a task outside of a coroutine. That is, coroutines shouldn't poll for the global state; that's someone else's job.
A coroutine would do something like co_await PollingTask(). This hands the coroutine_handle off to the system that polls the global state. When that global state enters the correct state, it will resume that handle. And when executing the co_await expression, it should also check the state then, so that if the state is already signaled, it should just not halt the coroutine's execution.
PollingTask() would return an awaitable that has all of this machinery built into it.

C++ async programming, how to not wait for future?

I'm trying to learn async programming in C++. In Python, we have await, with which we can resume a function from that point, but in C++ future waits for the results and halts the next line of code. What if we don't want to get the result, but instead continue to the next line of code? How can I do this?
You can use std::future::wait_for to check if the task has completed execution, e.g.:
if (future.wait_for(100ms) == std::future_status::ready) {
// Result is ready.
} else {
// Do something else.
}
The Concurrency TS includes std::future::is_ready (may be included in C++20), which is non blocking. If it gets included in the standard, usage will be something like:
auto f = std::async(std::launch::async, my_func);
while (!f.is_ready()) {
/* Do other stuff. */
}
auto result = f.get();
/* Do stuff with result. */
Alternatively, the Concurrency TS also includes std::future::then, which I interpret can be used e.g. as:
auto f = std::async(std::launch::async, my_func)
.then([] (auto fut) {
auto result = fut.get();
/* Do stuff when result is ready. */
});
/* Do other stuff before result is ready. */
Also see: How to check if a std::thread is still running?
future waits for the results and halts the next line of code
This is only true when you invoke .get() or when the future is being destroyed. You can run multiple tasks in parallel with std::future:
std::future<int> f = std::async(std::launch::async, foo);
auto res0 = bar();
auto res1 = f.get();
In the example above, bar and foo will run in parallel.
If you want to attach asynchronous continuations to an existing future, currently you cannot do that with std::future.
boost::future supports non-blocking .then(...), .when_all(...), and .when_any(...) continuations. These are proposed for standardization in "Extensions for concurrency".
There's also a "Coroutines" TS that aims to introduce resumable functions and co_await/co_yield.
Unsurprisingly, boost also provides a coroutine library that can be used today to implement resumable functions.

Is there an accepted way of either running a thread or executing sequentially?

Due to reasons outside my control, I have to write code to perform the following action:
If a condition is met, execute the function on a separate thread and wait for it to finish later in the code.
Otherwise, execute the program sequentially by simply calling the function without using a new thread.
boost::thread thread;
if (condition)
{
thread = boost::thread(function);
}
else
{
function();
}
<some more code here>
thread.join();
Is there a better way of doing this than the above code?
Unfortunately, I am quite restricted with what solutions I can use but any advice/idea/opinion is welcome.
A future that is either built ready or running an async task.
As alternative, std::future might help, something like:
std::future<void> fut;
if (condition)
{
fut = std::async(std::launch::async, function);
}
else
{
fut = std::async(std::launch::deferred, function);
fut.wait();
}
// some more code here
fut.wait()
Another take on using futures
std::future<void> fut;
if (condition)
{
fut = std::async(std::launch::async, function);
}
else
{
function();
std::promise<void> prom;
fut = prom.get_future();
prom.set_value();
// or std::experimental::make_ready_future() if avaliable
}
// some more code here
fut.wait()

C++ Callback on thread end and result returning

How can I accomplish this scenario purely asynchronously:
Let's assume there is one thread working asynchronously which creates new thread when some conditions were fullfiled:
class listener {
...
void on_message(data_type data) {
if(some_specific_data_found(data)) {
do_some_work_in_new_thread(new_thread, data, callback_on_end);
}
}
...
void callback_on_end(result_type result) {
do_some_work_in_this_thread(result);
}
...
}
Newly created thread looks like this:
void new_thread(data_type data) {
auto result = do_some_work_here();
push_result(result); // This result should be accessible in
// callback_on_end function.
}
I know that I can achieve similar solution using futures, but I don't want to call any blocking function like get() or wait().
mutex::lock / unlock
http://en.cppreference.com/w/cpp/thread/mutex
you can unlock it when the first thread returns.
I used boost::future::then like this:
boost::future f =
boost::async(boost::launch::async, // start task in new thread
boost::bind(task_code, task_args));
boost::future end_callback = f.then([&](auto i) {
auto result = i.get(); // i is of type future; get() returns object
// of type result_type_of_task_code
// get() is nonblocking
do_something(result);
});

Futures vs. Promises

I'm confusing myself with difference between a future and a promise.
Obviously, they have different methods and stuff, but what is the actual use case?
Is it?:
when I'm managing some async task, I use future to get the value "in future"
when I'm the async task, I use promise as the return type to allow the user get a future from my promise
Future and Promise are the two separate sides of an asynchronous operation.
std::promise is used by the "producer/writer" of the asynchronous operation.
std::future is used by the "consumer/reader" of the asynchronous operation.
The reason it is separated into these two separate "interfaces" is to hide the "write/set" functionality from the "consumer/reader".
auto promise = std::promise<std::string>();
auto producer = std::thread([&]
{
promise.set_value("Hello World");
});
auto future = promise.get_future();
auto consumer = std::thread([&]
{
std::cout << future.get();
});
producer.join();
consumer.join();
One (incomplete) way to implement std::async using std::promise could be:
template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
typedef decltype(func()) result_type;
auto promise = std::promise<result_type>();
auto future = promise.get_future();
std::thread(std::bind([=](std::promise<result_type>& promise)
{
try
{
promise.set_value(func()); // Note: Will not work with std::promise<void>. Needs some meta-template programming which is out of scope for this question.
}
catch(...)
{
promise.set_exception(std::current_exception());
}
}, std::move(promise))).detach();
return std::move(future);
}
Using std::packaged_task which is a helper (i.e. it basically does what we were doing above) around std::promise you could do the following which is more complete and possibly faster:
template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
auto task = std::packaged_task<decltype(func())()>(std::forward<F>(func));
auto future = task.get_future();
std::thread(std::move(task)).detach();
return std::move(future);
}
Note that this is slightly different from std::async where the returned std::future will when destructed actually block until the thread is finished.