OnixS C++ CME MDP Conflated UDP Handler  1.1.2
API documentation
Atomic.h
Go to the documentation of this file.
1 // Copyright Onix Solutions Limited [OnixS]. All rights reserved.
2 //
3 // This software owned by Onix Solutions Limited [OnixS] and is
4 // protected by copyright law and international copyright treaties.
5 //
6 // Access to and use of the software is governed by the terms of the applicable
7 // OnixS Software Services Agreement (the Agreement) and Customer end user license
8 // agreements granting a non-assignable, non-transferable and non-exclusive license
9 // to use the software for it's own data processing purposes under the terms defined
10 // in the Agreement.
11 //
12 // Except as otherwise granted within the terms of the Agreement, copying or
13 // reproduction of any part of this source code or associated reference material
14 // to any other location for further reproduction or redistribution, and any
15 // amendments to this copyright notice, are expressly prohibited.
16 //
17 // Any reproduction or redistribution for sale or hiring of the Software not in
18 // accordance with the terms of the Agreement is a violation of copyright law.
19 //
20 
21 #pragma once
22 
23 #if defined (_MSC_VER)
24 #include <intrin.h>
25 #endif
26 
28 
30 
31 #if defined (_MSC_VER)
32 
33 template
34 <
35  size_t SizeOf
36 >
37 class AtomicOps;
38 
39 template
40 <>
41 class
42 AtomicOps<1>
43 {
44  typedef char Integral;
45 
46 public:
47  template
48  <
49  class Atomic,
50  class Target
51  >
52  static
53  void
54  read(
55  volatile Atomic* atomic,
56  Target* target)
57  {
58  *(Integral*)target =
59  *(volatile Integral*)atomic;
60 
61  _ReadWriteBarrier();
62  }
63 
64  template
65  <
66  class Atomic,
67  class Addend
68  >
69  static
70  void
71  add(
72  volatile Atomic* atomic,
73  Addend* addend)
74  {
75  const
76  Integral
77  addendValue =
78  *static_cast
79  <Integral*>
80  (addend);
81 
82  *(Integral*)addend =
83  (
84  _InterlockedExchangeAdd8
85  (
86  (volatile Integral*)atomic,
87  addendValue
88  )
89  +
90  addendValue
91  );
92  }
93 
94  template
95  <
96  class Atomic,
97  class Subtrahend
98  >
99  static
100  void
101  subtract(
102  volatile Atomic* atomic,
103  Subtrahend* subtrahend)
104  {
105  const
106  Integral
107  subtrahendValue =
108  *static_cast
109  <Integral*>
110  (subtrahend);
111 
112  *(Integral*)value =
113  (
114  _InterlockedExchangeAdd8
115  (
116  (volatile Integral*)atomic,
117  -subtrahendValue
118  )
119  -
120  subtrahendValue
121  );
122  }
123 
124  template
125  <
126  class Atomic,
127  class Value
128  >
129  static
130  void
131  store(
132  volatile Atomic* atomic,
133  const Value* value)
134  {
135  _InterlockedExchange8
136  (
137  (volatile Integral*)atomic,
138  *(const Integral*)value
139  );
140  }
141 
142  template
143  <
144  class Atomic,
145  class Value
146  >
147  static
148  void
149  exchange(
150  volatile Atomic* atomic,
151  Value* value)
152  {
153  *(Integral*)value =
154  _InterlockedExchange8
155  (
156  (volatile Integral*)atomic,
157  *static_cast<Integral*>(value)
158  );
159  }
160 
161  template
162  <
163  class Atomic,
164  class Comparand,
165  class Value
166  >
167  static
168  bool
169  compareExchange(
170  volatile Atomic* atomic,
171  Comparand* comparand,
172  const Value* value)
173  {
174  const
175  Integral
176  comparandValue =
177  *(Integral*)comparand;
178 
179  const Integral previous =
180  _InterlockedCompareExchange8
181  (
182  (volatile Integral*)atomic,
183  *(const Integral*)value,
184  comparandValue
185  );
186 
187  if (previous ==
188  comparandValue)
189  {
190  return true;
191  }
192 
193  *(Integral*)value = previous;
194 
195  return false;
196  }
197 };
198 
199 template
200 <>
201 class
202 AtomicOps<2>
203 {
204  typedef short Integral;
205 
206 public:
207  template
208  <
209  class Atomic,
210  class Target
211  >
212  static
213  void
214  read(
215  volatile Atomic* atomic,
216  Target* target)
217  {
218  *(Integral*)target =
219  *(volatile Integral*)atomic;
220 
221  _ReadWriteBarrier();
222  }
223 
224  template
225  <
226  class Atomic,
227  class Addend
228  >
229  static
230  void
231  add(
232  volatile Atomic* atomic,
233  Addend* addend)
234  {
235  const
236  Integral
237  addendValue =
238  *static_cast
239  <Integral*>
240  (addend);
241 
242  *(Integral*)addend =
243  (
244  _InterlockedExchangeAdd16
245  (
246  (volatile Integral*)atomic,
247  addendValue
248  )
249  +
250  addendValue
251  );
252  }
253 
254  template
255  <
256  class Atomic,
257  class Subtrahend
258  >
259  static
260  void
261  subtract(
262  volatile Atomic* atomic,
263  Subtrahend* subtrahend)
264  {
265  const
266  Integral
267  subtrahendValue =
268  *static_cast
269  <Integral*>
270  (subtrahend);
271 
272  *(Integral*)value =
273  (
274  _InterlockedExchangeAdd16
275  (
276  (volatile Integral*)atomic,
277  -subtrahendValue
278  )
279  -
280  subtrahendValue
281  );
282  }
283 
284  template
285  <
286  class Atomic,
287  class Value
288  >
289  static
290  void
291  store(
292  volatile Atomic* atomic,
293  const Value* value)
294  {
295  _InterlockedExchange16
296  (
297  (volatile Integral*)atomic,
298  *(const Integral*)value
299  );
300  }
301 
302  template
303  <
304  class Atomic,
305  class Value
306  >
307  static
308  void
309  exchange(
310  volatile Atomic* atomic,
311  Value* value)
312  {
313  *(Integral*)value =
314  _InterlockedExchange16
315  (
316  (volatile Integral*)atomic,
317  *static_cast<Integral*>(value)
318  );
319  }
320 
321  template
322  <
323  class Atomic,
324  class Comparand,
325  class Value
326  >
327  static
328  bool
329  compareExchange(
330  volatile Atomic* atomic,
331  Comparand* comparand,
332  const Value* value)
333  {
334  const
335  Integral
336  comparandValue =
337  *(Integral*)comparand;
338 
339  const Integral previous =
340  _InterlockedCompareExchange16
341  (
342  (volatile Integral*)atomic,
343  *(const Integral*)value,
344  comparandValue
345  );
346 
347  if (previous ==
348  comparandValue)
349  {
350  return true;
351  }
352 
353  *(Integral*)value = previous;
354 
355  return false;
356  }
357 };
358 
359 template
360 <>
361 class
362 AtomicOps<4>
363 {
364  typedef long Integral;
365 
366 public:
367  template
368  <
369  class Atomic,
370  class Target
371  >
372  static
373  void
374  read(
375  volatile Atomic* atomic,
376  Target* target)
377  {
378  *(Integral*)target =
379  *(volatile Integral*)atomic;
380 
381  _ReadWriteBarrier();
382  }
383 
384  template
385  <
386  class Atomic,
387  class Addend
388  >
389  static
390  void
391  add(
392  volatile Atomic* atomic,
393  Addend* addend)
394  {
395  const
396  Integral
397  addendValue =
398  *static_cast
399  <Integral*>
400  (addend);
401 
402  *(Integral*)addend =
403  (
404  _InterlockedExchangeAdd
405  (
406  (volatile Integral*)atomic,
407  addendValue
408  )
409  +
410  addendValue
411  );
412  }
413 
414  template
415  <
416  class Atomic,
417  class Subtrahend
418  >
419  static
420  void
421  subtract(
422  volatile Atomic* atomic,
423  Subtrahend* subtrahend)
424  {
425  const
426  Integral
427  subtrahendValue =
428  *static_cast
429  <Integral*>
430  (subtrahend);
431 
432  *(Integral*)value =
433  (
434  _InterlockedExchangeAdd
435  (
436  (volatile Integral*)atomic,
437  -subtrahendValue
438  )
439  -
440  subtrahendValue
441  );
442  }
443 
444  template
445  <
446  class Atomic,
447  class Value
448  >
449  static
450  void
451  store(
452  volatile Atomic* atomic,
453  const Value* value)
454  {
455  _InterlockedExchange
456  (
457  (volatile Integral*)atomic,
458  *(const Integral*)value
459  );
460  }
461 
462  template
463  <
464  class Atomic,
465  class Value
466  >
467  static
468  void
469  exchange(
470  volatile Atomic* atomic,
471  Value* value)
472  {
473  *(Integral*)value =
474  _InterlockedExchange
475  (
476  (volatile Integral*)atomic,
477  *static_cast<Integral*>(value)
478  );
479  }
480 
481  template
482  <
483  class Atomic,
484  class Comparand,
485  class Value
486  >
487  static
488  bool
489  compareExchange(
490  volatile Atomic* atomic,
491  Comparand* comparand,
492  const Value* value)
493  {
494  const
495  Integral
496  comparandValue =
497  *(Integral*)comparand;
498 
499  const Integral previous =
500  _InterlockedCompareExchange
501  (
502  (volatile Integral*)atomic,
503  *(const Integral*)value,
504  comparandValue
505  );
506 
507  if (previous ==
508  comparandValue)
509  {
510  return true;
511  }
512 
513  *(Integral*)value = previous;
514 
515  return false;
516  }
517 };
518 
519 template
520 <>
521 class
522 AtomicOps<8>
523 {
524  typedef long long Integral;
525 
526 public:
527  template
528  <
529  class Atomic,
530  class Target
531  >
532  static
533  void
534  read(
535  volatile Atomic* atomic,
536  Target* target)
537  {
538  *(Integral*)target =
539  *(volatile Integral*)atomic;
540 
541  _ReadWriteBarrier();
542  }
543 
544  template
545  <
546  class Atomic,
547  class Addend
548  >
549  static
550  void
551  add(
552  volatile Atomic* atomic,
553  Addend* addend)
554  {
555  const
556  Integral
557  addendValue =
558  *static_cast
559  <Integral*>
560  (addend);
561 
562  *(Integral*)addend =
563  (
564  _InterlockedExchangeAdd64
565  (
566  (volatile Integral*)atomic,
567  addendValue
568  )
569  +
570  addendValue
571  );
572  }
573 
574  template
575  <
576  class Atomic,
577  class Subtrahend
578  >
579  static
580  void
581  subtract(
582  volatile Atomic* atomic,
583  Subtrahend* subtrahend)
584  {
585  const
586  Integral
587  subtrahendValue =
588  *static_cast
589  <Integral*>
590  (subtrahend);
591 
592  *(Integral*)value =
593  (
594  _InterlockedExchangeAdd64
595  (
596  (volatile Integral*)atomic,
597  -subtrahendValue
598  )
599  -
600  subtrahendValue
601  );
602  }
603 
604  template
605  <
606  class Atomic,
607  class Value
608  >
609  static
610  void
611  store(
612  volatile Atomic* atomic,
613  const Value* value)
614  {
615  _InterlockedExchange64
616  (
617  (volatile Integral*)atomic,
618  *(const Integral*)value
619  );
620  }
621 
622  template
623  <
624  class Atomic,
625  class Value
626  >
627  static
628  void
629  exchange(
630  volatile Atomic* atomic,
631  Value* value)
632  {
633  *(Integral*)value =
634  _InterlockedExchange64
635  (
636  (volatile Integral*)atomic,
637  *static_cast<Integral*>(value)
638  );
639  }
640 
641  template
642  <
643  class Atomic,
644  class Comparand,
645  class Value
646  >
647  static
648  bool
649  compareExchange(
650  volatile Atomic* atomic,
651  Comparand* comparand,
652  const Value* value)
653  {
654  const
655  Integral
656  comparandValue =
657  *(Integral*)comparand;
658 
659  const Integral previous =
660  _InterlockedCompareExchange64
661  (
662  (volatile Integral*)atomic,
663  *(const Integral*)value,
664  comparandValue
665  );
666 
667  if (previous ==
668  comparandValue)
669  {
670  return true;
671  }
672 
673  *(Integral*)value = previous;
674 
675  return false;
676  }
677 };
678 
679 //
680 
681 template
682 <
683  typename Type
684 >
685 struct Atomic
686 {
687  static
688  Type
689  read(
690  volatile Type& atomic)
691  {
692  Type value = Type();
693 
694  AtomicOps
695  <sizeof(Type)>::
696  read(
697  &atomic,
698  &value);
699 
700  return value;
701  }
702 
703  static
704  void
705  store(
706  volatile Type& atomic,
707  Type value)
708  {
709  AtomicOps
710  <sizeof(Type)>::
711  store(
712  &atomic,
713  &value);
714  }
715 
716  static
717  void
718  exchange(
719  volatile Type& atomic,
720  Type& value)
721  {
722  AtomicOps
723  <sizeof(Type)>::
724  exchange(
725  &atomic,
726  &value);
727  }
728 
729  static
730  bool
731  compareStore(
732  volatile Type& atomic,
733  Type comparand,
734  Type value)
735  {
736  return
737  AtomicOps
738  <sizeof(Type)>::
739  compareExchange(
740  &atomic,
741  &comparand,
742  &value);
743  }
744 
745  static
746  bool
747  compareExchange(
748  volatile Type& atomic,
749  Type comparand,
750  Type& value)
751  {
752  return
753  AtomicOps
754  <sizeof(Type)>::
755  compareExchange(
756  &atomic,
757  &comparand,
758  &value);
759  }
760 };
761 
762 #elif defined (__GNUC__)
763 
764 template
765 <
766  typename Type
767 >
768 struct Atomic
769 {
770  static
771  Type
772  read(
773  volatile Type& atomic)
774  {
775  const Type value = atomic;
776 
777  __sync_synchronize();
778 
779  return value;
780  }
781 
782  static
783  void
784  store(
785  volatile Type& atomic,
786  Type value)
787  {
788  (void)
789  (
790  __sync_lock_test_and_set
791  (
792  &atomic,
793  value
794  )
795  );
796  }
797 
798  static
799  void
800  exchange(
801  volatile Type& atomic,
802  Type& value)
803  {
804  value =
805  __sync_lock_test_and_set
806  (
807  &atomic,
808  value
809  );
810  }
811 
812  static
813  bool
814  compareStore(
815  volatile Type& atomic,
816  Type comparand,
817  Type value)
818  {
819  return
820  __sync_bool_compare_and_swap
821  (
822  &atomic,
823  comparand,
824  value
825  );
826  }
827 
828  static
829  bool
830  compareExchange(
831  volatile Type& atomic,
832  Type comparand,
833  Type& value)
834  {
835  const
836  Type
837  oldValue =
838  __sync_val_compare_and_swap
839  (
840  &atomic,
841  comparand,
842  value
843  );
844 
845  if (oldValue == comparand)
846  return true;
847 
848  value = oldValue;
849 
850  return false;
851  }
852 };
853 
854 #endif // Toolset selector.
855 
856 template
857 <
858  typename Type,
859  Type Value
860 >
861 class
863 {
864  volatile Type& variable_;
865 
867  const AtomicScopedStore&);
868 
870  operator =(
871  const AtomicScopedStore&);
872 
873 public:
875  volatile Type& variable)
876  : variable_(variable)
877  {
878  }
879 
881  {
882  Atomic<Type>::
883  store(
884  variable_,
885  Value);
886  }
887 };
888 
#define ONIXS_CONFLATEDUDP_NAMESPACE_END
Definition: Bootstrap.h:157
AtomicScopedStore(volatile Type &variable)
Definition: Atomic.h:874
bool value(Number &number, const MultiContainer &container, Tag tag)
#define ONIXS_CONFLATEDUDP_NAMESPACE_BEGIN
Definition: Bootstrap.h:153