summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2015-09-25 10:06:47 +0200
committerantirez <antirez@gmail.com>2015-10-01 13:02:25 +0200
commit7e5d69019e233d306accce19611f68c92ff45da8 (patch)
treeaa1f25bc679d912b55d2db0d2484a5b0d257e47d
parent7af4eeb7455b40ef73c436d7b9eb05df31eb6886 (diff)
downloadredis-7e5d69019e233d306accce19611f68c92ff45da8.tar.gz
Atomic vars implemented in a more general way.
We have them into zmalloc.c, but this is going to replace that implementation, so that it's possible to use the same idea everywhere inside the code base.
-rw-r--r--src/atomicvar.h94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/atomicvar.h b/src/atomicvar.h
new file mode 100644
index 000000000..3489972d2
--- /dev/null
+++ b/src/atomicvar.h
@@ -0,0 +1,94 @@
+/* This file implements atomic counters using __atomic or __sync macros if
+ * available, otherwise synchronizing different threads using a mutex.
+ *
+ * The exported interaface is composed of three macros:
+ *
+ * atomicIncr(var,count,mutex) -- Increment the atomic counter
+ * atomicDecr(var,count,mutex) -- Decrement the atomic counter
+ * atomicGet(var,dstvar,mutex) -- Fetch the atomic counter value
+ *
+ * If atomic primitives are availble (tested in config.h) the mutex
+ * is not used.
+ *
+ * Never use return value from the macros. To update and get use instead:
+ *
+ * atomicIncr(mycounter,...);
+ * atomicGet(mycounter,newvalue);
+ * doSomethingWith(newvalue);
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * Copyright (c) 2015, Salvatore Sanfilippo <antirez at gmail dot com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Redis nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <pthread.h>
+
+#ifndef __ATOMIC_VAR_H
+#define __ATOMIC_VAR_H
+
+#if defined(__ATOMIC_RELAXED)
+/* Implementation using __atomic macros. */
+
+#define atomicIncr(var,count,mutex) __atomic_add_fetch(&var,(count),__ATOMIC_RELAXED)
+#define atomicDecr(var,count,mutex) __atomic_sub_fetch(&var,(count),__ATOMIC_RELAXED)
+#define atomicGet(var,dstvar,mutex) do { \
+ dstvar = __atomic_load_n(&var,__ATOMIC_RELAXED); \
+} while(0)
+
+#elif defined(HAVE_ATOMIC)
+/* Implementation using __sync macros. */
+
+#define atomicIncr(var,count,mutex) __sync_add_and_fetch(&var,(count))
+#define atomicDecr(var,count,mutex) __sync_sub_and_fetch(&var,(count))
+#define atomicGet(var,dstvar,mutex) do { \
+ dstvar = __sync_sub_and_fetch(&var,0); \
+} while(0)
+
+#else
+/* Implementation using pthread mutex. */
+
+#define atomicIncr(var,count,mutex) do { \
+ pthread_mutex_lock(&mutex); \
+ var += (count); \
+ pthread_mutex_unlock(&mutex); \
+} while(0)
+
+#define atomicDecr(var,count,mutex) do { \
+ pthread_mutex_lock(&mutex); \
+ var -= (count); \
+ pthread_mutex_unlock(&mutex); \
+} while(0)
+
+#define atomicGet(var,dstvar,mutex) do { \
+ pthread_mutex_lock(&mutex); \
+ dstvar = var; \
+ pthread_mutex_unlock(&mutex); \
+} while(0)
+#endif
+
+#endif /* __ATOMIC_VAR_H */