]> git.mxchange.org Git - simgear.git/commitdiff
Modified Files:
authorfrohlich <frohlich>
Wed, 27 Dec 2006 10:07:19 +0000 (10:07 +0000)
committerfrohlich <frohlich>
Wed, 27 Dec 2006 10:07:19 +0000 (10:07 +0000)
Makefile.am SGReferenced.hxx
Added Files:
SGAtomic.cxx SGAtomic.hxx:
Make the reference counts thread safe.

simgear/structure/Makefile.am
simgear/structure/SGAtomic.cxx [new file with mode: 0644]
simgear/structure/SGAtomic.hxx [new file with mode: 0644]
simgear/structure/SGReferenced.hxx

index 6324da1747b1fe496b3220335a7481c5fb95f9e1..6cbc483cd30fce8679d13b9a9ab3a8e9057f3c79 100644 (file)
@@ -8,6 +8,7 @@ include_HEADERS = \
        exception.hxx \
        event_mgr.hxx \
        subsystem_mgr.hxx \
+       SGAtomic.hxx \
        SGReferenced.hxx \
        SGSharedPtr.hxx
 
@@ -15,8 +16,8 @@ libsgstructure_a_SOURCES = \
        commands.cxx \
        exception.cxx \
        event_mgr.cxx\
-       subsystem_mgr.cxx
-
+       subsystem_mgr.cxx \
+       SGAtomic.cxx
 
 INCLUDES = -I$(top_srcdir)
 
diff --git a/simgear/structure/SGAtomic.cxx b/simgear/structure/SGAtomic.cxx
new file mode 100644 (file)
index 0000000..3505fab
--- /dev/null
@@ -0,0 +1,63 @@
+/* -*-c++-*-
+ *
+ * Copyright (C) 2005-2006 Mathias Froehlich 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include "SGAtomic.hxx"
+
+#if defined(SGATOMIC_USE_GCC4_BUILTINS) && defined(__i386__)
+
+// Usually the apropriate functions are inlined by gcc.
+// But if gcc is called with something aequivalent to -march=i386,
+// it will not assume that there is a lock instruction and instead
+// calls this pair of functions. We will provide them here in this case.
+// Note that this assembler code will not work on a i386 chip anymore.
+// But I hardly believe that we can assume to run at least on a i486 ...
+
+extern "C" {
+
+unsigned __sync_sub_and_fetch_4(volatile void *ptr, unsigned value)
+{
+  register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(ptr);
+  register unsigned result;
+  __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
+                       : "=r" (result), "=m" (*mem)
+                       : "0" (-value), "m" (*mem)
+                       : "memory");
+  return result;
+}
+
+unsigned __sync_add_and_fetch_4(volatile void *ptr, unsigned value)
+{
+  register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(ptr);
+  register unsigned result;
+  __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
+                       : "=r" (result), "=m" (*mem)
+                       : "0" (value), "m" (*mem)
+                       : "memory");
+  return result;
+}
+
+void __sync_synchronize()
+{
+  __asm__ __volatile__("": : : "memory");
+}
+
+} // extern "C"
+
+#endif
diff --git a/simgear/structure/SGAtomic.hxx b/simgear/structure/SGAtomic.hxx
new file mode 100644 (file)
index 0000000..7bf8226
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*-c++-*-
+ *
+ * Copyright (C) 2005-2006 Mathias Froehlich 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef SGAtomic_HXX
+#define SGAtomic_HXX
+
+#if defined(__GNUC__) && (4 <= __GNUC__) && (1 <= __GNUC_MINOR__) \
+  && (defined(__i386__) || defined(__x86_64__))
+// No need to include something. Is a Compiler API ...
+# define SGATOMIC_USE_GCC4_BUILTINS
+#elif defined(WIN32) 
+# include <windows.h>
+# define SGATOMIC_USE_WIN32_INTERLOCKED
+#else
+// The sledge hammer ...
+# include <simgear/threads/SGThread.hxx>
+# include <simgear/threads/SGGuard.hxx>
+#endif
+
+class SGAtomic {
+public:
+  SGAtomic(unsigned value = 0) : mValue(value)
+  { }
+  unsigned operator++()
+  {
+#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+    return __sync_add_and_fetch(&mValue, 1);
+#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
+    return InterlockedIncrement(reinterpret_cast<long volatile*>(&mValue));
+#else
+    SGGuard<SGMutex> lock(mMutex);
+    return ++mValue;
+#endif
+  }
+  unsigned operator--()
+  {
+#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+    return __sync_sub_and_fetch(&mValue, 1);
+#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
+    return InterlockedDecrement(reinterpret_cast<long volatile*>(&mValue));
+#else
+    SGGuard<SGMutex> lock(mMutex);
+    return --mValue;
+#endif
+  }
+  operator unsigned() const
+  {
+#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+    __sync_synchronize();
+    return mValue;
+#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
+    return static_cast<unsigned const volatile &>(mValue);
+#else
+    SGGuard<SGMutex> lock(mMutex);
+    return mValue;
+#endif
+ }
+
+private:
+  SGAtomic(const SGAtomic&);
+  SGAtomic& operator=(const SGAtomic&);
+
+#if !defined(SGATOMIC_USE_GCC4_BUILTINS) \
+  && !defined(SGATOMIC_USE_WIN32_INTERLOCKED)
+  mutable SGMutex mMutex;
+#endif
+#ifdef SGATOMIC_USE_WIN32_INTERLOCKED
+  __declspec(align(32))
+#endif
+  unsigned mValue;
+};
+
+#endif
index 13f929954b48df485cb0c21e581f810702d26f3a..6a3038f3576494619e6590144ce3d638d547be31 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef SGReferenced_HXX
 #define SGReferenced_HXX
 
+#include "SGAtomic.hxx"
+
 /// Base class for all reference counted SimGear objects
 /// Classes derived from this one are meant to be managed with
 /// the SGSharedPtr class.
@@ -47,7 +49,7 @@ public:
   { if (ref) return 1u < ref->_refcount; else return false; }
 
 private:
-  mutable unsigned _refcount;
+  mutable SGAtomic _refcount;
 };
 
 #endif