C++ delayed tasks
I want to implement a way to schedule a task to be executed at a later time. The interface would be similar to JavaScript's setTimeout(function, milliseconds)
.
In my application certain resources are owned by a thread. To avoid race conditions they must always be accessed from that same thread. If other threads want to access the resource they must dispatch a task object to the resource thread.
So two problems I need to solve are:
The first problem is quickly fixed by using a lock-free queue which has the resource thread at the consuming side. (I use TBB's concurrent_bounded_queue.) The second problem however, is not so obvious for me. I can think of two strategies:
I've experimented with both approaches and I tend to favor the first because it's simple and reliable, while the second tends to be more prone to subtle bugs. The first approach delegates this to the OS thread scheduler.
However, the first solution does create a lot of short-lived threads, while I usually hear the recommendation to reuse threads.
手动执行将如下所示。
struct myrunnable {
uint64_t id_;
uint64_t stamp_;
std::function<void()> runnable_;
uint64_t id() { return id_; }
uint64_t stamp() { return stamp_; }
void execute() { if (runnable_) runnable_(); }
};
typedef std::shared_ptr<myrunnable> task_t;
// timestamp_cmp_t - a comparator by timestamp + incrementing task id
typedef tbb::concurrent_blocking_queue<task_t> queue_t;
typedef std::priority_queue<task, timestamp_cmp_t> schedule_t;
uint64_t now(); // a wrapper around gettimeofday(), write yourself
queue_t queue; // inbound concurrent blocking queue not bound in size
schedule_t schedule; // priority queue, a scheduler
// queue_t sink; // optional sink concurrent queue if you don't
// want to execute tasks in the scheduler thread context
// now() - a wrapper around gettimeofday(), write yourself
for(;;) { // "termination mark" comments below - exit points
while (!schedule.empty() && schedule.top().stamp() <= now()) {
task_t task = schedule.pop();
task .execute();
// alternatively sink.push(task) to offload scheduler thread
}
if (schedule.empty()) {
task_t task = queue.pop(); // block on the input queue
if (!task) return; // scheduler termination mark, empty task
schedule.push(task);
} else {
// Here we are driven by our latency/cpu balance requirements
// in this example we are ultra low latency and are just spinning CPU
// and on Linux such thread may need extra tuning to perform consistently.
// To pace it down one can use TBB's sleep_for() or select() system call
while (schedule.top().stamp() > now()) {
task_t task;
if (queue.try_pop(task)) {
if (!task) return; // scheduler termination mark, empty task
schedule.push(task);
}
}
}
}
链接地址: http://www.djcxy.com/p/14578.html
上一篇: Facebook iOS SDK:如何在请求发布时处理SKIP按钮
下一篇: C ++延迟任务