|
@@ -14,6 +14,10 @@
|
|
|
#include <pthread.h>
|
|
|
#endif
|
|
|
|
|
|
+#ifdef HAVE_STDATOMIC_H
|
|
|
+#include <stdatomic.h>
|
|
|
+#endif
|
|
|
+
|
|
|
#if defined(_WIN32)
|
|
|
#define USE_WIN32_THREADS
|
|
|
#elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE)
|
|
@@ -150,16 +154,68 @@ void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
|
|
|
/**
|
|
|
* Atomic counter type; holds a size_t value.
|
|
|
*/
|
|
|
+#ifdef HAVE_STDATOMIC_H
|
|
|
+typedef struct atomic_counter_t {
|
|
|
+ atomic_size_t val;
|
|
|
+} atomic_counter_t;
|
|
|
+#define ATOMIC_LINKAGE static
|
|
|
+#else
|
|
|
typedef struct atomic_counter_t {
|
|
|
tor_mutex_t mutex;
|
|
|
size_t val;
|
|
|
} atomic_counter_t;
|
|
|
+#define ATOMIC_LINKAGE
|
|
|
+#endif
|
|
|
+
|
|
|
+ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter);
|
|
|
+ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter);
|
|
|
+ATOMIC_LINKAGE void atomic_counter_add(atomic_counter_t *counter, size_t add);
|
|
|
+ATOMIC_LINKAGE void atomic_counter_sub(atomic_counter_t *counter, size_t sub);
|
|
|
+ATOMIC_LINKAGE size_t atomic_counter_get(atomic_counter_t *counter);
|
|
|
+ATOMIC_LINKAGE size_t atomic_counter_exchange(atomic_counter_t *counter,
|
|
|
+ size_t newval);
|
|
|
+#undef ATOMIC_LINKAGE
|
|
|
+
|
|
|
+#ifdef HAVE_STDATOMIC_H
|
|
|
+/** Initialize a new atomic counter with the value 0 */
|
|
|
+static inline void
|
|
|
+atomic_counter_init(atomic_counter_t *counter)
|
|
|
+{
|
|
|
+ atomic_init(&counter->val, 0);
|
|
|
+}
|
|
|
+/** Clean up all resources held by an atomic counter. */
|
|
|
+static inline void
|
|
|
+atomic_counter_destroy(atomic_counter_t *counter)
|
|
|
+{
|
|
|
+ (void)counter;
|
|
|
+}
|
|
|
+/** Add a value to an atomic counter. */
|
|
|
+static inline void
|
|
|
+atomic_counter_add(atomic_counter_t *counter, size_t add)
|
|
|
+{
|
|
|
+ (void) atomic_fetch_add(&counter->val, add);
|
|
|
+}
|
|
|
+/** Subtract a value from an atomic counter. */
|
|
|
+static inline void
|
|
|
+atomic_counter_sub(atomic_counter_t *counter, size_t sub)
|
|
|
+{
|
|
|
+ (void) atomic_fetch_sub(&counter->val, sub);
|
|
|
+}
|
|
|
+/** Return the current value of an atomic counter */
|
|
|
+static inline size_t
|
|
|
+atomic_counter_get(atomic_counter_t *counter)
|
|
|
+{
|
|
|
+ return atomic_load(&counter->val);
|
|
|
+}
|
|
|
+/** Replace the value of an atomic counter; return the old one. */
|
|
|
+static inline size_t
|
|
|
+atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
|
|
|
+{
|
|
|
+ return atomic_exchange(&counter->val, newval);
|
|
|
+}
|
|
|
|
|
|
-void atomic_counter_init(atomic_counter_t *counter);
|
|
|
-void atomic_counter_destroy(atomic_counter_t *counter);
|
|
|
-void atomic_counter_add(atomic_counter_t *counter, size_t add);
|
|
|
-void atomic_counter_sub(atomic_counter_t *counter, size_t sub);
|
|
|
-size_t atomic_counter_get(atomic_counter_t *counter);
|
|
|
+#else
|
|
|
+#endif
|
|
|
|
|
|
#endif /* !defined(TOR_COMPAT_THREADS_H) */
|
|
|
|