From 29d56cc34f0ebb55fbd228f291378afe489a7e5d Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Fri, 9 Sep 2011 08:06:15 +0000
Subject: [PATCH] Added types, functions, macros for creating and using
 thread-safe protected (interlocked/atomic) integer variables.

---
 src/xpdev/threadwrap.c | 52 ++++++++++++++++++++++++++++++++++++++++++
 src/xpdev/threadwrap.h | 47 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+)

diff --git a/src/xpdev/threadwrap.c b/src/xpdev/threadwrap.c
index 0247b23904..e68664a66a 100644
--- a/src/xpdev/threadwrap.c
+++ b/src/xpdev/threadwrap.c
@@ -188,3 +188,55 @@ int pthread_mutex_destroy(pthread_mutex_t* mutex)
 }
 
 #endif	/* POSIX thread mutexes */
+
+/************************************************************************/
+/* Protected (thread-safe) Integers (e.g. atomic/interlocked variables) */
+/************************************************************************/
+
+int	protected_int32_init(protected_int32_t* prot, int32_t value)
+{
+	prot->value = value;
+	return pthread_mutex_init(&prot->mutex,NULL);
+}
+
+int	protected_int64_init(protected_int64_t* prot, int64_t value)
+{
+	prot->value = value;
+	return pthread_mutex_init(&prot->mutex,NULL);
+}
+
+int32_t protected_int32_adjust(protected_int32_t* i, int32_t adjustment)
+{
+	int32_t	newval;
+	pthread_mutex_lock(&i->mutex);
+	newval = i->value += adjustment;
+	pthread_mutex_unlock(&i->mutex);
+	return newval;
+}
+
+uint32_t protected_uint32_adjust(protected_uint32_t* i, int32_t adjustment)
+{
+	uint32_t newval;
+	pthread_mutex_lock(&i->mutex);
+	newval = i->value += adjustment;
+	pthread_mutex_unlock(&i->mutex);
+	return newval;
+}
+
+int64_t protected_int64_adjust(protected_int64_t* i, int64_t adjustment)
+{
+	int64_t	newval;
+	pthread_mutex_lock(&i->mutex);
+	newval = i->value += adjustment;
+	pthread_mutex_unlock(&i->mutex);
+	return newval;
+}
+
+uint64_t protected_uint64_adjust(protected_uint64_t* i, int64_t adjustment)
+{
+	uint64_t newval;
+	pthread_mutex_lock(&i->mutex);
+	newval = i->value += adjustment;
+	pthread_mutex_unlock(&i->mutex);
+	return newval;
+}
diff --git a/src/xpdev/threadwrap.h b/src/xpdev/threadwrap.h
index 336b380ffd..17b2c8227b 100644
--- a/src/xpdev/threadwrap.h
+++ b/src/xpdev/threadwrap.h
@@ -129,6 +129,53 @@ int pthread_mutex_destroy(pthread_mutex_t*);
 	#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP	pthread_mutex_initializer_np(/* recursive: */TRUE)
 #endif
 
+/************************************************************************/
+/* Protected (thread-safe) Integers (e.g. atomic/interlocked variables) */
+/************************************************************************/
+/* Use of these types and functions is not as fast as your compiler or  */
+/* platform-specific functions (e.g. InterlockedIncrement on Windows or */
+/* atomic_add_int on FreeBSD) but they have the advantage of always		*/
+/* working and being thread-safe on all platforms that support pthread	*/
+/* mutexes.																*/
+/************************************************************************/
+typedef struct {
+	int32_t				value;
+	pthread_mutex_t		mutex;
+} protected_int32_t;
+
+typedef struct {
+	uint32_t			value;
+	pthread_mutex_t		mutex;
+} protected_uint32_t;
+
+typedef struct {
+	int64_t				value;
+	pthread_mutex_t		mutex;
+} protected_int64_t;
+
+typedef struct {
+	uint64_t			value;
+	pthread_mutex_t		mutex;
+} protected_uint64_t;
+
+/* Return 0 on success, non-zero on failure (see pthread_mutex_init): */
+int			protected_int32_init(protected_int32_t*,	int32_t value);
+#define protected_uint32_init(i, val)	protected_int32_init((protected_int32_t*)i, val)
+int			protected_int64_init(protected_int64_t*,	int64_t value);
+#define protected_uint64_init(i, val)	protected_int64_init((protected_int64_t*)i, val)
+
+/* Return new value: */
+int32_t		protected_int32_adjust(protected_int32_t*,	int32_t adjustment);
+uint32_t	protected_uint32_adjust(protected_uint32_t*,int32_t adjustment);
+int64_t		protected_int64_adjust(protected_int64_t*,	int64_t adjustment);
+uint64_t	protected_uint64_adjust(protected_uint64_t*,int64_t adjustment);
+
+/* Return 0 on success, non-zero on failure (see pthread_mutex_destroy): */
+#define protected_int32_destroy(i)	pthread_mutex_destroy(&i.mutex)
+#define protected_uint32_destroy	protected_int32_destroy	
+#define protected_int64_destroy		protected_int32_destroy	
+#define protected_uint64_destroy	protected_int32_destroy	
+
 #if defined(__cplusplus)
 }
 #endif
-- 
GitLab