diff --git a/cpp/configure.in b/cpp/configure.in index 95635c3c..cc86cdfd 100644 --- a/cpp/configure.in +++ b/cpp/configure.in @@ -50,9 +50,7 @@ AC_CACHE_CHECK([for __sync_* atomic operations], msgpack_cv_atomic_ops, [ ], [], msgpack_cv_atomic_ops="yes") ]) if test "$msgpack_cv_atomic_ops" != "yes"; then - AC_MSG_ERROR([__sync_* atomic operations are not supported. - -Note that gcc < 4.1 is not supported. + AC_MSG_NOTICE([__sync_* atomic operations are not found. Use libstdc++ instead. If you are using gcc >= 4.1 and the default target CPU architecture is "i386", try to add CFLAGS="-march=i686" and CXXFLAGS="-march=i686" options to ./configure as follows: diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am index 0979d235..d96217a5 100644 --- a/cpp/src/Makefile.am +++ b/cpp/src/Makefile.am @@ -10,7 +10,8 @@ libmsgpack_la_SOURCES = \ if ENABLE_CXX libmsgpack_la_SOURCES += \ - object.cpp + object.cpp \ + gcc_atomic.cpp endif # -version-info CURRENT:REVISION:AGE diff --git a/cpp/src/gcc_atomic.cpp b/cpp/src/gcc_atomic.cpp new file mode 100644 index 00000000..599e832b --- /dev/null +++ b/cpp/src/gcc_atomic.cpp @@ -0,0 +1,17 @@ +#if defined(__GNUC__) && ((__GNUC__*10 + __GNUC_MINOR__) < 41) + +#include "gcc_atomic.h" +#include + +int _msgpack_sync_decr_and_fetch(volatile _msgpack_atomic_counter_t* ptr) +{ + return __gnu_cxx::__exchange_and_add(ptr, -1); +} + +int _msgpack_sync_incr_and_fetch(volatile _msgpack_atomic_counter_t* ptr) +{ + return __gnu_cxx::__exchange_and_add(ptr, 1); +} + + +#endif // old gcc workaround diff --git a/cpp/src/gcc_atomic.h b/cpp/src/gcc_atomic.h new file mode 100644 index 00000000..842a48fb --- /dev/null +++ b/cpp/src/gcc_atomic.h @@ -0,0 +1,33 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MSGPACK_GCC_ATOMIC_H__ +#define MSGPACK_GCC_ATOMIC_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef int _msgpack_atomic_counter_t; + +int _msgpack_sync_decr_and_fetch(volatile _msgpack_atomic_counter_t* ptr); +int _msgpack_sync_incr_and_fetch(volatile _msgpack_atomic_counter_t* ptr); + + +#if defined(__cplusplus) +} +#endif + + +#endif // MSGPACK_GCC_ATOMIC_H__ diff --git a/msgpack/sysdep.h b/msgpack/sysdep.h index 557c7cd6..1707e900 100644 --- a/msgpack/sysdep.h +++ b/msgpack/sysdep.h @@ -36,19 +36,19 @@ typedef unsigned __int64 uint64_t; #include #endif - #ifdef _WIN32 #define _msgpack_atomic_counter_header typedef long _msgpack_atomic_counter_t; #define _msgpack_sync_decr_and_fetch(ptr) InterlockedDecrement(ptr) #define _msgpack_sync_incr_and_fetch(ptr) InterlockedIncrement(ptr) +#elif defined(__GNUC__) && ((__GNUC__*10 + __GNUC_MINOR__) < 41) +#define _msgpack_atomic_counter_header "gcc_atomic.h" #else typedef unsigned int _msgpack_atomic_counter_t; #define _msgpack_sync_decr_and_fetch(ptr) __sync_sub_and_fetch(ptr, 1) #define _msgpack_sync_incr_and_fetch(ptr) __sync_add_and_fetch(ptr, 1) #endif - #ifdef _WIN32 #ifdef __cplusplus