diff options
author | antirez <antirez@gmail.com> | 2015-09-25 10:06:47 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2015-10-01 13:02:25 +0200 |
commit | 7e5d69019e233d306accce19611f68c92ff45da8 (patch) | |
tree | aa1f25bc679d912b55d2db0d2484a5b0d257e47d | |
parent | 7af4eeb7455b40ef73c436d7b9eb05df31eb6886 (diff) | |
download | redis-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.h | 94 |
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 */ |