libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
atomic_counter_impl.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2007 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE { namespace ppd {
20 
21 template<class V, class LkT> inline constexpr
22 atomic_ctr_gen<V, LkT>::atomic_ctr_gen() noexcept(noexcept(value_type()) && noexcept(atomic_t()))
23 : count(), locker() {
24 }
25 
26 template<class V, class LkT> inline constexpr
27 atomic_ctr_gen<V, LkT>::atomic_ctr_gen(const value_type v) noexcept(noexcept(value_type(std::declval<value_type>())) && noexcept(atomic_t()))
28 : count(v), locker() {
29 }
30 
31 template<class V, class LkT> inline constexpr
32 atomic_ctr_gen<V, LkT>::atomic_ctr_gen(const atomic_ctr_gen &a) noexcept(false)
33 : count(a.count), locker() {
34 }
35 
36 template<class V, class LkT>
37 template<class V1>
38 inline constexpr
39 atomic_ctr_gen<V, LkT>::atomic_ctr_gen(const atomic_ctr_gen<V1, LkT> &a) noexcept(false)
40 : count(dynamic_cast<value_type>(a.count)), locker() {
41  static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
42 }
43 
44 template<class V, class LkT>
45 template<class V1>
46 inline
47 atomic_ctr_gen<V, LkT>::atomic_ctr_gen(atomic_ctr_gen<V1, LkT> &&a) noexcept(true)
48 : count(), locker() {
49  static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
50  swap(a);
51 }
52 
53 template<class V, class LkT> inline
54 atomic_ctr_gen<V, LkT>::~atomic_ctr_gen() noexcept(true) {
55 }
56 
57 template<class V, class LkT> inline void
58 atomic_ctr_gen<V, LkT>::swap(atomic_ctr_gen &a) noexcept(true) {
59  const typename atomic_t::write_lock_type lock_this(locker, atomic_t::lock_traits::infinite_timeout());
60  const typename atomic_t::write_lock_type lock_that(a.locker, atomic_t::lock_traits::infinite_timeout());
61  std::swap(count, a.count);
62 }
63 
64 template<class V, class LkT>
65 template<class V1, class V2>
66 inline typename std::enable_if<std::is_pointer<V2>::value, void>::type
67 atomic_ctr_gen<V, LkT>::swap(atomic_ctr_gen<V1, LkT> &a) noexcept(true) {
68 // This is too brutal: it doesn't detect common bases.... static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
69  const typename atomic_t::write_lock_type lock_this(locker, atomic_t::lock_traits::infinite_timeout());
70  const typename atomic_t::write_lock_type lock_that(a.locker, atomic_t::lock_traits::infinite_timeout());
71  std::swap(count, a.count);
72 }
73 
74 template<class V, class LkT> inline void
75 atomic_ctr_gen<V, LkT>::operator=(const atomic_ctr_gen &a) noexcept(true) {
76  const typename atomic_t::write_lock_type lock_this(locker, atomic_t::lock_traits::infinite_timeout());
77  const typename atomic_t::read_lock_type lock_that(a.locker, atomic_t::lock_traits::infinite_timeout());
78  count=a.count;
79 }
80 
81 template<class V, class LkT>
82 template<class V1, class V2>
83 inline typename std::enable_if<std::is_pointer<V2>::value, void>::type
84 atomic_ctr_gen<V, LkT>::operator=(const atomic_ctr_gen<V1, LkT> &a) noexcept(true) {
85  static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
86  const typename atomic_t::write_lock_type lock_this(locker, atomic_t::lock_traits::infinite_timeout());
87  const typename atomic_t::read_lock_type lock_that(a.locker, atomic_t::lock_traits::infinite_timeout());
88  count=dynamic_cast<value_type>(a.get());
89 }
90 
91 template<class V, class LkT> inline void
92 atomic_ctr_gen<V, LkT>::operator=(const value_type &v) noexcept(true) {
93  const typename atomic_t::write_lock_type lock_this(locker, atomic_t::lock_traits::infinite_timeout());
94  count=v;
95 }
96 
97 template<class V, class LkT> inline constexpr typename atomic_ctr_gen<V, LkT>::value_type const &
98 atomic_ctr_gen<V, LkT>::get() const noexcept(true) {
99  return count;
100 }
101 
102 template<class V, class LkT> inline constexpr bool
103 atomic_ctr_gen<V, LkT>::operator==(const value_type v) const noexcept(true) {
104  return count==v;
105 }
106 
107 template<class V, class LkT> inline constexpr bool
108 atomic_ctr_gen<V, LkT>::operator==(const atomic_ctr_gen &a) const noexcept(true) {
109  return count==a.count;
110 }
111 
112 template<class V, class LkT> inline constexpr bool
113 atomic_ctr_gen<V, LkT>::operator!=(const value_type v) const noexcept(true) {
114  return !operator==(v);
115 }
116 
117 template<class V, class LkT> inline constexpr bool
118 atomic_ctr_gen<V, LkT>::operator!=(const atomic_ctr_gen &a) const noexcept(true) {
119  return !operator==(a);
120 }
121 
122 template<class V, class LkT> inline constexpr bool
123 atomic_ctr_gen<V, LkT>::operator!() const noexcept(true) {
124  return operator==(0);
125 }
126 
127 template<class V, class LkT> inline constexpr bool
128 atomic_ctr_gen<V, LkT>::operator<(const value_type v) const noexcept(true) {
129  return count<v;
130 }
131 
132 template<class V, class LkT> inline constexpr bool
133 atomic_ctr_gen<V, LkT>::operator<(const atomic_ctr_gen &a) const noexcept(true) {
134  return count<a.count;
135 }
136 
137 template<class V, class LkT> inline constexpr bool
138 atomic_ctr_gen<V, LkT>::operator<(base_t const &a) const noexcept(true) {
139  return *this<dynamic_cast<atomic_ctr_gen const &>(a);
140 }
141 
142 template<class V, class LkT> inline constexpr bool
143 atomic_ctr_gen<V, LkT>::operator>(const value_type v) const noexcept(true) {
144  return count>v;
145 }
146 
147 template<class V, class LkT> inline constexpr bool
148 atomic_ctr_gen<V, LkT>::operator>(const atomic_ctr_gen &a) const noexcept(true) {
149  return count>a.count;
150 }
151 
152 template<class V, class LkT> inline constexpr bool
153 atomic_ctr_gen<V, LkT>::operator>(const base_t &a) const noexcept(true) {
154  return *this>dynamic_cast<atomic_ctr_gen const &>(a);
155 }
156 
157 template<class V, class LkT> inline constexpr bool
158 atomic_ctr_gen<V, LkT>::operator<=(const value_type v) const noexcept(true) {
159  return count<=v;
160 }
161 
162 template<class V, class LkT> inline constexpr bool
163 atomic_ctr_gen<V, LkT>::operator<=(const atomic_ctr_gen &a) const noexcept(true) {
164  return count<=a.count;
165 }
166 
167 template<class V, class LkT> inline constexpr bool
168 atomic_ctr_gen<V, LkT>::operator>=(const atomic_ctr_gen &a) const noexcept(true) {
169  return count>=a.count;
170 }
171 
172 template<class V, class LkT> inline constexpr bool
173 atomic_ctr_gen<V, LkT>::operator>=(const value_type v) const noexcept(true) {
174  return count>=v;
175 }
176 
177 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
178 atomic_ctr_gen<V, LkT>::operator++() noexcept(true) {
179  const typename atomic_t::write_lock_type lock(locker, atomic_t::lock_traits::infinite_timeout());
180  const value_type ret=++count;
181  return ret;
182 }
183 
184 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
185 atomic_ctr_gen<V, LkT>::operator++(int) noexcept(true) {
186  const value_type orig(count);
187  ++*this;
188  return orig;
189 }
190 
191 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
192 atomic_ctr_gen<V, LkT>::operator--() noexcept(true) {
193  const typename atomic_t::write_lock_type lock(locker, atomic_t::lock_traits::infinite_timeout());
194  const value_type ret=--count;
195  return ret;
196 }
197 
198 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
199 atomic_ctr_gen<V, LkT>::operator--(int) noexcept(true) {
200  const value_type orig(count);
201  --*this;
202  return orig;
203 }
204 
205 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
206 atomic_ctr_gen<V, LkT>::operator+=(const value_type v) noexcept(true) {
207  const typename atomic_t::write_lock_type lock(locker, atomic_t::lock_traits::infinite_timeout());
208  count+=v;
209  return count;
210 }
211 
212 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
213 atomic_ctr_gen<V, LkT>::operator+=(const atomic_ctr_gen &a) noexcept(true) {
214  const typename atomic_t::write_lock_type lock_this(locker, atomic_t::lock_traits::infinite_timeout());
215  const typename atomic_t::read_lock_type lock_that(a.locker, atomic_t::lock_traits::infinite_timeout());
216  count+=a.count;
217  return count;
218 }
219 
220 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
221 atomic_ctr_gen<V, LkT>::operator-=(const value_type v) noexcept(true) {
222  const typename atomic_t::write_lock_type lock(locker,atomic_t::lock_traits::infinite_timeout());
223  count-=v;
224  return count;
225 }
226 
227 template<class V, class LkT> inline typename atomic_ctr_gen<V, LkT>::value_type
228 atomic_ctr_gen<V, LkT>::operator-=(const atomic_ctr_gen &a) noexcept(true) {
229  const typename atomic_t::write_lock_type lock_this(locker, atomic_t::lock_traits::infinite_timeout());
230  const typename atomic_t::read_lock_type lock_that(a.locker, atomic_t::lock_traits::infinite_timeout());
231  count-=a.count;
232  return count;
233 }
234 
235 template<class V, class LkT>
236 template<class BinOp>
237 inline
238 typename atomic_ctr_gen<V, LkT>::value_type
239 atomic_ctr_gen<V, LkT>::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>()))) {
240  const typename atomic_t::write_lock_type lock(locker, atomic_t::lock_traits::infinite_timeout());
241  count=op.operator()(count,a);
242  return count;
243 }
244 
245 template<class V, class LkT>
246 template<class V1>
247 inline
248 typename atomic_ctr_gen<V, LkT>::value_type
249 atomic_ctr_gen<V, LkT>::apply(V1 const &a, std::plus<V1> const &) noexcept(true) {
250  return *this+=a;
251 }
252 
253 template<class V, class LkT>
254 template<class V1>
255 inline
256 typename atomic_ctr_gen<V, LkT>::value_type
257 atomic_ctr_gen<V, LkT>::apply(V1 const &a, std::minus<V1> const &) noexcept(true) {
258  return *this-=a;
259 }
260 
261 template<class V, class LkT>
262 inline bool
263 atomic_ctr_gen<V, LkT>::compare_exchange_strong(value_type expected, value_type desired) noexcept(true) {
264  const typename atomic_t::write_lock_type lock(locker, atomic_t::lock_traits::infinite_timeout());
265  if (count==expected) {
266  count=desired;
267  return true;
268  } else {
269  return false;
270  }
271 }
272 
273 template<class V, class LkT>
274 template<class V1, class V2>
275 inline typename std::enable_if<std::is_pointer<V2>::value, bool>::type
276 atomic_ctr_gen<V, LkT>::compare_exchange_strong(value_type expected, V1 desired) noexcept(true) {
277  static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
278  const typename atomic_t::write_lock_type lock(locker, atomic_t::lock_traits::infinite_timeout());
279  if (count==expected) {
280  count=desired;
281  return true;
282  } else {
283  return false;
284  }
285 }
286 
287 template<class V, class LkT>
288 template<class Op>
289 inline atomic_ctr_gen<V, LkT>
290 atomic_ctr_gen<V, LkT>::assign(Op &&op) noexcept(true) {
291  atomic_ctr_gen expected;
292  do {
293  expected=*this;
294  } while (!compare_exchange_strong(expected, op(expected)));
295  return expected;
296 }
297 
298 template<class V, class LkT> inline constexpr
299 atomic_ctr_opt<V, LkT>::atomic_ctr_opt() noexcept(true)
300 : count() {
301 }
302 
303 template<class V, class LkT> inline constexpr
304 atomic_ctr_opt<V, LkT>::atomic_ctr_opt(const value_type v) noexcept(true)
305 : count(v) {
306 }
307 
308 template<class V, class LkT> constexpr inline
309 atomic_ctr_opt<V, LkT>::atomic_ctr_opt(const atomic_ctr_opt &a) noexcept(true)
310 : count(a.get()) {
311 }
312 
313 template<class V, class LkT>
314 template<class V1>
315 constexpr inline
316 atomic_ctr_opt<V, LkT>::atomic_ctr_opt(const atomic_ctr_opt<V1, LkT> &a) noexcept(true)
317 : count(dynamic_cast<value_type>(a.get())) {
318 // This is too brutal: it doesn't detect common bases.... static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
319 }
320 
321 template<class V, class LkT>
322 template<class V1>
323 inline
324 atomic_ctr_opt<V, LkT>::atomic_ctr_opt(atomic_ctr_opt<V1, LkT> &&a) noexcept(true)
325 : count() {
326 // This is too brutal: it doesn't detect common bases.... static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
327  swap(a);
328 }
329 
330 template<class V, class LkT> inline
331 atomic_ctr_opt<V, LkT>::~atomic_ctr_opt() noexcept(true) {
332  assert(count.is_lock_free());
333 }
334 
335 template<class V, class LkT> inline void
336 atomic_ctr_opt<V, LkT>::swap(atomic_ctr_opt &a) noexcept(true) {
337  const value_type lhs_orig=count.exchange(a.get());
338  a.count.store(lhs_orig);
339 }
340 
341 template<class V, class LkT>
342 template<class V1, class V2>
343 inline typename std::enable_if<std::is_pointer<V2>::value, void>::type
344 atomic_ctr_opt<V, LkT>::swap(atomic_ctr_opt<V1, LkT> &a) noexcept(true) {
345 // This is too brutal: it doesn't detect common bases.... static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
346  value_type const tmp=dynamic_cast<value_type>(a.get());
347  a.count.exchange(dynamic_cast<typename atomic_ctr_opt<V1, LkT>::value_type>(count.load()));
348  count.exchange(tmp);
349 }
350 
351 template<class V, class LkT>
352 template<class V1, class V2>
353 inline typename std::enable_if<std::is_pointer<V2>::value, void>::type
354 atomic_ctr_opt<V, LkT>::operator=(const atomic_ctr_opt<V1, LkT> &a) noexcept(true) {
355 // This is too brutal: it doesn't detect common bases.... static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
356  assert(count.is_lock_free() && a.count.is_lock_free());
357  count=dynamic_cast<value_type>(a.get());
358 }
359 
360 template<class V, class LkT> inline void
361 atomic_ctr_opt<V, LkT>::operator=(const atomic_ctr_opt &a) noexcept(true) {
362  assert(count.is_lock_free() && a.count.is_lock_free());
363  count=a.get();
364 }
365 
366 template<class V, class LkT> inline void
367 atomic_ctr_opt<V, LkT>::operator=(const value_type &v) noexcept(true) {
368  assert(count.is_lock_free());
369  count=v;
370 }
371 
372 template<class V, class LkT> constexpr inline typename atomic_ctr_opt<V, LkT>::value_type
373 atomic_ctr_opt<V, LkT>::get() const noexcept(true) {
374  assert(count.is_lock_free());
375  return count.load();
376 }
377 
378 template<class V, class LkT> constexpr inline bool
379 atomic_ctr_opt<V, LkT>::operator==(const value_type v) const noexcept(true) {
380  assert(count.is_lock_free());
381  return count==v;
382 }
383 
384 template<class V, class LkT> constexpr inline bool
385 atomic_ctr_opt<V, LkT>::operator==(const atomic_ctr_opt &a) const noexcept(true) {
386  assert(count.is_lock_free() && a.count.is_lock_free());
387  return count==a.count;
388 }
389 
390 template<class V, class LkT> constexpr inline bool
391 atomic_ctr_opt<V, LkT>::operator!=(const value_type v) const noexcept(true) {
392  assert(count.is_lock_free());
393  return !operator==(v);
394 }
395 
396 template<class V, class LkT> constexpr inline bool
397 atomic_ctr_opt<V, LkT>::operator!=(const atomic_ctr_opt &a) const noexcept(true) {
398  assert(count.is_lock_free() && a.count.is_lock_free());
399  return !operator==(a);
400 }
401 
402 template<class V, class LkT> constexpr inline
403 atomic_ctr_opt<V, LkT>::operator bool() const noexcept(true) {
404  assert(count.is_lock_free());
405  return count!=value_type();
406 }
407 
408 template<class V, class LkT> constexpr inline bool
409 atomic_ctr_opt<V, LkT>::operator<(const value_type v) const noexcept(true) {
410  assert(count.is_lock_free());
411  return count<v;
412 }
413 
414 template<class V, class LkT> constexpr inline bool
415 atomic_ctr_opt<V, LkT>::operator<(const atomic_ctr_opt &a) const noexcept(true) {
416  assert(count.is_lock_free() && a.count.is_lock_free());
417  return count<a.count;
418 }
419 
420 template<class V, class LkT> constexpr inline bool
421 atomic_ctr_opt<V, LkT>::operator<(const base_t &a) const noexcept(true) {
422  assert(count.is_lock_free());
423  return *this<dynamic_cast<atomic_ctr_opt const &>(a);
424 }
425 
426 template<class V, class LkT> constexpr inline bool
427 atomic_ctr_opt<V, LkT>::operator>(const value_type v) const noexcept(true) {
428  assert(count.is_lock_free());
429  return count>v;
430 }
431 
432 template<class V, class LkT> constexpr inline bool
433 atomic_ctr_opt<V, LkT>::operator>(const atomic_ctr_opt &a) const noexcept(true) {
434  assert(count.is_lock_free() && a.count.is_lock_free());
435  return count>a.count;
436 }
437 
438 template<class V, class LkT> constexpr inline bool
439 atomic_ctr_opt<V, LkT>::operator>(const base_t &a) const noexcept(true) {
440  assert(count.is_lock_free());
441  return *this>dynamic_cast<atomic_ctr_opt const &>(a);
442 }
443 
444 template<class V, class LkT> constexpr inline bool
445 atomic_ctr_opt<V, LkT>::operator<=(const value_type v) const noexcept(true) {
446  assert(count.is_lock_free());
447  return count<=v;
448 }
449 
450 template<class V, class LkT> constexpr inline bool
451 atomic_ctr_opt<V, LkT>::operator<=(const atomic_ctr_opt &a) const noexcept(true) {
452  assert(count.is_lock_free() && a.count.is_lock_free());
453  return count<=a.count;
454 }
455 
456 template<class V, class LkT> constexpr inline bool
457 atomic_ctr_opt<V, LkT>::operator>=(const atomic_ctr_opt &a) const noexcept(true) {
458  assert(count.is_lock_free() && a.count.is_lock_free());
459  return count>=a.count;
460 }
461 
462 template<class V, class LkT> constexpr inline bool
463 atomic_ctr_opt<V, LkT>::operator>=(const value_type v) const noexcept(true) {
464  assert(count.is_lock_free());
465  return count>=v;
466 }
467 
468 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
469 atomic_ctr_opt<V, LkT>::operator++() noexcept(true) {
470  assert(count.is_lock_free());
471  return ++count;
472 }
473 
474 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
475 atomic_ctr_opt<V, LkT>::operator++(int) noexcept(true) {
476  assert(count.is_lock_free());
477  return count++;
478 }
479 
480 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
481 atomic_ctr_opt<V, LkT>::operator--() noexcept(true) {
482  assert(count.is_lock_free());
483  return --count;
484 }
485 
486 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
487 atomic_ctr_opt<V, LkT>::operator--(int) noexcept(true) {
488  assert(count.is_lock_free());
489  return count--;
490 }
491 
492 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
493 atomic_ctr_opt<V, LkT>::operator+=(const value_type v) noexcept(true) {
494  assert(count.is_lock_free());
495  return count+=v;
496 }
497 
498 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
499 atomic_ctr_opt<V, LkT>::operator+=(const atomic_ctr_opt &a) noexcept(true) {
500  assert(count.is_lock_free() && a.count.is_lock_free());
501  return *this+=a.count;
502 }
503 
504 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
505 atomic_ctr_opt<V, LkT>::operator-=(const value_type v) noexcept(true) {
506  assert(count.is_lock_free());
507  return count-=v;
508 }
509 
510 template<class V, class LkT> inline typename atomic_ctr_opt<V, LkT>::value_type
511 atomic_ctr_opt<V, LkT>::operator-=(const atomic_ctr_opt &a) noexcept(true) {
512  assert(count.is_lock_free() && a.count.is_lock_free());
513  return *this-=a.count;
514 }
515 
516 template<class V, class LkT>
517 inline bool
518 atomic_ctr_opt<V, LkT>::compare_exchange_strong(value_type expected, value_type desired) noexcept(true) {
519  assert(count.is_lock_free());
520  return count.compare_exchange_strong(expected, desired);
521 }
522 
523 template<class V, class LkT>
524 template<class V1, class V2>
525 inline typename std::enable_if<std::is_pointer<V2>::value, bool>::type
526 atomic_ctr_opt<V, LkT>::compare_exchange_strong(value_type expected, V1 desired) noexcept(true) {
527  static_assert(std::is_base_of<typename std::remove_pointer<value_type>::type, typename std::remove_pointer<V1>::type>::value, "The two types must have the same base.");
528  return count.compare_exchange_strong(expected, desired);
529 }
530 
531 template<class V, class LkT>
532 template<class BinOp>
533 inline
534 typename atomic_ctr_opt<V, LkT>::value_type
535 atomic_ctr_opt<V, LkT>::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>()))) {
536  assert(count.is_lock_free());
537  value_type expected=count.load();
538  value_type desired;
539  do {
540  desired=op.operator()(expected, a);
541  } while (!compare_exchange_strong(expected, desired));
542  return expected;
543 }
544 
545 template<class V, class LkT>
546 template<class V1>
547 inline
548 typename atomic_ctr_opt<V, LkT>::value_type
549 atomic_ctr_opt<V, LkT>::apply(V1 const &a, std::plus<V1> const &) noexcept(true) {
550  assert(count.is_lock_free());
551  return *this+=a;
552 }
553 
554 template<class V, class LkT>
555 template<class V1>
556 inline
557 typename atomic_ctr_opt<V, LkT>::value_type
558 atomic_ctr_opt<V, LkT>::apply(V1 const &a, std::minus<V1> const &) noexcept(true) {
559  assert(count.is_lock_free());
560  return *this-=a;
561 }
562 
563 template<class V, class LkT>
564 template<class Op>
565 inline atomic_ctr_opt<V, LkT>
566 atomic_ctr_opt<V, LkT>::assign(Op &&op) noexcept(true) {
567  atomic_ctr_opt expected;
568  do {
569  expected=*this;
570  } while (!compare_exchange_strong(expected.get(), op(expected).get()));
571  return expected;
572 }
573 
574 } } }