Electroneum
thread_group.h
Go to the documentation of this file.
1 // Copyrights(c) 2017-2019, The Electroneum Project
2 // Copyrights(c) 2014-2017, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #pragma once
30 
31 #include <boost/optional/optional.hpp>
32 #include <boost/thread/condition_variable.hpp>
33 #include <boost/thread/mutex.hpp>
34 #include <boost/thread/thread.hpp>
35 #include <cstddef>
36 #include <functional>
37 #include <thread>
38 #include <utility>
39 #include <vector>
40 
41 namespace tools
42 {
45 {
46 public:
47 
49  static std::size_t optimal();
50 
52  static std::size_t optimal_with_max(std::size_t count);
53 
55  explicit thread_group() : thread_group(optimal()) {}
56 
58  explicit thread_group(std::size_t count);
59 
60  thread_group(thread_group const&) = delete;
61  thread_group(thread_group&&) = delete;
62 
64  ~thread_group() = default;
65 
66  thread_group& operator=(thread_group const&) = delete;
67  thread_group& operator=(thread_group&&) = delete;
68 
70  std::size_t count() const noexcept {
71  if (internal) {
72  return internal->count();
73  }
74  return 0;
75  }
76 
78  bool try_run_one() noexcept {
79  if (internal) {
80  return internal->try_run_one();
81  }
82  return false;
83  }
84 
89  template<typename F>
90  void dispatch(F&& f) {
91  if (internal) {
92  internal->dispatch(std::forward<F>(f));
93  }
94  else {
95  f();
96  }
97  }
98 
99 private:
100  class data {
101  public:
102  data(std::size_t count);
103  ~data() noexcept;
104 
105  std::size_t count() const noexcept {
106  return threads.size();
107  }
108 
109  bool try_run_one() noexcept;
110  void dispatch(std::function<void()> f);
111 
112  private:
113  struct work;
114 
115  struct node {
116  std::unique_ptr<work> ptr;
117  };
118 
119  struct work {
120  std::function<void()> f;
122  };
123 
125  std::unique_ptr<work> get_next() noexcept;
126 
128  void run() noexcept;
129 
130  private:
131  std::vector<boost::thread> threads;
134  boost::condition_variable has_work;
136  bool stop;
137  };
138 
139 private:
140  // optionally construct elements, without separate heap allocation
141  boost::optional<data> internal;
142 };
143 
144 }
node * last
Definition: thread_group.h:133
bool stop
Definition: thread_group.h:136
std::unique_ptr< work > ptr
Definition: thread_group.h:116
Definition: unordered_containers_boost_serialization.h:38
std::size_t count() const noexcept
Definition: thread_group.h:105
#define F(w, k)
Definition: sha512-blocks.c:61
void dispatch(std::function< void()> f)
Definition: thread_group.cpp:141
void run() noexcept
Blocks until destructor is invoked, only call from thread.
Definition: thread_group.cpp:123
static std::size_t optimal_with_max(std::size_t count)
Definition: thread_group.cpp:50
Definition: thread_group.h:119
Definition: block_queue.cpp:41
~data() noexcept
Definition: thread_group.cpp:75
node next
Definition: thread_group.h:121
node head
Definition: thread_group.h:132
std::unique_ptr< work > get_next() noexcept
Requires lock on mutex.
Definition: thread_group.cpp:89
Definition: thread_group.h:100
boost::optional< data > internal
Definition: thread_group.h:141
Manages zero or more threads for work dispatching.
Definition: thread_group.h:44
Various Tools.
Definition: base58.cpp:43
~thread_group()=default
Joins threads, but does not necessarily run all dispatched functions.
static std::size_t optimal()
Definition: thread_group.cpp:41
bool try_run_one() noexcept
Definition: thread_group.h:78
bool try_run_one() noexcept
Definition: thread_group.cpp:100
thread_group & operator=(thread_group const &)=delete
boost::mutex mutex
Definition: thread_group.h:135
std::size_t count() const noexcept
Definition: thread_group.h:70
data(std::size_t count)
Definition: thread_group.cpp:60
thread_group()
Create an optimal number of threads.
Definition: thread_group.h:55
std::vector< boost::thread > threads
Definition: thread_group.h:131
boost::condition_variable has_work
Definition: thread_group.h:134
std::function< void()> f
Definition: thread_group.h:120
void dispatch(F &&f)
Definition: thread_group.h:90
Definition: thread_group.h:115