我有一个TaskManager类,其中包含一系列任务。每次弹出并执行下一个任务。
class TaskManager
{
TaskQueue m_queue;
svc_tasks()
{
while (!m_queue.empty())
{
Task* task = m_queue.pop();
task->execute();
}
}
};
在“任务”中,我想暂停至少SLEEP_TIME_MS毫秒。在此暂停期间,我想开始执行下一个任务。暂停结束后,我想再次将任务放入队列。
class Task
{
int m_phase = -1;
execute()
{
m_phase++;
switch(m_phase)
{
case 0:
...
do_pause(SLEEP_TIME_MS);
return;
case 1:
...
break;
}
}
};
std(C ++ 17)中是否有我可以使用的调度程序,当SLEEP_TIME_MS通过时会调用处理程序函数吗?
谢谢您的建议
答案 0 :(得分:1)
您可以将boost::asio::high_resolution_timer
和async_wait
方法一起使用。
每次要安排将任务推入队列的操作时,都必须:
high_resolution_timer
expires_after
,它指定到期时间(SLEEP_TIME_MS),即何时调用处理程序。在此处理程序中,您将任务推入队列。async_wait
如果我们假设execute
方法返回bool
来指示任务是否已完成(所有阶段均已执行),则可以将其重写为以下内容:
while (!m_queue.empty()) // this condition should be changed
{
Task* task = m_queue.pop();
bool finished = task->execute();
if (!finished)
scheduler works here - start async_wait with handler
}
如果我的理解正确,您想在SLEEP_TIME_MS
到期时将任务推入队列,因此当队列为空时您就不能中断循环,因为您必须等待待完成的任务完成。您可以引入stop
标志。并按需中断循环。
下面,我放了一段代码,该代码的工作方式与您描述的方式相同(希望如此):
struct Scheduler {
Scheduler(boost::asio::io_context& io)
: io(io) {}
boost::asio::io_context& io;
template<class F>
void schedule (F&& handler) {
auto timer = std::make_shared<boost::asio::high_resolution_timer>(io);
timer->expires_after(std::chrono::milliseconds(5000)); // SLEEP_TIME_MS
timer->async_wait(
[timer,handler](const boost::system::error_code& ec) {
handler();
});
}
};
struct Task {
int phase = -1;
bool execute() {
++phase;
std::cout << "phase: " << phase << std::endl;
if (phase == 0) {
return false;
}
else {
}
return true;
}
};
struct TaskManager {
Scheduler s;
std::queue<std::shared_ptr<Task>> tasks;
std::mutex tasksMtx;
std::atomic<bool> stop{false};
TaskManager(boost::asio::io_context& io) : s(io) {
for (int i = 0; i < 5; ++i)
tasks.push(std::make_shared<Task>());
}
void run() {
while (true) {
if (stop)
break;
{
std::lock_guard<std::mutex> lock{tasksMtx};
if (tasks.empty())
continue;
}
std::shared_ptr<Task> currTask = tasks.front();
tasks.pop();
bool finished = currTask->execute();
if (!finished)
s.schedule( [this, currTask](){ insertTaskToVector(std::move(currTask)); } );
}
}
template<class T>
void insertTaskToVector(T&& t) {
std::lock_guard<std::mutex> lock{tasksMtx};
tasks.push(std::forward<T>(t));
}
};
int main() {
boost::asio::io_context io;
boost::asio::io_context::work work{io};
std::thread th([&io](){ io.run();});
TaskManager tm(io);
tm.run();