SSP21-CPP
ThreadPool.h
1 /*
2  * Copyright (c) 2018, Automatak LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
6  * following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
9  * disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
15  * products derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #ifndef EXE4CPP_ASIO_THREADPOOL_H
26 #define EXE4CPP_ASIO_THREADPOOL_H
27 
28 #include <functional>
29 #include <chrono>
30 #include <thread>
31 
32 #include "asio.hpp"
33 
34 namespace exe4cpp
35 {
36 
37 /**
38 * A thread pool that calls asio::io_service::run
39 */
41 {
42 public:
43  typedef std::function<void(uint32_t)> thread_init_t;
44 
45  ThreadPool(
46  const std::shared_ptr<asio::io_service>& io_service,
47  uint32_t concurrency
48  ) : ThreadPool(
49  io_service,
50  concurrency,
51  [](uint32_t) {},
52  [](uint32_t) {}
53  )
54  {}
55 
56  ThreadPool(
57  const std::shared_ptr<asio::io_service>& io_service,
58  uint32_t concurrency,
59  const thread_init_t& on_thread_start,
60  const thread_init_t& on_thread_exit
61  ) : io_service{io_service},
62  on_thread_start{on_thread_start},
63  on_thread_exit{on_thread_exit},
64  infinite_timer{*io_service}
65  {
66  if (concurrency == 0)
67  {
68  concurrency = 1;
69  }
70 
71  infinite_timer.expires_at(std::chrono::steady_clock::time_point::max());
72  infinite_timer.async_wait([](const std::error_code&) {});
73 
74  for (uint32_t i = 0; i < concurrency; ++i)
75  {
76  auto run = [this, i]()
77  {
78  this->run(i);
79  };
80  threads.push_back(std::make_unique<std::thread>(run));
81  }
82  }
83 
84  virtual ~ThreadPool()
85  {
86  this->shutdown();
87  threads.clear();
88  }
89 
90  void shutdown()
91  {
92  if (!this->is_shutdown)
93  {
94  this->is_shutdown = true;
95  this->infinite_timer.cancel();
96  for (auto& thread : threads)
97  {
98  thread->join();
99  }
100  }
101  }
102 
103 private:
104  void run(uint32_t threadnum)
105  {
106  this->on_thread_start(threadnum);
107 
108  this->io_service->run();
109 
110  this->on_thread_exit(threadnum);
111  }
112 
113  const std::shared_ptr<asio::io_service> io_service;
114 
115  thread_init_t on_thread_start;
116  thread_init_t on_thread_exit;
117 
118  bool is_shutdown = false;
119 
120  asio::basic_waitable_timer<std::chrono::steady_clock> infinite_timer;
121  std::vector<std::unique_ptr<std::thread>> threads;
122 };
123 
124 }
125 
126 #endif
exe4cpp header-only library namespace
Definition: AsioTimer.h:29