summaryrefslogtreecommitdiff
path: root/src/thread-utils.h
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2008-12-31 13:20:21 -0800
committerShawn O. Pearce <spearce@spearce.org>2008-12-31 13:36:55 -0800
commit028ef0de72da1ad4d1b2ee4a125ede81e3f2ebed (patch)
tree480cc70e318d8a80657f36fb55967477050cf3ec /src/thread-utils.h
parentd44cfd460e2c52d67dea14838b03219967cf9cb9 (diff)
downloadlibgit2-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.h83
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);