diff options
author | Shawn O. Pearce <spearce@spearce.org> | 2008-12-31 13:20:21 -0800 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2008-12-31 13:36:55 -0800 |
commit | 028ef0de72da1ad4d1b2ee4a125ede81e3f2ebed (patch) | |
tree | 480cc70e318d8a80657f36fb55967477050cf3ec /src/thread-utils.h | |
parent | d44cfd460e2c52d67dea14838b03219967cf9cb9 (diff) | |
download | libgit2-028ef0de72da1ad4d1b2ee4a125ede81e3f2ebed.tar.gz |
Add a mutex and atomic counter abstraction and implementations
These abstractions can be used to implement an efficient resource
reference counter and simple mutual exclusion. On pthreads we use
pthread_mutex_t, except when we are also on glibc and can directly
use its asm/atomic.h definitions.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'src/thread-utils.h')
-rw-r--r-- | src/thread-utils.h | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/src/thread-utils.h b/src/thread-utils.h index 199447c2a..f5a98ad91 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -1,7 +1,88 @@ #ifndef INCLUDE_thread_utils_h__ #define INCLUDE_thread_utils_h__ -#include "git/thread-utils.h" +#if defined(GIT_HAS_PTHREAD) +typedef pthread_mutex_t git_lck; +# define GITLCK_INIT PTHREAD_MUTEX_INITIALIZER +# define gitlck_init(a) pthread_mutex_init(a, NULL) +# define gitlck_lock(a) pthread_mutex_lock(a) +# define gitlck_unlock(a) pthread_mutex_unlock(a) +# define gitlck_free(a) pthread_mutex_destroy(a) + +# if defined(__GLIBC__) +# include <asm/atomic.h> +typedef atomic_t git_refcnt; +# define gitrc_init(a) atomic_set(a, 0) +# define gitrc_inc(a) atomic_inc_return(a) +# define gitrc_dec(a) atomic_dec_and_test(a) +# define gitrc_free(a) (void)0 + +# else +typedef struct { git_lck lock; int counter; } git_refcnt; + +/** Initialize to 0. No memory barrier is issued. */ +GIT_INLINE(void) gitrc_init(git_refcnt *p) +{ + gitlck_init(&p->lock); + p->counter = 0; +} + +/** + * Increment. + * + * Atomically increments @p by 1. A memory barrier is also + * issued before and after the operation. + * + * @param p pointer of type git_refcnt + */ +GIT_INLINE(void) gitrc_inc(git_refcnt *p) +{ + gitlck_lock(&p->lock); + p->counter++; + gitlck_unlock(&p->lock); +} + +/** + * Decrement and test. + * + * Atomically decrements @p by 1 and returns true if the + * result is 0, or false for all other cases. A memory + * barrier is also issued before and after the operation. + * + * @param p pointer of type git_refcnt + */ +GIT_INLINE(int) gitrc_dec(git_refcnt *p) +{ + int c; + gitlck_lock(&p->lock); + c = --p->counter; + gitlck_unlock(&p->lock); + return !!c; +} + +/** Free any resources associated with the counter. */ +# define gitrc_free(p) gitlck_free(&(p)->lock) + +# endif + +#elif defined(GIT_THREADS) +# error GIT_THREADS but no git_lck implementation + +#else +typedef struct {} git_lck; +# define GIT_MUTEX_INIT {} +# define gitlck_init(a) (void)0 +# define gitlck_lock(a) (void)0 +# define gitlck_unlock(a) (void)0 +# define gitlck_free(a) (void)0 + +typedef struct { int counter; } git_refcnt; +# define gitrc_init(a) ((a)->counter = 0) +# define gitrc_inc(a) ((a)->counter++) +# define gitrc_dec(a) (--(a)->counter == 0) +# define gitrc_free(a) (void)0 + +#endif extern int git_online_cpus(void); |