This patch is my attempt to simplify the platform-specific
conditional logic in apr_atomic.h.

I need a few volunteers to test it on Win32, FreeBSD, Netware,
and OS/390 before I commit.

With this patch, the overriding of the default atomic ops is
mow more granular: you can add #defines for whatever atomic
ops are available natively on your target platform, and the
ifdefs at the end of apr_atomic.h will pull in default
declarations for the ops that are missing.

I've also added a default implementation for platforms without
threads in apr_atomic.c.

--Brian

Index: include/apr_atomic.h
===================================================================
RCS file: /home/cvs/apr/include/apr_atomic.h,v
retrieving revision 1.32
diff -u -r1.32 apr_atomic.h
--- include/apr_atomic.h        5 Jul 2002 20:51:39 -0000       1.32
+++ include/apr_atomic.h        13 Jul 2002 03:29:36 -0000
@@ -136,13 +136,14 @@
 apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp);
 #else /* !DOXYGEN */
 
-#if APR_FORCE_ATOMIC_GENERIC 
-#if APR_HAS_THREADS
-#define APR_ATOMIC_NEED_DEFAULT 1
-#define APR_ATOMIC_NEED_CAS_DEFAULT 1
-#endif /* APR_HAS_THREADS */
+/* The following definitions provide optimized, OS-specific
+ * implementations of the APR atomic functions on various
+ * platforms.  Any atomic operation that isn't redefined as
+ * a macro here will be declared as a function later, and
+ * apr_atomic.c will provide a mutex-based default implementation.
+ */
 
-#elif defined(WIN32)
+#if defined(WIN32)
 
 typedef LONG apr_atomic_t;
 
@@ -161,6 +162,7 @@
 
 #define apr_atomic_add(mem, val)     atomic_add(mem,val)
 APR_DECLARE(int) apr_atomic_dec(apr_atomic_t *mem);
+#define apr_override_atomic_dec 1
 #define apr_atomic_inc(mem)          atomic_inc(mem)
 #define apr_atomic_set(mem, val)     (*mem = val)
 #define apr_atomic_read(mem)         (*mem)
@@ -178,9 +180,8 @@
 #define apr_atomic_set(mem, val)     atomic_set_int(mem, val)
 #define apr_atomic_read(mem)         (*mem)
 
-#define APR_ATOMIC_NEED_CAS_DEFAULT 1
+#elif defined(__linux__) && defined(__i386__) && !APR_FORCE_ATOMIC_GENERIC
 
-#elif defined(__linux__) && defined(__i386__)
 #define apr_atomic_t apr_uint32_t
 #define apr_atomic_cas(mem,with,cmp) \
 ({ apr_atomic_t prev; \
@@ -190,12 +191,8 @@
          : "memory"); \
     prev;})
 
-#define APR_ATOMIC_NEED_DEFAULT 1
-#if defined(APR_ATOMIC_NEED_CAS_DEFAULT)
-#undef APR_ATOMIC_NEED_CAS_DEFAULT
-#endif
+#elif defined(__sparc__) || defined(sparc) && !APR_FORCE_ATOMIC_GENERIC
 
-#elif defined(__sparc__) || defined(sparc)
 #define apr_atomic_t apr_uint32_t
 #define apr_atomic_read(p)  *p
 
@@ -217,6 +214,8 @@
 apr_int32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_int32_t val);
 apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, 
                             apr_uint32_t cmp);
+#define apr_override_atomic_add 1
+#define apr_override_atomic_cas 1
 
 #define apr_atomic_inc(mem)          apr_atomic_add(mem, 1)
 #define apr_atomic_dec(mem)          apr_atomic_add(mem, -1)
@@ -234,30 +233,67 @@
 #define apr_atomic_read(p)           (*p)
 #define apr_atomic_set(mem, val)     (*mem = val)
 
-#else
-#if APR_HAS_THREADS
-#define APR_ATOMIC_NEED_DEFAULT 1
-#define APR_ATOMIC_NEED_CAS_DEFAULT 1
-#endif /* APR_HAS_THREADS */
+#endif /* end big if-elseif switch for platform-specifics */
+
 
-#endif /* !defined(WIN32) */
+/* Default implementation of the atomic API
+ * The definitions above may override some or all of the
+ * atomic functions with optimized, platform-specific versions.
+ * Any operation that hasn't been overridden as a macro above
+ * is declared as a function here, unless apr_override_atomic_[operation]
+ * is defined.
+ */
+
+#define APR_ATOMIC_NEED_DEFAULT_INIT 0
 
-#if defined(APR_ATOMIC_NEED_DEFAULT)
+#if !defined(apr_atomic_t)
 #define apr_atomic_t apr_uint32_t
-#define apr_atomic_read(p)  *p
+#endif
+
+#if !defined(apr_atomic_init) && !defined(apr_override_atomic_init)
 apr_status_t apr_atomic_init(apr_pool_t *p);
+#endif
+
+#if !defined(apr_atomic_read) && !defined(apr_override_atomic_read)
+#define apr_atomic_read(p)  *p
+#endif
+
+#if !defined(apr_atomic_set) && !defined(apr_override_atomic_set)
 void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val);
+#define APR_ATOMIC_NEED_DEFAULT_INIT 1
+#endif
+
+#if !defined(apr_atomic_add) && !defined(apr_override_atomic_add)
 void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val);
+#define APR_ATOMIC_NEED_DEFAULT_INIT 1
+#endif
+
+#if !defined(apr_atomic_inc) && !defined(apr_override_atomic_inc)
 void apr_atomic_inc(volatile apr_atomic_t *mem);
+#define APR_ATOMIC_NEED_DEFAULT_INIT 1
+#endif
+
+#if !defined(apr_atomic_dec) && !defined(apr_override_atomic_dec)
 int apr_atomic_dec(volatile apr_atomic_t *mem);
+#define APR_ATOMIC_NEED_DEFAULT_INIT 1
 #endif
 
-#if defined(APR_ATOMIC_NEED_CAS_DEFAULT)
-apr_status_t apr_atomic_init(apr_pool_t *p);
+#if !defined(apr_atomic_cas) && !defined(apr_override_atomic_cas)
 apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp);
+#define APR_ATOMIC_NEED_DEFAULT_INIT 1
+#endif
+
+/* If we're using the default versions of any of the atomic functions,
+ * we'll need the atomic init to set up mutexes.  If a platform-specific
+ * override above has replaced the atomic_init with a macro, it's an error.
+ */
+#if APR_ATOMIC_NEED_DEFAULT_INIT
+#if defined(apr_atomic_init) || defined(apr_override_atomic_init)
+#error Platform has redefined apr_atomic_init, but other default default 
atomics require a default apr_atomic_init
 #endif
+#endif /* APR_ATOMIC_NEED_DEFAULT_INIT */
 
-#endif /* DOXYGEN */
+#endif /* !DOXYGEN */
 #ifdef __cplusplus
 }
 #endif
Index: atomic/unix/apr_atomic.c
===================================================================
RCS file: /home/cvs/apr/atomic/unix/apr_atomic.c,v
retrieving revision 1.16
diff -u -r1.16 apr_atomic.c
--- atomic/unix/apr_atomic.c    5 Jul 2002 21:10:10 -0000       1.16
+++ atomic/unix/apr_atomic.c    13 Jul 2002 03:29:36 -0000
@@ -56,17 +56,18 @@
 #include "apr_atomic.h"
 #include "apr_thread_mutex.h"
 
-#if APR_HAS_THREADS
-
-#if defined(APR_ATOMIC_NEED_DEFAULT) || defined(APR_ATOMIC_NEED_CAS_DEFAULT)
+#if !defined(apr_atomic_init) && !defined(apr_override_atomic_init)
 
+#if APR_HAS_THREADS
 #define NUM_ATOMIC_HASH 7
 /* shift by 2 to get rid of alignment issues */
 #define ATOMIC_HASH(x) (unsigned int)(((unsigned long)(x)>>2)%(unsigned 
int)NUM_ATOMIC_HASH)
 static apr_thread_mutex_t **hash_mutex;
+#endif /* APR_HAS_THREADS */
 
 apr_status_t apr_atomic_init(apr_pool_t *p)
 {
+#if APR_HAS_THREADS
     int i;
     apr_status_t rv;
     hash_mutex = apr_palloc(p, sizeof(apr_thread_mutex_t*) * NUM_ATOMIC_HASH);
@@ -78,13 +79,15 @@
            return rv;
         }
     }
+#endif /* APR_HAS_THREADS */
     return APR_SUCCESS;
 }
-#endif /* APR_ATOMIC_NEED_DEFAULT || APR_ATOMIC_NEED_CAS_DEFAULT */
+#endif /*!defined(apr_atomic_init) && !defined(apr_override_atomic_init) */
 
-#if defined(APR_ATOMIC_NEED_DEFAULT) 
+#if !defined(apr_atomic_add) && !defined(apr_override_atomic_add)
 void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val) 
 {
+#if APR_HAS_THREADS
     apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
     apr_uint32_t prev;
        
@@ -93,10 +96,16 @@
         *mem += val;
         apr_thread_mutex_unlock(lock);
     }
+#else
+    *mem += val;
+#endif /* APR_HAS_THREADS */
 }
+#endif /*!defined(apr_atomic_add) && !defined(apr_override_atomic_add) */
 
+#if !defined(apr_atomic_set) && !defined(apr_override_atomic_set)
 void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val) 
 {
+#if APR_HAS_THREADS
     apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
     apr_uint32_t prev;
 
@@ -105,10 +114,16 @@
         *mem = val;
         apr_thread_mutex_unlock(lock);
     }
+#else
+    *mem = val;
+#endif /* APR_HAS_THREADS */
 }
+#endif /*!defined(apr_atomic_set) && !defined(apr_override_atomic_set) */
 
+#if !defined(apr_atomic_inc) && !defined(apr_override_atomic_inc)
 void apr_atomic_inc(volatile apr_uint32_t *mem) 
 {
+#if APR_HAS_THREADS
     apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
     apr_uint32_t prev;
 
@@ -117,10 +132,16 @@
         (*mem)++;
         apr_thread_mutex_unlock(lock);
     }
+#else
+    (*mem)++;
+#endif /* APR_HAS_THREADS */
 }
+#endif /*!defined(apr_atomic_inc) && !defined(apr_override_atomic_inc) */
 
+#if !defined(apr_atomic_dec) && !defined(apr_override_atomic_dec)
 int apr_atomic_dec(volatile apr_atomic_t *mem) 
 {
+#if APR_HAS_THREADS
     apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
     apr_uint32_t new;
 
@@ -130,14 +151,17 @@
         apr_thread_mutex_unlock(lock);
         return new; 
     }
+#else
+    (*mem)--;
+#endif /* APR_HAS_THREADS */
     return *mem; 
 }
+#endif /*!defined(apr_atomic_dec) && !defined(apr_override_atomic_dec) */
 
-#endif /* APR_ATOMIC_NEED_DEFAULT */
-#if defined(APR_ATOMIC_NEED_CAS_DEFAULT)
-
+#if !defined(apr_atomic_cas) && !defined(apr_override_atomic_case)
 apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp)
 {
+#if APR_HAS_THREADS
     apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
     long prev;
 
@@ -150,16 +174,12 @@
         return prev;
     }
     return *(long*)mem;
-}
-#endif /* APR_ATOMIC_NEED_CAS_DEFAULT */
-
-#else /* !APR_HAS_THREADS */
-
-#if !defined(apr_atomic_init)
-apr_status_t apr_atomic_init(apr_pool_t *p)
-{
-    return APR_SUCCESS;
-}
-#endif /* !defined(apr_atomic_init) */
-
+#else
+    prev = *(long*)mem;
+    if ( prev == cmp) {
+        *(long*)mem = with;
+    }
+    return prev;
 #endif /* APR_HAS_THREADS */
+}
+#endif /*!defined(apr_atomic_dec) && !defined(apr_override_atomic_dec) */

Reply via email to