concurrency.h 1.7 KB
Newer Older
S
superjom 已提交
1 2 3
#ifndef VISUALDL_BACKEND_UTILS_CONCURRENCY_H
#define VISUALDL_BACKEND_UTILS_CONCURRENCY_H

S
superjom 已提交
4
#include <glog/logging.h>
S
superjom 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17
#include <chrono>
#include <memory>
#include <thread>
#include <vector>

namespace visualdl {
namespace cc {

/*
 * Run a task every `duration` milliseconds.
 * Each evoke will start a thread to do this asynchronously.
 */
struct PeriodExector {
S
superjom 已提交
18
  using task_t = std::function<bool()>;
S
superjom 已提交
19

S
superjom 已提交
20
  static PeriodExector& Global() {
S
superjom 已提交
21 22 23 24 25 26 27 28 29
    static PeriodExector exec;
    return exec;
  }

  void Quit() {
    // TODO use some conditonal variable to help quit immediately.
    quit = true;
  }

S
superjom 已提交
30 31
  void Start() { quit = false; }

S
superjom 已提交
32
  void operator()(task_t&& task, int msec) {
S
superjom 已提交
33 34
    const int interval = 500;

S
superjom 已提交
35
    auto task_wrapper = [=] {
S
superjom 已提交
36
      while (!quit) {
S
superjom 已提交
37
        if (!task()) break;
S
superjom 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51
        // if the program is terminated, quit while as soon as possible.
        // this is just trick, but should works.
        if (msec > 1000) {
          int i;
          for (i = 0; i < msec / interval; i++) {
            if (quit) break;
            std::this_thread::sleep_for(std::chrono::milliseconds(interval));
          }
          std::this_thread::sleep_for(
              std::chrono::milliseconds(msec - i * interval));
          if (quit) break;
        } else {
          std::this_thread::sleep_for(std::chrono::milliseconds(msec));
        }
S
superjom 已提交
52
      }
S
superjom 已提交
53
      LOG(INFO) << "quit concurrent job";
S
superjom 已提交
54 55
    };
    threads_.emplace_back(std::thread(std::move(task_wrapper)));
S
superjom 已提交
56
    msec_ = msec;
S
superjom 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69
  }

  ~PeriodExector() {
    for (auto& t : threads_) {
      if (t.joinable()) {
        t.join();
      }
    }
  }

private:
  bool quit = false;
  std::vector<std::thread> threads_;
S
superjom 已提交
70
  int msec_;
S
superjom 已提交
71 72 73 74 75 76
};

}  // namespace cc
}  // namespace visualdl

#endif