std::chrono;
using namespace std;
template<typename F>
struct Job {
time_point<system_clock> time_to_exec;
F func;
};
template<typename F>
inline bool operator<(const Job<F> &lhs, const Job<F> &rhs) {
return lhs.time_to_exec < rhs.time_to_exec;
};
struct Executor
{
Executor() {
runner = thread(&Executor::running, this);
}
~Executor() {
unique_lock<mutex> lock(queue_mutex);
stop = true;
runner.join();
}
void running() {
while(not stop) {
unique_lock<mutex> lock(queue_mutex);
if(jobs.empty()) {
cv.wait(lock, [this] () {not jobs.empty() || stop;});
} else if (jobs.top().time_to_exec > system_clock::now()) {
cv.wait_until(lock, jobs.top().time_to_exec, [this]() {not jobs.empty() || stop;});
} else {
auto job = jobs.top();
jobs.pop();
lock.unlock();
job();
}
}
}
template<typename F>
void exec(F f, milliseconds timeout) {
Job job(f, system_clock::now() + timeout);
unique_lock<mutex> lock(queue_mutex);
jobs.push(job);
cv.notify_one();
}
priority_queue<Job<F>> jobs; // <-----------?... o_O
mutex queue_mutex;
condition_variable cv;
thread runner;
bool stop = false;
};
string str = "1234567";
int foo(int 5) {
cout << "out finally!" << str[5] << endl;
};
int main()
{
Executor executor;
executor.exec([](){cout << "out finally!";}, seconds{5});
executor.exec(&foo, 5, seconds{7});
cout<<"Hello World";
return 0;
}
А что не работает? Виснет в деструкторе Executor?
Я удалил твой пост с длинной ссылкой, сори. Если надо - пришли как-то по-другому
Не компилится. Получается, Job при создание параметризуется конкретным задаваемым типом функции. А в очереди нужно знать тип Job, который должен быть один - параметризирован лишь одним типом параметра == одним типом функции, что сильно ограничивает применение.
Гляньте тут, сравните со своим кодом https://godbolt.org/z/xdKoqExzo
Вау) Здорово) Спасибо) Т.е. Executor<std::function<void()>> executor; std::function<void()> - как общий тип F, под который подходит любая сигнатура функции? Что обычной, что передаваемой с параметрами, обёрнутая в bind?
А как ты собираешься эти разные функции вызывать потом ? Надо сводить это всё к одному виду функций
Да, std::function<void()> - "универсальный" тип для жобы без аргументов и возвращающей void.
И что к такой функции можно свести любые типы функции. Ну, почти любые, получается. Любые с точки зрения - хоть какие передаваемые параметры. Без возвращаемого значения просто.
Ну вот в этом и загвоздка была. Что я не знал о таком универсальном типе.
И что к такой функции можно свести любые типы функции. Ну, почти любые, получается. Любые с точки зрения - хоть какие передаваемые параметры. Без возвращаемого значения просто.
Не совсем понял в отношении универсальный. Это же конкретная сигнатура, ничего не принимает, ничего не отдает.
А ты имеешь ввиду универсальный в том плане, что в нее можно передать не только голую функцию, а например, класс, с оператором "функция" (часто именуемый функтор), это да. Но сигнатура должна четко совпадать.
Ну да. Спасибо Александру. Сейчас классно получилось, что можно передать: void foo(); и void bar(int x, char y) и лямбду похожей сигнатуры Если нужно возвращаемое значение - это уже, наверное, по-другому реализовывать. Видел что-то похожее с выдачей пользователю future. Т.е. асинхронно/параллельно исполнили и положили результат. Сверху/в другом ожидающем потоке просто future.get() - забираешь результат.
Я не знал, что в std::function<void()> можно положить void bar(int x, char y). Буду знать. Спасибо.
А где про это почитать? На cppref не вижу, вроде
Так статья про std::function. ... is a general-purpose polymorphic function wrapper... https://en.cppreference.com/w/cpp/utility/functional/function
не, именно про то, что в std::function<void()> можно класть любые функции
Ну, не любые вообще. Без аргументов и без возвращаемого значения. В той же статье написно
А, все-таки без аргументов, тогда все нормально. Просто в https://t.me/supapro/1353545 меня смутило "Я не знал, что в std::function<void()> можно положить void bar(int x, char y)"
bind подразумевался, наверное
Обсуждают сегодня