OnixS C++ CME MDP Conflated UDP Handler 1.1.2
API documentation
Loading...
Searching...
No Matches
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
33template
34<
35 size_t SizeOf
36>
37class AtomicOps;
38
39template
40<>
41class
42AtomicOps<1>
43{
44 typedef char Integral;
45
46public:
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
199template
200<>
201class
202AtomicOps<2>
203{
204 typedef short Integral;
205
206public:
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
359template
360<>
361class
362AtomicOps<4>
363{
364 typedef long Integral;
365
366public:
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
519template
520<>
521class
522AtomicOps<8>
523{
524 typedef long long Integral;
525
526public:
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
681template
682<
683 typename Type
684>
685struct 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
764template
765<
766 typename Type
767>
768struct 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
856template
857<
858 typename Type,
859 Type Value
860>
861class
862AtomicScopedStore
863{
864 volatile Type& variable_;
865
866 AtomicScopedStore(
867 const AtomicScopedStore&);
868
869 AtomicScopedStore&
870 operator =(
871 const AtomicScopedStore&);
872
873public:
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
#define ONIXS_CONFLATEDUDP_NAMESPACE_BEGIN
Definition Bootstrap.h:153
AtomicScopedStore(volatile Type &variable)
Definition Atomic.h:874
bool value(Number &number, const MultiContainer &container, Tag tag)