From: frohlich Date: Wed, 27 Dec 2006 10:07:19 +0000 (+0000) Subject: Modified Files: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=11b16b8a86d49743a2f29570871bd8adccb51890;p=simgear.git Modified Files: Makefile.am SGReferenced.hxx Added Files: SGAtomic.cxx SGAtomic.hxx: Make the reference counts thread safe. --- diff --git a/simgear/structure/Makefile.am b/simgear/structure/Makefile.am index 6324da17..6cbc483c 100644 --- a/simgear/structure/Makefile.am +++ b/simgear/structure/Makefile.am @@ -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 index 00000000..3505fabf --- /dev/null +++ b/simgear/structure/SGAtomic.cxx @@ -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(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(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 index 00000000..7bf8226f --- /dev/null +++ b/simgear/structure/SGAtomic.hxx @@ -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 +# define SGATOMIC_USE_WIN32_INTERLOCKED +#else +// The sledge hammer ... +# include +# include +#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(&mValue)); +#else + SGGuard 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(&mValue)); +#else + SGGuard 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(mValue); +#else + SGGuard 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 diff --git a/simgear/structure/SGReferenced.hxx b/simgear/structure/SGReferenced.hxx index 13f92995..6a3038f3 100644 --- a/simgear/structure/SGReferenced.hxx +++ b/simgear/structure/SGReferenced.hxx @@ -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