This source file includes following definitions.
- first_thread
- first_thread
- end
- find
- find
- empty
- clear
- colln
- num_running
1 #ifndef libjmmcg_core_private_fixed_threads_container_hpp
2 #define libjmmcg_core_private_fixed_threads_container_hpp
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include "../../core/non_copyable.hpp"
25 #include "../../core/trace.hpp"
26
27 #include <algorithm>
28 #include <cassert>
29 #include <memory>
30 #include <unordered_map>
31
32 namespace jmmcg { namespace ppd { namespace private_ {
33
34
35
36
37
38
39
40 template<
41 class PTT,
42 class ThrdT
43 >
44 class fixed_pool_of_threads {
45 using internal_container_type=std::vector<ThrdT>;
46
47 public:
48 using pool_traits_type=PTT;
49 using os_traits=typename pool_traits_type::os_traits;
50 using thread_traits=typename os_traits::thread_traits;
51 using container_type=std::unordered_map<
52 typename thread_traits::api_params_type::tid_type,
53 typename internal_container_type::iterator
54 >;
55 using thread_type=typename internal_container_type::value_type;
56 using value_type=thread_type;
57 using key_type=typename container_type::key_type;
58 using iterator=typename container_type::iterator;
59 using const_iterator=typename container_type::const_iterator;
60 using size_type=typename container_type::size_type;
61 using exit_requested_type=typename PTT::template pool_thread_queue_details<typename thread_type::queue_model>::exit_requested_type;
62 using have_work_type=typename PTT::template pool_thread_queue_details<typename thread_type::queue_model>::have_work_type;
63
64 fixed_pool_of_threads(size_type const sz, exit_requested_type &exit_requested, typename internal_container_type::value_type::signalled_work_queue_type &signalled_work_queue) noexcept(false) {
65 pool.reserve(sz);
66 lookup_table.reserve(sz);
67 lookup_table.rehash(sz);
68 for (size_type i=0; i<sz; ++i) {
69 pool.emplace_back(std::ref(exit_requested), std::ref(signalled_work_queue));
70 auto a_thread=std::next(pool.begin(), pool.size()-1);
71 a_thread->create_running();
72 typename thread_traits::api_params_type::processor_mask_type mask(i);
73 try {
74 a_thread->kernel_affinity(mask);
75 } catch (typename thread_type::exception_type const &ex) {
76
77
78 }
79 const auto tid=a_thread->params().id;
80 lookup_table.insert(typename container_type::value_type(tid, a_thread));
81 }
82 assert(pool.size()==lookup_table.size());
83 assert(size()==sz);
84 }
85
86 fixed_pool_of_threads(size_type const sz, exit_requested_type &exit_requested) noexcept(false) {
87 pool.reserve(sz);
88 lookup_table.reserve(sz);
89 lookup_table.rehash(sz);
90 for (size_type i=0; i<sz; ++i) {
91 pool.emplace_back(std::ref(exit_requested));
92 auto a_thread=std::next(pool.begin(), pool.size()-1);
93 a_thread->create_running();
94 typename thread_traits::api_params_type::processor_mask_type mask(i);
95 try {
96 a_thread->kernel_affinity(mask);
97 } catch (typename thread_type::exception_type const &ex) {
98
99
100 }
101 const auto tid=a_thread->params().id;
102 lookup_table.insert(typename container_type::value_type(tid, a_thread));
103 }
104 assert(pool.size()==lookup_table.size());
105 assert(size()==sz);
106 }
107
108 fixed_pool_of_threads(fixed_pool_of_threads const &)=delete;
109 fixed_pool_of_threads &operator=(fixed_pool_of_threads const &)=delete;
110 fixed_pool_of_threads(fixed_pool_of_threads &&)=default;
111 fixed_pool_of_threads &operator=(fixed_pool_of_threads &&)=default;
112
113 thread_type const &first_thread() const noexcept(true) FORCE_INLINE {
114 return *pool.begin();
115 }
116 thread_type &first_thread() noexcept(true) FORCE_INLINE {
117 return *pool.begin();
118 }
119
120 const_iterator end() const noexcept(true) FORCE_INLINE {
121 return lookup_table.end();
122 }
123
124 const_iterator find(key_type key) const noexcept(true) {
125 return lookup_table.find(key);
126 }
127
128 iterator find(key_type key) noexcept(true) FORCE_INLINE {
129 return lookup_table.find(key);
130 }
131
132 bool __fastcall empty() const noexcept(true) FORCE_INLINE {
133 assert(lookup_table.empty()==pool.empty());
134 return pool.empty();
135 }
136
137 size_type __fastcall size() const noexcept(true) FORCE_INLINE {
138 const size_type sz=lookup_table.size();
139 [[maybe_unused]] const size_type currently_running=num_running();
140 assert(sz>=currently_running);
141 return sz;
142 }
143
144 void clear() noexcept(false) FORCE_INLINE {
145
146 assert(lookup_table.size()>=num_running());
147 lookup_table.clear();
148 pool.clear();
149 }
150
151 private:
152 template<class S> friend
153 class wrkr_accumulate_across_threads;
154 template<class S> friend
155 class mstr_accumulate_across_threads;
156 internal_container_type pool;
157 container_type lookup_table;
158
159 internal_container_type const &__fastcall colln() const noexcept(true) FORCE_INLINE {
160 return pool;
161 }
162
163 size_type num_running() const noexcept(true) FORCE_INLINE {
164 assert(pool.size()==lookup_table.size());
165 return std::accumulate(
166 pool.begin(),
167 pool.end(),
168 size_type(),
169 [](size_type const s, typename internal_container_type::const_iterator::value_type const &v) {
170 return s+static_cast<size_type>(v.is_running());
171 }
172 );
173 }
174 };
175
176 } } }
177
178 #endif