CMS 3D CMS Logo

WaitingThreadPool.h
Go to the documentation of this file.
1 #ifndef FWCore_Concurrency_WaitingThreadPool_h
2 #define FWCore_Concurrency_WaitingThreadPool_h
3 
7 
8 #include <condition_variable>
9 #include <mutex>
10 #include <thread>
11 
12 namespace edm {
13  namespace impl {
14  class WaitingThread {
15  public:
16  WaitingThread();
17  ~WaitingThread() noexcept;
18 
19  WaitingThread(WaitingThread const&) = delete;
21  WaitingThread(WaitingThread&&) = delete;
22  WaitingThread& operator=(WaitingThread const&) = delete;
23 
24  template <typename F, typename G>
26  F&& func,
27  G&& errorContextFunc,
28  std::shared_ptr<WaitingThread> thisPtr) {
29  std::unique_lock lk(mutex_);
30  func_ = [holder = std::move(holder),
31  func = std::forward<F>(func),
32  errorContext = std::forward<G>(errorContextFunc)]() mutable {
33  try {
34  convertException::wrap([&func]() { func(); });
35  } catch (cms::Exception& e) {
36  e.addContext(errorContext());
37  holder.doneWaiting(std::current_exception());
38  }
39  };
40  thisPtr_ = std::move(thisPtr);
41  cond_.notify_one();
42  }
43 
44  private:
45  void stopThread() {
46  std::unique_lock lk(mutex_);
47  stopThread_ = true;
48  cond_.notify_one();
49  }
50 
51  void threadLoop() noexcept;
52 
53  std::thread thread_;
55  std::condition_variable cond_;
57  // The purpose of thisPtr_ is to keep the WaitingThread object
58  // outside of the WaitingThreadPool until the func_ has returned.
61  };
62  } // namespace impl
63 
64  // Provides a mechanism to run the function 'func' asynchronously,
65  // i.e. without the calling thread to wait for the func() to return.
66  // The func should do as little work (outside of the TBB threadpool)
67  // as possible. The func must terminate eventually. The intended use
68  // case are blocking synchronization calls with external entities,
69  // where the calling thread is suspended while waiting.
70  //
71  // The func() is run in a thread that belongs to a separate pool of
72  // threads than the calling thread. Remotely similar to
73  // std::async(), but instead of dealing with std::futures, takes an
74  // edm::WaitingTaskWithArenaHolder object, that is signaled upon the
75  // func() returning or throwing an exception.
76  //
77  // The caller is responsible for keeping the WaitingThreadPool
78  // object alive at least as long as all asynchronous calls finish.
80  public:
81  WaitingThreadPool() = default;
82  WaitingThreadPool(WaitingThreadPool const&) = delete;
86 
95  template <typename F, typename G>
96  void runAsync(WaitingTaskWithArenaHolder holder, F&& func, G&& errorContextFunc) {
97  auto thread = pool_.makeOrGet([]() { return std::make_unique<impl::WaitingThread>(); });
98  thread->run(std::move(holder), std::forward<F>(func), std::forward<G>(errorContextFunc), std::move(thread));
99  }
100 
101  private:
103  };
104 } // namespace edm
105 
106 #endif
static std::mutex mutex
Definition: Proxy.cc:8
void doneWaiting(std::exception_ptr iExcept)
edm::ReusableObjectHolder< impl::WaitingThread > pool_
#define CMS_THREAD_GUARD(_var_)
void runAsync(WaitingTaskWithArenaHolder holder, F &&func, G &&errorContextFunc)
std::shared_ptr< WaitingThread > thisPtr_
void run(WaitingTaskWithArenaHolder holder, F &&func, G &&errorContextFunc, std::shared_ptr< WaitingThread > thisPtr)
HLT enums.
WaitingThread & operator=(WaitingThread &&)=delete
auto wrap(F iFunc) -> decltype(iFunc())
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:163
std::condition_variable cond_
std::function< void()> func_
def move(src, dest)
Definition: eostools.py:511