Hybrid ICN (hICN) plugin  v21.06-rc0-4-g18fa668
event_thread.h
1 /*
2  * Copyright (c) 2017-2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include <hicn/transport/config.h>
19 #include <hicn/transport/core/asio_wrapper.h>
20 #include <hicn/transport/errors/runtime_exception.h>
21 
22 #include <memory>
23 #include <thread>
24 
25 namespace utils {
26 
27 class EventThread {
28  public:
29  EventThread(asio::io_service& io_service, bool detached = false)
30  : internal_io_service_(nullptr),
31  io_service_(std::ref(io_service)),
32  work_(std::make_unique<asio::io_service::work>(io_service_)),
33  thread_(nullptr),
34  detached_(detached) {
35  run();
36  }
37 
38  EventThread(bool detached = false)
39  : internal_io_service_(std::make_unique<asio::io_service>()),
40  io_service_(std::ref(*internal_io_service_)),
41  work_(std::make_unique<asio::io_service::work>(io_service_)),
42  thread_(nullptr),
43  detached_(detached) {
44  run();
45  }
46 
47  EventThread(const EventThread&) = delete;
48  EventThread& operator=(const EventThread&) = delete;
49 
50  EventThread(EventThread&& other)
51  : internal_io_service_(std::move(other.internal_io_service_)),
52  io_service_(std::move(other.io_service_)),
53  work_(std::move(other.work_)),
54  thread_(std::move(other.thread_)),
55  detached_(std::move(other.detached_)) {}
56 
57  EventThread& operator=(EventThread&& other) {
58  internal_io_service_ = std::move(other.internal_io_service_);
59  io_service_ = std::move(other.io_service_);
60  work_ = std::move(other.work_);
61  thread_ = std::move(other.thread_);
62  detached_ = other.detached_;
63 
64  return *this;
65  }
66 
67  ~EventThread() { stop(); }
68 
69  void run() {
70  if (stopped()) {
71  io_service_.get().stopped();
72  }
73 
74  thread_ =
75  std::make_unique<std::thread>([this]() { io_service_.get().run(); });
76 
77  if (detached_) {
78  thread_->detach();
79  }
80  }
81 
82  std::thread::id getThreadId() const {
83  if (thread_) {
84  return thread_->get_id();
85  } else {
86  throw errors::RuntimeException("Event thread is not running.");
87  }
88  }
89 
90  template <typename Func>
91  void add(Func&& f) {
92  io_service_.get().post(std::forward<Func&&>(f));
93  }
94 
95  template <typename Func>
96  void tryRunHandlerNow(Func&& f) {
97  io_service_.get().dispatch(std::forward<Func&&>(f));
98  }
99 
100  void stop() {
101  work_.reset();
102 
103  if (thread_ && thread_->joinable()) {
104  thread_->join();
105  }
106 
107  thread_.reset();
108  }
109 
110  bool stopped() { return io_service_.get().stopped(); }
111 
112  asio::io_service& getIoService() { return io_service_; }
113 
114  private:
115  std::unique_ptr<asio::io_service> internal_io_service_;
116  std::reference_wrapper<asio::io_service> io_service_;
117  std::unique_ptr<asio::io_service::work> work_;
118  std::unique_ptr<std::thread> thread_;
119  bool detached_;
120 };
121 
122 } // namespace utils
utils::EventThread
Definition: event_thread.h:27
errors::RuntimeException
Definition: runtime_exception.h:25