libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
atomic_counter.hpp
Go to the documentation of this file.
1 #ifndef LIBJMMCG_CORE_ATOMIC_CTR_HPP
2 #define LIBJMMCG_CORE_ATOMIC_CTR_HPP
3 
4 /******************************************************************************
5 ** Copyright © 2007 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 #include "deleter.hpp"
24 
25 #include <atomic>
26 
27 #ifdef __GCC__
28 # pragma GCC diagnostic push
29 # pragma GCC diagnostic ignored "-Wsuggest-final-methods"
30 #endif
31 
32 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
33 
34  /// An optional interface for the intrusive sp_counter_type.
35  /**
36  If a client wishes to dynamically, as opposed to statically, specify the increment, decrement or deletion methods, then they must inherit from this class in some base within their object hierarchy. For example if one has a mix of objects in a collection, in which some are are heap allocated, others allocated via placement new in a pre-allocated buffer, i.e. a custom memory-manager.
37 
38  \see sp_counter_type, shared_ptr
39  */
40  template<
41  class V ///< The type of the value to be atomically controlled.
42  >
44  public:
45  typedef V value_type;
46  /// The default deletion method for objects that inherit from this intrusively-counted type, which is just heap-deletion, if the objects are heap-allocated.
47  /**
48  \see deleter()
49  */
51 
52  /**
53  To assist in allowing compile-time computation of the algorithmic order of the threading model.
54  */
56 
57  virtual ~sp_counter_itf_type() {}
58 
59  virtual value_type sp_count() const noexcept(true) {
60  return value_type(1);
61  }
62  virtual value_type sp_acquire() noexcept(true) {
63  return value_type(1);
64  }
65  virtual bool sp_release() noexcept(true) {
66  return true;
67  }
68  /**
69  This is a hack: we could use a dynamic_cast to check this, but in GCC dynamic_casts involve strcmps which may be slowish, so use a virtual thunk instead, which should be faster.
70  */
71  virtual bool sp_noop_ctr() const noexcept(true) {
72  return true;
73  }
74 
75  virtual bool __fastcall operator<(const value_type) const noexcept(true) {
76  return false;
77  }
78  virtual bool __fastcall operator>(const value_type) const noexcept(true) {
79  return true;
80  }
81  virtual bool __fastcall operator>=(const value_type) const noexcept(true) {
82  return true;
83  }
84  constexpr bool FORCE_INLINE operator==(const value_type v) const noexcept(true) {
85  return !(*this<v) && !(*this>v);
86  }
87 
88  /// Call the correct deleter_t object to delete the object.
89  /**
90  Note that we are calling the dtor on the object from within a virtual function, which is allowed. (The converse is not, of course.)
91  */
92  virtual void deleter() {
93  deleter_t().operator()(this);
94  }
95 
96  virtual tstring
97  sp_to_string() const noexcept(false) {
98  return tstring();
99  }
100 
102  operator<<(tostream &os, sp_counter_itf_type const &v) {
103  os<<v.sp_to_string();
104  return os;
105  }
106 
107  protected:
108  constexpr sp_counter_itf_type() noexcept(true) {}
109  };
110 
111 namespace ppd {
112 
113  template<generic_traits::api_type API, typename Mdl>
114  struct api_lock_traits;
115 
116  /// A general-purpose, atomic counter class, similar to the atomic integer types in C++11 ch 29.
117  /**
118  Note that this class is a valid value-type.
119  Also note that this class reduces to a simple V-type, if it is single threaded, so costs nothing.
120  */
121  template<
122  class V, ///< The type of the value for the counter. Note that this must be a type that is atomically manipulated on the target architecture, such as int or long. i.e. no word-tearing.
123  class LkT
124  >
125  class atomic_ctr_gen : public virtual sp_counter_itf_type<V> {
126  public:
128  typedef LkT lock_traits;
130  typedef typename base_t::value_type value_type;
131  /**
132  To assist in allowing compile-time computation of the algorithmic order of the threading model.
133  */
135 
136  public:
137  constexpr atomic_ctr_gen() noexcept(noexcept(value_type()) && noexcept(atomic_t())) FORCE_INLINE;
138  explicit constexpr atomic_ctr_gen(const value_type v) noexcept(noexcept(value_type(std::declval<value_type>())) && noexcept(atomic_t())) FORCE_INLINE;
139  constexpr atomic_ctr_gen(const atomic_ctr_gen &) noexcept(false) FORCE_INLINE;
140  template<class V1>
141  constexpr atomic_ctr_gen(const atomic_ctr_gen<V1, LkT> &) noexcept(false) FORCE_INLINE;
142  template<class V1>
143  atomic_ctr_gen(atomic_ctr_gen<V1, LkT> &&) noexcept(true) FORCE_INLINE;
144  ~atomic_ctr_gen() noexcept(true);
145  void swap(atomic_ctr_gen &rhs) noexcept(true) FORCE_INLINE;
146  template<class V1, class V2=V1>
147  typename std::enable_if<std::is_pointer<V2>::value, void>::type swap(atomic_ctr_gen<V1, LkT> &rhs) noexcept(true) FORCE_INLINE;
148  template<class V1, class V2=V1>
149  typename std::enable_if<std::is_pointer<V2>::value, void>::type __fastcall operator=(const atomic_ctr_gen<V1, LkT> &v) noexcept(true) FORCE_INLINE;
150  void __fastcall operator=(const atomic_ctr_gen &) noexcept(true) FORCE_INLINE;
151  void __fastcall operator=(const value_type &) noexcept(true) FORCE_INLINE;
152 
153  constexpr bool FORCE_INLINE sp_noop_ctr() const noexcept(true) override {
154  return false;
155  }
156 
157  constexpr value_type const &__fastcall get() const noexcept(true) FORCE_INLINE;
158 
159  constexpr bool __fastcall operator!() const noexcept(true) FORCE_INLINE;
160 
161  constexpr bool __fastcall operator==(const value_type) const noexcept(true) FORCE_INLINE;
162  constexpr bool __fastcall operator==(const atomic_ctr_gen &) const noexcept(true) FORCE_INLINE;
163  constexpr bool __fastcall operator!=(const value_type) const noexcept(true) FORCE_INLINE;
164  constexpr bool __fastcall operator!=(const atomic_ctr_gen &) const noexcept(true) FORCE_INLINE;
165  constexpr bool __fastcall operator<(const value_type) const noexcept(true) FORCE_INLINE override;
166  constexpr bool __fastcall operator<(const atomic_ctr_gen &) const noexcept(true) FORCE_INLINE;
167 // TODO constexpr bool __fastcall operator<(sp_counter_itf_type const &) const noexcept(true) FORCE_INLINE;
168  constexpr bool __fastcall operator<(base_t const &) const noexcept(true) FORCE_INLINE;
169  constexpr bool __fastcall operator>(const value_type) const noexcept(true) override;
170  constexpr bool __fastcall operator>(const atomic_ctr_gen &) const noexcept(true) FORCE_INLINE;
171 // TODO constexpr bool __fastcall operator>(sp_counter_itf_type const &) const noexcept(true) FORCE_INLINE;
172  constexpr bool __fastcall operator>(base_t const &) const noexcept(true) FORCE_INLINE;
173  constexpr bool __fastcall operator<=(const value_type) const noexcept(true) FORCE_INLINE;
174  constexpr bool __fastcall operator<=(const atomic_ctr_gen &) const noexcept(true) FORCE_INLINE;
175  constexpr bool __fastcall operator>=(const value_type) const noexcept(true) override;
176  constexpr bool __fastcall operator>=(const atomic_ctr_gen &) const noexcept(true) FORCE_INLINE;
177 
178  /**
179  \return Atomically increment and return that incremented value.
180  */
181  value_type __fastcall operator++() noexcept(true) FORCE_INLINE;
182  [[nodiscard]] value_type __fastcall operator++(int) noexcept(true) FORCE_INLINE;
183  /**
184  \return Atomically decrement and return that incremented value.
185  */
186  value_type __fastcall operator--() noexcept(true) FORCE_INLINE;
187  value_type __fastcall operator--(int) noexcept(true) FORCE_INLINE;
188 
189  value_type __fastcall operator+=(const value_type) noexcept(true) FORCE_INLINE;
190  value_type __fastcall operator+=(const atomic_ctr_gen &) noexcept(true) FORCE_INLINE;
191  value_type __fastcall operator-=(const value_type) noexcept(true) FORCE_INLINE;
192  value_type __fastcall operator-=(const atomic_ctr_gen &) noexcept(true) FORCE_INLINE;
193 
194  template<class V1=value_type>
195  typename std::enable_if<std::is_pointer<V1>::value, V1>::type FORCE_INLINE
196  operator->() const noexcept(true) {
197  return count;
198  }
199 
200  template<class BinOp> value_type __fastcall apply(typename BinOp::second_argument_type const &a, BinOp const &op) noexcept(noexcept(op.operator()(std::declval<value_type>(), std::declval<typename BinOp::second_argument_type>()))) FORCE_INLINE;
201  template<class V1> value_type __fastcall apply(V1 const &a, std::plus<V1> const &) noexcept(true) FORCE_INLINE;
202  template<class V1> value_type __fastcall apply(V1 const &a, std::minus<V1> const &) noexcept(true) FORCE_INLINE;
203  bool compare_exchange_strong(value_type expected, value_type desired) noexcept(true) FORCE_INLINE;
204  template<class V1, class V2=V1>
205  typename std::enable_if<std::is_pointer<V2>::value, bool>::type compare_exchange_strong(value_type expected, V1 desired) noexcept(true) FORCE_INLINE;
206  template<class Op>
207  atomic_ctr_gen assign(Op &&op) noexcept(true) FORCE_INLINE;
208 
209  protected:
210  template<class V1, class LkT1> friend class atomic_ctr_gen;
211 
213  mutable atomic_t locker;
214  };
215 
216  /// A specialisation for sequential operation to optimise performance.
217  template<
218  class V, ///< The type of the value for the counter. Note that this must be a type that is atomically manipulated on the target architecture, such as int or long. i.e. no word-tearing.
220  >
221  class atomic_ctr_gen<V, api_lock_traits<API, sequential_mode> > : public virtual sp_counter_itf_type<V> {
222  public:
223  typedef api_lock_traits<API, sequential_mode> lock_traits;
225  typedef V value_type;
226  /**
227  To assist in allowing compile-time computation of the algorithmic order of the threading model.
228  */
230 
231  public:
232  constexpr atomic_ctr_gen() noexcept(true) : count() {
233  }
234  explicit constexpr atomic_ctr_gen(const value_type val) noexcept(true)
235  : count(val) {
236  }
237  constexpr atomic_ctr_gen(const atomic_ctr_gen &lkctr) noexcept(true)
238  : count(lkctr.count) {
239  }
240  template<class V1>
241  constexpr atomic_ctr_gen(const atomic_ctr_gen<V1, api_lock_traits<API, sequential_mode>> &lkctr) noexcept(true)
242  : count(lkctr.count) {
243  }
244  ~atomic_ctr_gen() noexcept(true) {}
245 
246  void FORCE_INLINE swap(atomic_ctr_gen &rhs) noexcept(true) {
247  std::swap(count, rhs.count);
248  }
249  template<class V1, class V2=V1>
250  typename std::enable_if<std::is_pointer<V2>::value, void>::type FORCE_INLINE
251  swap(atomic_ctr_gen<V1, api_lock_traits<API, sequential_mode>> &rhs) noexcept(true) {
252  std::swap(count, rhs.count);
253  }
254 
255  template<class V1, class V2=V1>
256  typename std::enable_if<std::is_pointer<V2>::value, void>::type __fastcall operator=(const atomic_ctr_gen<V1, api_lock_traits<API, sequential_mode>> &v) noexcept(true) {
257  count=dynamic_cast<value_type>(v.count);
258  }
259  void FORCE_INLINE operator=(const atomic_ctr_gen &lkctr) noexcept(true) {
260  count=lkctr.count;
261  }
262  void __fastcall FORCE_INLINE operator=(const value_type &v) noexcept(true) {
263  count=v;
264  }
265 
266  constexpr bool FORCE_INLINE sp_noop_ctr() const noexcept(true) override {
267  return true;
268  }
269 
270  constexpr value_type __fastcall FORCE_INLINE get() const noexcept(true) {
271  return count;
272  }
273 
274  constexpr bool __fastcall FORCE_INLINE operator==(const value_type val) const noexcept(true) {
275  return count==val;
276  }
277  constexpr bool __fastcall FORCE_INLINE operator==(const atomic_ctr_gen &val) const noexcept(true) {
278  return count==val.count;
279  }
280  constexpr bool __fastcall FORCE_INLINE operator!=(const value_type val) const noexcept(true) {
281  return !operator==(val);
282  }
283  constexpr bool __fastcall FORCE_INLINE operator!=(const atomic_ctr_gen &val) const noexcept(true) {
284  return !operator==(val);
285  }
286  explicit constexpr FORCE_INLINE operator bool() const noexcept(true) {
287  return count!=value_type();
288  }
289  value_type __fastcall FORCE_INLINE operator++() noexcept(true) {
290  return ++count;
291  }
292  [[nodiscard]] value_type __fastcall FORCE_INLINE operator++(int) noexcept(true) {
293  const value_type ret(count);
294  ++count;
295  return ret;
296  }
297  value_type __fastcall FORCE_INLINE operator--() noexcept(true) {
298  return --count;
299  }
300  value_type __fastcall FORCE_INLINE operator--(int) noexcept(true) {
301  const value_type ret(count);
302  --count;
303  return ret;
304  }
305 
306  constexpr bool __fastcall FORCE_INLINE operator<(const value_type val) const noexcept(true) override {
307  return count<val;
308  }
309  constexpr bool __fastcall FORCE_INLINE operator<(const atomic_ctr_gen &val) const noexcept(true) {
310  return count<val.count;
311  }
312 /* constexpr bool __fastcall FORCE_INLINEoperator<(sp_counter_itf_type const &val) const noexcept(true) {
313  assert(dynamic_cast<atomic_ctr_gen const *>(&val));
314  return *this<dynamic_cast<atomic_ctr_gen const &>(val);
315  }
316 */constexprbool__fastcallFORCE_INLINE operator>(const value_type val) const noexcept(true) override {
317  return count>val;
318  }
319  constexpr bool __fastcall FORCE_INLINE operator>(const atomic_ctr_gen &val) const noexcept(true) {
320  return count>val.count;
321  }
322 /* constexpr bool __fastcall FORCE_INLINE operator>(sp_counter_itf_type const &) const noexcept(true) {
323  assert(dynamic_cast<atomic_ctr_gen const *>(&val));
324  return *this>dynamic_cast<atomic_ctr_gen const &>(val);
325  }
326 */constexprbool__fastcallFORCE_INLINE operator<=(const value_type val) const noexcept(true) {
327  return count<=val;
328  }
329  constexpr bool __fastcall FORCE_INLINE operator<=(const atomic_ctr_gen &val) const noexcept(true) {
330  return count<=val.count;
331  }
332  constexpr bool __fastcall FORCE_INLINE operator>=(const value_type val) const noexcept(true) override {
333  return count>=val;
334  }
335  constexpr bool __fastcall FORCE_INLINE operator>=(const atomic_ctr_gen &val) const noexcept(true) {
336  return count>=val.count;
337  }
338 
339  value_type __fastcall FORCE_INLINE operator+=(const value_type v) noexcept(true) {
340  return count+=v;
341  }
342  value_type __fastcall FORCE_INLINE operator+=(const atomic_ctr_gen &v) noexcept(true) {
343  return count+=v.count;
344  }
345  value_type __fastcall FORCE_INLINE operator-=(const value_type v) noexcept(true) {
346  return count-=v;
347  }
348  value_type __fastcall FORCE_INLINE operator-=(const atomic_ctr_gen &v) noexcept(true) {
349  return count-=v.count;
350  }
351 
352  template<class V1=value_type>
353  typename std::enable_if<std::is_pointer<V1>::value, V1>::type FORCE_INLINE
354  operator->() const noexcept(true) {
355  return count;
356  }
357 
358  template<class BinOp> value_type __fastcall FORCE_INLINE
359  apply(typename BinOp::second_argument_type const &a, BinOp const &op) noexcept(noexcept(op.operator()(std::declval<value_type>(), std::declval<typename BinOp::second_argument_type>()))) {
360  return count=op.operator()(count, a);
361  }
362  template<class V1> value_type __fastcall FORCE_INLINE
363  apply(V1 const &a, std::plus<V1> const &) noexcept(true) {
364  return *this+=a;
365  }
366  template<class V1> value_type __fastcall FORCE_INLINE
367  apply(V1 const &a, std::minus<V1> const &) noexcept(true) {
368  return *this-=a;
369  }
371  count=desired;
372  return true;
373  }
374  template<class V1, class V2=V1>
375  typename std::enable_if<std::is_pointer<V2>::value, bool>::type FORCE_INLINE
376  compare_exchange_strong(value_type, V1 desired) noexcept(true) {
377  count=desired;
378  return true;
379  }
380  template<class Op>
382  assign(Op &&op) noexcept(true) {
383  atomic_ctr_gen expected(*this);
384  compare_exchange_strong(expected.load(), op(expected).load());
385  return expected;
386  }
387 
388  protected:
390  };
391 
392  /// An atomic counter class for integer types, similar to the atomic integer types in C++11 ch 29.
393  /**
394  Note that this class is a valid value-type.
395  Also note that this class reduces to a simple V-type, if it is single threaded, so costs nothing.
396  */
397  template<
398  class V, ///< The type of the value for the counter. Note that this must be a type that is atomically manipulated on the target architecture, such as int or long. i.e. no word-tearing.
399  class LkT
400  >
401  class atomic_ctr_opt : public virtual sp_counter_itf_type<V> {
402  public:
404  typedef LkT lock_traits;
405  typedef typename base_t::value_type value_type;
406  typedef std::atomic<value_type> atomic_t;
407  /**
408  To assist in allowing compile-time computation of the algorithmic order of the threading model.
409  \todo Consider using to define this, equals 0 (never lockfree) or 2 (always lockfree):
410 ATOMIC_BOOL_LOCK_FREE
411 ATOMIC_CHAR_LOCK_FREE
412 ATOMIC_CHAR16_T_LOCK_FREE
413 ATOMIC_CHAR32_T_LOCK_FREE
414 ATOMIC_WCHAR_T_LOCK_FREE
415 ATOMIC_SHORT_LOCK_FREE
416 ATOMIC_INT_LOCK_FREE
417 ATOMIC_LONG_LOCK_FREE
418 ATOMIC_LLONG_LOCK_FREE
419 ATOMIC_POINTER_LOCK_FREE
420  */
422 
423  public:
424  constexpr __stdcall atomic_ctr_opt() noexcept(true) FORCE_INLINE;
425  explicit constexpr __stdcall atomic_ctr_opt(const value_type) noexcept(true) FORCE_INLINE;
426  constexpr atomic_ctr_opt(const atomic_ctr_opt &) noexcept(true) FORCE_INLINE;
427  template<class V1>
428  constexpr atomic_ctr_opt(const atomic_ctr_opt<V1, LkT> &) noexcept(true) FORCE_INLINE;
429  template<class V1>
430  atomic_ctr_opt(atomic_ctr_opt<V1, LkT> &&) noexcept(true) FORCE_INLINE;
431  ~atomic_ctr_opt() noexcept(true) FORCE_INLINE;
432  template<class V1, class V2=V1>
433  typename std::enable_if<std::is_pointer<V2>::value, void>::type __fastcall operator=(const atomic_ctr_opt<V1, LkT> &v) noexcept(true) FORCE_INLINE;
434  void __fastcall operator=(const atomic_ctr_opt &) noexcept(true) FORCE_INLINE;
435  void __fastcall operator=(const value_type &) noexcept(true) FORCE_INLINE;
436 
437  /**
438  \note This is not lockfree! So it is not thread-safe.
439  */
440  void swap(atomic_ctr_opt &) noexcept(true) FORCE_INLINE;
441  template<class V1, class V2=V1>
442  typename std::enable_if<std::is_pointer<V2>::value, void>::type swap(atomic_ctr_opt<V1, LkT> &rhs) noexcept(true) FORCE_INLINE;
443 
444  constexpr bool sp_noop_ctr() const noexcept(true) override __attribute__((const)) {
445  return false;
446  }
447 
448  constexpr value_type __fastcall get() const noexcept(true) FORCE_INLINE;
449 
450  explicit constexpr operator bool() const noexcept(true) FORCE_INLINE;
451 
452  constexpr bool __fastcall operator==(const value_type) const noexcept(true) FORCE_INLINE;
453  constexpr bool __fastcall operator==(const atomic_ctr_opt &) const noexcept(true) FORCE_INLINE;
454  constexpr bool __fastcall operator!=(const value_type) const noexcept(true) FORCE_INLINE;
455  constexpr bool __fastcall operator!=(const atomic_ctr_opt &) const noexcept(true) FORCE_INLINE;
456  constexpr bool __fastcall operator<(const value_type) const noexcept(true) FORCE_INLINE override;
457  constexpr bool __fastcall operator<(const atomic_ctr_opt &) const noexcept(true) FORCE_INLINE;
458 // TODO constexpr bool __fastcall operator<(sp_counter_itf_type const &) const noexcept(true) FORCE_INLINE;
459  constexpr bool __fastcall operator<(base_t const &) const noexcept(true) FORCE_INLINE;
460  constexpr bool __fastcall operator>(const value_type) const noexcept(true) FORCE_INLINE override;
461  constexpr bool __fastcall operator>(const atomic_ctr_opt &) const noexcept(true) FORCE_INLINE;
462 // TODO constexpr bool __fastcall operator>(sp_counter_itf_type const &) const noexcept(true) FORCE_INLINE;
463  constexpr bool __fastcall operator>(base_t const &) const noexcept(true) FORCE_INLINE;
464  constexpr bool __fastcall operator<=(const value_type) const noexcept(true) FORCE_INLINE;
465  constexpr bool __fastcall operator<=(const atomic_ctr_opt &) const noexcept(true) FORCE_INLINE;
466  constexpr bool __fastcall operator>=(const value_type) const noexcept(true) FORCE_INLINE override;
467  constexpr bool __fastcall operator>=(const atomic_ctr_opt &) const noexcept(true) FORCE_INLINE;
468 
469  /**
470  \return Atomically increment and return that incremented value.
471  */
472  value_type __fastcall operator++() noexcept(true) FORCE_INLINE;
473  [[nodiscard]] value_type __fastcall operator++(int) noexcept(true) FORCE_INLINE;
474  /**
475  \return Atomically decrement and return that incremented value.
476  */
477  value_type __fastcall operator--() noexcept(true) FORCE_INLINE;
478  value_type __fastcall operator--(int) noexcept(true) FORCE_INLINE;
479 
480  value_type __fastcall operator+=(const value_type) noexcept(true) FORCE_INLINE;
481  value_type __fastcall operator+=(const atomic_ctr_opt &) noexcept(true) FORCE_INLINE;
482  value_type __fastcall operator-=(const value_type) noexcept(true) FORCE_INLINE;
483  value_type __fastcall operator-=(const atomic_ctr_opt &) noexcept(true) FORCE_INLINE;
484 
485  template<class V1=value_type>
486  typename std::enable_if<std::is_pointer<V1>::value, V1>::type FORCE_INLINE
487  operator->() const noexcept(true) {
488  return count.load();
489  }
490 
491  template<class BinOp> value_type __fastcall apply(typename BinOp::second_argument_type const &a, BinOp const &op) noexcept(noexcept(op.operator()(std::declval<value_type>(), std::declval<typename BinOp::second_argument_type>()))) FORCE_INLINE;
492  template<class V1> value_type __fastcall apply(V1 const &a, std::plus<V1> const &) noexcept(true) FORCE_INLINE;
493  template<class V1> value_type __fastcall apply(V1 const &a, std::minus<V1> const &) noexcept(true) FORCE_INLINE;
494  bool compare_exchange_strong(value_type expected, value_type desired) noexcept(true) FORCE_INLINE;
495  template<class V1, class V2=V1>
496  typename std::enable_if<std::is_pointer<V2>::value, bool>::type compare_exchange_strong(value_type expected, V1 desired) noexcept(true) FORCE_INLINE;
497  template<class Op>
498  atomic_ctr_opt assign(Op &&op) noexcept(true) FORCE_INLINE;
499 
500  protected:
501  template<class V1, class LkT1> friend class atomic_ctr_opt;
502 
504  };
505 
506  /// A general-purpose, atomic-wrapper class, similar to the atomic types in C++11 ch 29, with some important differences.
507  /**
508  Unlike std::atomic:
509  #Works for any type: integer-types & pointers (to anything) are atomic, others use a mutex, so aren't: guaranteed.
510  #Has a uniform interface.
511  #Also note that this class reduces to a simple V-type, if it is single threaded, so costs nothing.
512  #Note that this class is a valid value-type.
513 
514  \see std::stomic
515  */
516  template<
517  class V, ///< The type of the value for the counter. Note that this must be a type that is atomically manipulated on the target architecture, such as int or long. i.e. no word-tearing.
518  class LkT
519  >
520  using atomic_ctr=typename std::conditional<
521  std::is_integral<V>::value,
522  atomic_ctr_opt<V, LkT>,
523  typename std::conditional<
524  std::is_pointer<V>::value,
525  atomic_ctr_opt<V, LkT>,
526  atomic_ctr_gen<V, LkT>
527  >::type
528  >::type;
529 
530  /**
531  \todo Implement using the advice given in "Standard C++ IOStreams and Locales" by A.Langer & K.Kreft, page 170.
532  */
533  template<class V, class LkT> inline
535  operator<<(tostream &os, atomic_ctr<V, LkT> const &a) {
536  os<<a.get();
537  return os;
538  }
539 
540  /// An atomic counter class that actually does nothing, doesn't count at all.
541  /**
542  Note that this class is a valid value-type.
543  */
544  template<
545  class V, ///< The type of the value for the counter.
546  class LkT
547  >
548  class noop_atomic_ctr_base : public virtual sp_counter_itf_type<V> {
549  public:
551  typedef LkT lock_traits;
553  typedef typename base_t::value_type value_type;
554 
555  /**
556  To assist in allowing compile-time computation of the algorithmic order of the threading model.
557  */
559 
560  constexpr noop_atomic_ctr_base() noexcept(true)=default;
561 
562  value_type sp_count() const noexcept(true) override __attribute__((const)) {
563  return value_type(1);
564  }
565  constexpr value_type get() const noexcept(true) __attribute__((const)) {
566  return value_type(1);
567  }
568  bool sp_noop_ctr() const noexcept(true) override __attribute__((const)) {
569  return true;
570  }
571 
572  bool __fastcall operator<(const value_type) const noexcept(true) override __attribute__((const)) {
573  return false;
574  }
575  bool __fastcall operator>(const value_type) const noexcept(true) override __attribute__((const)) {
576  return true;
577  }
578  bool __fastcall operator>=(const value_type) const noexcept(true) override __attribute__((const)) {
579  return true;
580  }
581 
582  value_type __fastcall FORCE_INLINE operator++() noexcept(true) {
583  return std::numeric_limits<value_type>::max();
584  }
585  value_type __fastcall FORCE_INLINE operator--() noexcept(true) {
586  return std::numeric_limits<value_type>::min();
587  }
588  };
589 
590 } } }
591 
593 
594 #ifdef __GCC__
595 # pragma GCC diagnostic pop
596 #endif
597 
598 #endif