Как сделать функцию асинхронной в С++?
Я хочу вызвать функцию, которая будет асинхронной (я дам обратный вызов, когда эта задача будет выполнена).
Я хочу сделать это в одном потоке.
Ответы
Ответ 1
Это можно сделать портативно с помощью современного С++ или даже со старыми С++ и некоторыми boost. Оба boost и С++ 11 включают сложные средства для получения асинхронных значений из потоков, но если все, что вы хотите, является обратным вызовом, просто запустите поток и вызовите его.
1998 С++/boost подход:
#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 С++-подход (с использованием gcc 4.5.2, которому требуется это #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();
}
Ответ 2
Вы не можете использовать простой С++. Вам нужно будет использовать механизм, специфичный для ОС, и вам потребуется точка, в которой выполнение приостанавливается таким образом, чтобы ОС могла выполнить обратный вызов. Например. для Windows, QueueUserAPC
- обратный вызов будет выполнен, когда вы, например. SleepEx
или WaitForSingleObjectEx
Ответ 3
Для этого есть два бита.
Сначала упакуйте вызов функции, чтобы он мог быть выполнен позже.
Во-вторых, планирование его.
Это планирование, которое зависит от других аспектов реализации. Если вы знаете, "когда эта задача выполнена", то все, что вам нужно - вернуться и получить "вызов функции" и вызвать его. Поэтому я не уверен, что это обязательно большая проблема.
Первая часть - это действительно о объектах функций или даже указателях функций. Последние являются традиционным механизмом обратного вызова из C.
Для FO вы можете:
class Callback
{
public:
virtual void callMe() = 0;
};
Вы извлекаете из этого и реализуете это, как вы сочтете нужным для вашей конкретной проблемы. Асинхронная очередь событий - это не более чем list<>
обратных вызовов:
std::list<Callback*> asyncQ; // Or shared_ptr or whatever.
Ответ 4
Длительный ответ включает в себя реализацию вашего собственного планировщика задач и перенос вашей "функции" в одну или несколько задач. Я не уверен, что тебе нужен длинный ответ. Это, безусловно, не позволяет вам что-то называть, полностью забыть об этом, а затем уведомляться, когда это делается; однако, если вы чувствуете амбициозность, это позволит вам симулировать сопрограммы на каком-то уровне, не выходя за пределы стандартного С++.
Короткий ответ заключается в том, что это невозможно. Используйте несколько потоков или несколько процессов. Я могу дать вам более конкретную информацию, если вы раскрываете, какую ОС/платформу вы разрабатываете.
Ответ 5
Я не уверен, что понимаю, что вы хотите, но если это поможет сделать обратный вызов: он работает, определяя указатель на функцию, как это (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);
Ответ 6
Как говорили другие, вы технически не можете на простом С++.
Тем не менее, вы можете создать менеджера, который выполняет вашу задачу и выполняет временное планирование или планирование времени; с каждым вызовом функции менеджер использует таймер для измерения времени, затраченного на процесс; если процесс занимает меньше времени, чем запланировано, и он считает, что он может завершить другой вызов и использовать оставшееся время без переезда, он может снова позвонить ему; если функция перейдет через выделенное время, это означает, что функция имеет меньше времени для следующего обновления для запуска. Таким образом, это будет связано с созданием несколько сложной системы для ее обработки.
Или, если у вас есть определенная платформа, вы можете использовать потоки или создать другой процесс для обработки работы.