atomic_counter.hpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #ifndef __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
4 #define __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
5 
6 #include "stdint.hpp"
7 #include "macros.hpp"
8 
9 #if defined ZMQ_FORCE_MUTEXES
10 #define ZMQ_ATOMIC_COUNTER_MUTEX
11 #elif (defined __cplusplus && __cplusplus >= 201103L) \
12  || (defined _MSC_VER && _MSC_VER >= 1900)
13 #define ZMQ_ATOMIC_COUNTER_CXX11
14 #elif defined ZMQ_HAVE_ATOMIC_INTRINSICS
15 #define ZMQ_ATOMIC_COUNTER_INTRINSIC
16 #elif (defined __i386__ || defined __x86_64__) && defined __GNUC__
17 #define ZMQ_ATOMIC_COUNTER_X86
18 #elif defined __ARM_ARCH_7A__ && defined __GNUC__
19 #define ZMQ_ATOMIC_COUNTER_ARM
20 #elif defined ZMQ_HAVE_WINDOWS
21 #define ZMQ_ATOMIC_COUNTER_WINDOWS
22 #elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD \
23  || defined ZMQ_HAVE_GNU)
24 #define ZMQ_ATOMIC_COUNTER_ATOMIC_H
25 #elif defined __tile__
26 #define ZMQ_ATOMIC_COUNTER_TILE
27 #else
28 #define ZMQ_ATOMIC_COUNTER_MUTEX
29 #endif
30 
31 #if defined ZMQ_ATOMIC_COUNTER_MUTEX
32 #include "mutex.hpp"
33 #elif defined ZMQ_ATOMIC_COUNTER_CXX11
34 #include <atomic>
35 #elif defined ZMQ_ATOMIC_COUNTER_WINDOWS
36 #include "windows.hpp"
37 #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
38 #include <atomic.h>
39 #elif defined ZMQ_ATOMIC_COUNTER_TILE
40 #include <arch/atomic.h>
41 #endif
42 
43 namespace zmq
44 {
45 // This class represents an integer that can be incremented/decremented
46 // in atomic fashion.
47 //
48 // In zmq::shared_message_memory_allocator a buffer with an atomic_counter_t
49 // at the start is allocated. If the class does not align to pointer size,
50 // access to pointers in structures in the buffer will cause SIGBUS on
51 // architectures that do not allow mis-aligned pointers (eg: SPARC).
52 // Force the compiler to align to pointer size, which will cause the object
53 // to grow from 4 bytes to 8 bytes on 64 bit architectures (when not using
54 // mutexes).
55 
56 #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
57 class __declspec(align (8)) atomic_counter_t
58 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_ARM_ARMV7VE))
59 class __declspec(align (4)) atomic_counter_t
60 #else
62 #endif
63 {
64  public:
65  typedef uint32_t integer_t;
66 
68 
69  // Set counter _value (not thread-safe).
70  void set (integer_t value_) ZMQ_NOEXCEPT { _value = value_; }
71 
72  // Atomic addition. Returns the old _value.
74  {
75  integer_t old_value;
76 
77 #if defined ZMQ_ATOMIC_COUNTER_WINDOWS
78  old_value = InterlockedExchangeAdd ((LONG *) &_value, increment_);
79 #elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
80  old_value = __atomic_fetch_add (&_value, increment_, __ATOMIC_ACQ_REL);
81 #elif defined ZMQ_ATOMIC_COUNTER_CXX11
82  old_value = _value.fetch_add (increment_, std::memory_order_acq_rel);
83 #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
84  integer_t new_value = atomic_add_32_nv (&_value, increment_);
85  old_value = new_value - increment_;
86 #elif defined ZMQ_ATOMIC_COUNTER_TILE
87  old_value = arch_atomic_add (&_value, increment_);
88 #elif defined ZMQ_ATOMIC_COUNTER_X86
89  __asm__ volatile("lock; xadd %0, %1 \n\t"
90  : "=r"(old_value), "=m"(_value)
91  : "0"(increment_), "m"(_value)
92  : "cc", "memory");
93 #elif defined ZMQ_ATOMIC_COUNTER_ARM
94  integer_t flag, tmp;
95  __asm__ volatile(" dmb sy\n\t"
96  "1: ldrex %0, [%5]\n\t"
97  " add %2, %0, %4\n\t"
98  " strex %1, %2, [%5]\n\t"
99  " teq %1, #0\n\t"
100  " bne 1b\n\t"
101  " dmb sy\n\t"
102  : "=&r"(old_value), "=&r"(flag), "=&r"(tmp),
103  "+Qo"(_value)
104  : "Ir"(increment_), "r"(&_value)
105  : "cc");
106 #elif defined ZMQ_ATOMIC_COUNTER_MUTEX
107  sync.lock ();
108  old_value = _value;
109  _value += increment_;
110  sync.unlock ();
111 #else
112 #error atomic_counter is not implemented for this platform
113 #endif
114  return old_value;
115  }
116 
117  // Atomic subtraction. Returns false if the counter drops to zero.
118  bool sub (integer_t decrement_) ZMQ_NOEXCEPT
119  {
120 #if defined ZMQ_ATOMIC_COUNTER_WINDOWS
121  LONG delta = -((LONG) decrement_);
122  integer_t old = InterlockedExchangeAdd ((LONG *) &_value, delta);
123  return old - decrement_ != 0;
124 #elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
125  integer_t nv =
126  __atomic_sub_fetch (&_value, decrement_, __ATOMIC_ACQ_REL);
127  return nv != 0;
128 #elif defined ZMQ_ATOMIC_COUNTER_CXX11
129  const integer_t old =
130  _value.fetch_sub (decrement_, std::memory_order_acq_rel);
131  return old - decrement_ != 0;
132 #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
133  int32_t delta = -((int32_t) decrement_);
134  integer_t nv = atomic_add_32_nv (&_value, delta);
135  return nv != 0;
136 #elif defined ZMQ_ATOMIC_COUNTER_TILE
137  int32_t delta = -((int32_t) decrement_);
138  integer_t nv = arch_atomic_add (&_value, delta);
139  return nv != 0;
140 #elif defined ZMQ_ATOMIC_COUNTER_X86
141  integer_t oldval = -decrement_;
142  volatile integer_t *val = &_value;
143  __asm__ volatile("lock; xaddl %0,%1"
144  : "=r"(oldval), "=m"(*val)
145  : "0"(oldval), "m"(*val)
146  : "cc", "memory");
147  return oldval != decrement_;
148 #elif defined ZMQ_ATOMIC_COUNTER_ARM
149  integer_t old_value, flag, tmp;
150  __asm__ volatile(" dmb sy\n\t"
151  "1: ldrex %0, [%5]\n\t"
152  " sub %2, %0, %4\n\t"
153  " strex %1, %2, [%5]\n\t"
154  " teq %1, #0\n\t"
155  " bne 1b\n\t"
156  " dmb sy\n\t"
157  : "=&r"(old_value), "=&r"(flag), "=&r"(tmp),
158  "+Qo"(_value)
159  : "Ir"(decrement_), "r"(&_value)
160  : "cc");
161  return old_value - decrement_ != 0;
162 #elif defined ZMQ_ATOMIC_COUNTER_MUTEX
163  sync.lock ();
164  _value -= decrement_;
165  bool result = _value ? true : false;
166  sync.unlock ();
167  return result;
168 #else
169 #error atomic_counter is not implemented for this platform
170 #endif
171  }
172 
174  {
175  return _value;
176  }
177 
178  private:
179 #if defined ZMQ_ATOMIC_COUNTER_CXX11
180  std::atomic<integer_t> _value;
181 #else
182  volatile integer_t _value;
183 #endif
184 
185 #if defined ZMQ_ATOMIC_COUNTER_MUTEX
187 #endif
188 
189 #if !defined ZMQ_ATOMIC_COUNTER_CXX11
191 #endif
192 #if defined(__GNUC__) || defined(__INTEL_COMPILER) \
193  || (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \
194  || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
195 } __attribute__ ((aligned (sizeof (void *))));
196 #else
197 };
198 #endif
199 }
200 
201 // Remove macros local to this file.
202 #undef ZMQ_ATOMIC_COUNTER_MUTEX
203 #undef ZMQ_ATOMIC_COUNTER_INTRINSIC
204 #undef ZMQ_ATOMIC_COUNTER_CXX11
205 #undef ZMQ_ATOMIC_COUNTER_X86
206 #undef ZMQ_ATOMIC_COUNTER_ARM
207 #undef ZMQ_ATOMIC_COUNTER_WINDOWS
208 #undef ZMQ_ATOMIC_COUNTER_ATOMIC_H
209 #undef ZMQ_ATOMIC_COUNTER_TILE
210 
211 #endif
benchmarks.python.py_benchmark.const
const
Definition: py_benchmark.py:14
zmq::atomic_counter_t::integer_t
uint32_t integer_t
Definition: atomic_counter.hpp:65
zmq::atomic_counter_t::set
void set(integer_t value_) ZMQ_NOEXCEPT
Definition: atomic_counter.hpp:70
zmq
Definition: zmq.hpp:229
ZMQ_NOEXCEPT
#define ZMQ_NOEXCEPT
Definition: macros.hpp:19
macros.hpp
windows.hpp
stdint.hpp
zmq::atomic_counter_t
Definition: atomic_counter.hpp:61
zmq::atomic_counter_t::get
integer_t get() const ZMQ_NOEXCEPT
Definition: atomic_counter.hpp:173
zmq::atomic_counter_t::add
integer_t add(integer_t increment_) ZMQ_NOEXCEPT
Definition: atomic_counter.hpp:73
ZMQ_NON_COPYABLE_NOR_MOVABLE
#define ZMQ_NON_COPYABLE_NOR_MOVABLE(classname)
Definition: macros.hpp:58
zmq::atomic_counter_t::_value
volatile integer_t _value
Definition: atomic_counter.hpp:182
zmq::atomic_counter_t::sync
mutex_t sync
Definition: atomic_counter.hpp:186
zmq::mutex_t
Definition: mutex.hpp:82
value_
int value_
Definition: gmock-matchers_test.cc:571
zmq::atomic_counter_t::sub
bool sub(integer_t decrement_) ZMQ_NOEXCEPT
Definition: atomic_counter.hpp:118
true
#define true
Definition: cJSON.c:65
val
GLuint GLfloat * val
Definition: glcorearb.h:3604
mutex.hpp
zmq::atomic_counter_t::atomic_counter_t
atomic_counter_t(integer_t value_=0) ZMQ_NOEXCEPT
Definition: atomic_counter.hpp:67


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:48