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:

  • dispatch a task to a thread
  • delay the invocation
  • 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:

  • Start a new thread for each task. This thread will sleep the required delay, then dispatch the task to the concurrent queue.
  • Start only one thread which runs a loop that iterates the scheduled tasks and invokes them if their waiting time has expired.
  • 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 ++延迟任务