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

39,827

Solution 1

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();
}

Solution 2

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

Solution 3

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.

Solution 4

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.

Solution 5

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.
Share:
39,827

Related videos on Youtube

yogesh
Author by

yogesh

Updated on July 09, 2022

Comments

  • yogesh
    yogesh almost 2 years

    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.

    • Kiran Kumar
      Kiran Kumar about 13 years
      C++ has no concept of threads. You need to specify the OS and libraries you are using to get a useful answer.
    • Martin York
      Martin York about 13 years
      @Naveen: I have yet to find a C/C++ system that does not support pthreads.
  • kqnr
    kqnr about 13 years
    This would be awesome if it fulfilled the asynchronous requirement - meaning doSomeWorkWithCallback(myCallback) would return immediately while continuing to do work in parallel with the caller, and myCallback would be called at some later time when said work was finished. Alas...
  • DarkDust
    DarkDust about 13 years
    Using a runloop it is possible to do asynchronous stuff in a single thread (but you probably need a complete framework with support for that). Apple's Objective-C/Cocoa framework is a nice example of how it can be done.
  • kqnr
    kqnr about 13 years
    Well, I wouldn't call Cocoa a "nice" example of anything (IMHO!;)), but yes - that is a good example of a single-threaded task scheduler.
  • Damon
    Damon about 13 years
    Well, in theory, if you can figure out std::async and std::future... modern compilers certainly support those. Though sure enough I can't figure them out so a 2 liner produces less than 5 compiler errors... so yeah, +1 on QueueUserAPC.
  • yogesh
    yogesh about 13 years
    Yes this is what I exactly wanted
  • yogesh
    yogesh about 13 years
    I was wondering if this can be done using Timers..I know this is possible in symbian. I am using Bada framework.They have a library for timers.But I am not sure how to exactly do that
  • yogesh
    yogesh about 13 years
    I am using Bada, but I am not sure if everyone is familiar with it..thats why I was asking a generic approach
  • Alex
    Alex over 3 years
    in 2020, this is the best answer
  • jenkas
    jenkas over 2 years
    Can you co_await on future?

Related