libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
thread_params_traits.hpp
Go to the documentation of this file.
1 #ifndef LIBJMMCG_CORE_THREAD_PARAMS_TRAITS_HPP
2 #define LIBJMMCG_CORE_THREAD_PARAMS_TRAITS_HPP
3 
4 /******************************************************************************
5 ** Copyright © 2004 by J.M.McGuiness, coder@hussar.me.uk
6 **
7 ** This library is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU Lesser General Public
9 ** License as published by the Free Software Foundation; either
10 ** version 2.1 of the License, or (at your option) any later version.
11 **
12 ** This library is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ** Lesser General Public License for more details.
16 **
17 ** You should have received a copy of the GNU Lesser General Public
18 ** License along with this library; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 
22 #ifdef _MSC_VER
23 # pragma warning(disable:4786) // identifier was truncated to '255' characters in the debug information
24 #endif
25 
26 #include "info.hpp"
27 #include "ttypes.hpp"
28 
29 #include <boost/mpl/assert.hpp>
30 
31 #include <cassert>
32 #include <array>
33 
34 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE { namespace ppd {
35 
36  /**
37  These parameters allow the users to choose a thread pool that has the
38  properties they would like. Note that not all combinations make sense,
39  so will give compilation errors, as they are not implemented, and of the
40  rest, some of those may not be implemented. Contact the author if you need
41  a specific specialisation!
42  */
43  namespace generic_traits {
44  enum class creation_cost {
46  expensive_to_create, ///< E.g. x86 ISA & Win32
47  cheap_to_create ///< E.g. IBM BlueGene/[C|P] (or Cyclops)
48  };
49  enum class destruction_cost {
51  expensive_to_destroy, ///< E.g. x86 ISA & Win32
52  cheap_to_destroy ///< E.g. IBM BlueGene/[C|P] (or Cyclops)
53  };
54  enum class synchronisation_cost { ///< The cost of the base read-modify-write operation used to implement a mutex.
56  expensive_to_synchronise, ///< E.g. x86 ISA & Win32
57  cheap_to_synchronise ///< E.g. IBM BlueGene/[C|P] (or Cyclops)
58  };
59  enum class return_data {
60  joinable, ///< The work has a return value.
61  nonjoinable ///< The work does not have a return value.
62  };
63  enum class api_type {
64  no_api, ///< For sequential operation. i.e. no threading. Usually one would use the constant platform_api, which is suitably declared as one of the threading models, below.
65  MS_Win32, ///< Usually "heavy-weight" threads, e.g. x86, alpha.
66  posix_pthreads, ///< Usually "heavy-weight" threads, e.g. x86, alpha, SPARC. On Solaris, Linux, etc.
67  IBM_cyclops ///< IBM BlueGene/[C|P] (or Cyclops), ~10^6-~10^9 lightweight threads, NUMA architecture.
68  };
69 
70  inline tostream & __fastcall FORCE_INLINE
71  operator<<(tostream &os, api_type const &api) {
72  switch (api) {
73  case api_type::MS_Win32:
74  os<<_T("MS_Win32");
75  break;
77  os<<_T("posix_pthreads");
78  break;
80  os<<_T("IBM_cyclops");
81  break;
82  case api_type::no_api:
83  default:
84  os<<_T("no_api");
85  }
86  return os;
87  }
88  /// The various memory access modes that the assorted locks may support.
89  /**
90  To assist in allowing compile-time computation of the algorithmic order of the threading model.
91  */
92  enum class memory_access_modes {
93  erew_memory_access, ///< Exclusive-Read, Exclusive-Write memory access.
94  crew_memory_access ///< Concurrent-Read, Exclusive-Write memory access.
95  };
96  }
97 
98  /// A namespace to hold various traits relating to selecting the specific specialisation of thread_pool they would like.
99  /**
100  These parameters allow the users to choose a thread_pool that has the properties they would like. Note that not all combinations make sense, so will give compilation errors, as they are not implemented, and of the rest, some of those may not be implemented. Contact the author if you need a specific specialisation!
101  */
102  namespace pool_traits {
103  /// Various models of work distribution.
105  namespace queue_model_t {
106  /// The thread_pool owns a single queue into which input_work is placed & from which thread_wk_t is distributed.
107  /**
108  Work stealing from the queue; the adding work to and removing work from the queue is the limiting resource, possibly lock-free or with some sort of lock_type, that may have some sort of anon_semaphore to indicate to waiting pool_threads that it contains work.
109 
110  \see intrusive::slist, safe_colln
111  */
112  struct pool_owns_queue {};
113 
114  enum class stealing_mode_t {
115  random ///< When a pool_thread runs out of work it chooses another pool_thread to steal from at random.
116  };
117  /// The pool_threads own a queue each into which work that thread places work it generates.
118  template<stealing_mode_t SM>
120  static inline constexpr stealing_mode_t stealing_mode=SM;
121  };
122  }
123  ///. Master-slave; the master thread would be the limiting resource.
124  template<class QM=queue_model_t::pool_owns_queue>
126  BOOST_MPL_ASSERT((std::is_same<QM, queue_model_t::pool_owns_queue>));
127  using queue_model=queue_model_t::pool_owns_queue;
128  };
129  template<class QM>
131  using queue_model=QM;
132  };
133  }
134  /// Control the size of the thread pool in various ways.
135  enum class size_mode_t {
136  sequential, ///< Specify a serial thread pool, i.e. no threading.
137  fixed_size, ///< Specify n threads to be in the pool.
138  time_average_size, ///< Allow some automated mechanism to control the pool size.
139  tracks_to_max, ///< Have a maximum of n threads, but less or zero according to outstanding work.
140  infinite ///< Specify a situation where a thread is spawned per job, with no limits.
141  };
142  /// Specifiy if the thread_pool can sort work by some form of priority, executing the highest first.
143  enum class priority_mode_t {
144  normal, ///< No priority, a strict fifo.
145  priority ///< The work items should have some form of partial ordering specified upon them.
146  };
147  }
148 
149  /**
150  Clearly you should provide some useful types for these when you specialise this class for an API!
151  */
152  template<generic_traits::api_type API>
154  public:
155  typedef int stack_size_type;
156 
157  static inline constexpr generic_traits::api_type api_type=API;
158  static inline constexpr stack_size_type max_stack_size=std::numeric_limits<stack_size_type>::max();
159 
160  typedef int handle_type;
161  typedef int pid_type;
162  typedef int tid_type;
163  using username_type=std::array<char, 256>; ///< The size is a guess...
164 
165  typedef int processor_mask_type;
166 
167  typedef int suspend_count;
168  typedef int suspend_period_ms;
169 
170  typedef int security_type;
171  typedef void core_work_fn_ret_t;
172  typedef void core_work_fn_arg_t;
173 
174 #pragma GCC diagnostic push
175 #pragma GCC diagnostic ignored "-Wattributes"
176 
177  typedef core_work_fn_ret_t (__cdecl core_work_fn_type)(void);
178 
179 #pragma GCC diagnostic pop
180 
181  typedef int arglist_type;
182  typedef void initflag_type;
183 
187  };
197  };
198 
199  /**
200  Note that these states are in a specific order - the higher the number, the more severe any error.
201  */
202  enum states {
203  no_kernel_thread=0, ///< This is not a failure - the thread may not be started yet, or may have exited.
207  // Error conditions now...
218  unknown
219  };
223  };
224 
227  core_work_fn_type * const work_fn;
229 
232 
233  explicit __stdcall thread_params(core_work_fn_type * const sa, const security_type se=0, const stack_size_type ss=0) noexcept(true) FORCE_INLINE
234  : security(se), stack_size(ss), work_fn(sa), arglist(), handle(), id() {
235  assert(work_fn);
236  }
237 
238  const tstring to_string() const {
239  tostringstream ss;
240  ss<<_T("API type: 0x")<<std::hex<<api_type
241  <<_T(", work function ptr: 0x")<<std::hex<<work_fn
242  <<_T(", argument list: 0x")<<std::hex<<arglist
243  <<_T(", handle: 0x")<<std::hex<<handle
244  <<_T(", ID: 0x")<<std::hex<<id;
245  return ss.str();
246  }
247  };
248 
249  template<generic_traits::api_type API> inline tostream & __fastcall FORCE_INLINE
250  operator<<(tostream &os, thread_params<API> const &p) {
251  os<<p.to_string();
252  return os;
253  }
254 
256  struct model_traits {
257  static inline constexpr generic_traits::creation_cost creation=Cr;
258  static inline constexpr generic_traits::destruction_cost destruction=Dr;
260  };
261 
262  /**
263  These typedefs provide quick ways to get to the various implemented threading models.
264  */
265  using sequential_mode=model_traits<
269  >; ///< I.e. single-threaded, no locks.
270  using heavyweight_threading=model_traits<
274  >; /// E.g. x86 or SPARC.
275  using lightweight_threading=model_traits<
279  >; /// E.g. IBM BlueGene/[C|P] (or Cyclops)
280 
281 } } }
282 
283 #ifdef WIN32
284 # include "../experimental/NT-based/NTSpecific/thread_params_traits.hpp"
285 #elif defined(__unix__)
286 # include "../unix/thread_params_traits.hpp"
287 #endif
288 
289 #endif