Drizzled Public API Documentation

atomics.h
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2009 Sun Microsystems, Inc.
00005  *  Copyright 2005-2008 Intel Corporation.  All Rights Reserved.
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; version 2 of the License.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #pragma once
00022 
00023 # if defined(__SUNPRO_CC)
00024 #  include <drizzled/atomic/sun_studio.h>
00025 # endif
00026 # if !defined(__ICC) && !defined(__clang__) && (defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(__SUNPRO_CC))
00027 #  include <drizzled/atomic/gcc_traits.h>
00028 #  define ATOMIC_TRAITS internal::gcc_traits
00029 # else  /* use pthread impl */
00030 #  define ATOMIC_TRAITS internal::pthread_traits
00031 # endif
00032 
00033 # if (SIZEOF_SIZE_T >= SIZEOF_LONG_LONG) || (!defined(HAVE_GCC_ATOMIC_BUILTINS) || !defined(__SUNPRO_CC)) || defined(__ppc__)
00034 #  include <pthread.h>
00035 #  include <drizzled/atomic/pthread_traits.h>
00036 # endif
00037 
00038 namespace drizzled {
00039 namespace internal {
00040 
00041 template<typename I>            // Primary template
00042 struct atomic_base {
00043   volatile I my_value;
00044   atomic_base() : my_value(0) {}
00045   virtual ~atomic_base() {}
00046 };
00047 
00048 template<typename I, typename D, typename T >
00049 class atomic_impl: private atomic_base<I>
00050 {
00051   T traits;
00052 public:
00053   typedef I value_type;
00054 
00055   atomic_impl() : atomic_base<I>(), traits() {}
00056 
00057   value_type add_and_fetch( D addend )
00058   {
00059     return traits.add_and_fetch(&this->my_value, addend);
00060   }
00061 
00062   value_type fetch_and_add( D addend )
00063   {
00064     return traits.fetch_and_add(&this->my_value, addend);
00065   }
00066 
00067   value_type fetch_and_increment()
00068   {
00069     return traits.fetch_and_increment(&this->my_value);
00070   }
00071 
00072   value_type fetch_and_decrement()
00073   {
00074     return traits.fetch_and_decrement(&this->my_value);
00075   }
00076 
00077   value_type fetch_and_store( value_type value )
00078   {
00079     return traits.fetch_and_store(&this->my_value, value);
00080   }
00081 
00082   bool compare_and_swap( value_type value, value_type comparand )
00083   {
00084     return traits.compare_and_swap(&this->my_value, value, comparand);
00085   }
00086 
00087   operator value_type() const volatile
00088   {
00089     return traits.fetch(&this->my_value);
00090   }
00091 
00092   value_type& _internal_reference() const
00093   {
00094     return this->my_value;
00095   }
00096 
00097 protected:
00098   value_type store_with_release( value_type rhs )
00099   {
00100     return traits.store_with_release(&this->my_value, rhs);
00101   }
00102 
00103 public:
00104   atomic_impl<I,D,T>& operator+=( D addend )
00105   {
00106     increment(addend);
00107     return *this;
00108   }
00109 
00110   atomic_impl<I,D,T>& operator-=( D addend )
00111   {
00112     // Additive inverse of addend computed using binary minus,
00113     // instead of unary minus, for sake of avoiding compiler warnings.
00114     return operator+=(D(0)-addend);
00115   }
00116 
00117   value_type increment()
00118   {
00119     return add_and_fetch(1);
00120   }
00121 
00122   value_type decrement()
00123   {
00124     return add_and_fetch(D(-1));
00125   }
00126 };
00127 
00128 } /* namespace internal */
00129 
00131 
00133 template<typename T>
00134 struct atomic {
00135 };
00136 
00137 /* *INDENT-OFF* */
00138 #define __DRIZZLE_DECL_ATOMIC(T)                                        \
00139   template<> struct atomic<T>                                           \
00140   : internal::atomic_impl<T,T,ATOMIC_TRAITS<T,T> > {                    \
00141     atomic<T>() : internal::atomic_impl<T,T,ATOMIC_TRAITS<T,T> >() {}   \
00142     atomic<T>& operator=( T rhs ) { store_with_release(rhs); return *this; } \
00143   };
00144 /* *INDENT-ON* */
00145 
00146 
00147 __DRIZZLE_DECL_ATOMIC(long)
00148 __DRIZZLE_DECL_ATOMIC(unsigned long)
00149 __DRIZZLE_DECL_ATOMIC(unsigned int)
00150 __DRIZZLE_DECL_ATOMIC(int)
00151 __DRIZZLE_DECL_ATOMIC(unsigned short)
00152 __DRIZZLE_DECL_ATOMIC(short)
00153 __DRIZZLE_DECL_ATOMIC(char)
00154 __DRIZZLE_DECL_ATOMIC(signed char)
00155 __DRIZZLE_DECL_ATOMIC(unsigned char)
00156 __DRIZZLE_DECL_ATOMIC(bool)
00157 
00158 /* 32-bit platforms don't have a GCC atomic operation for 64-bit types,
00159  * so we'll use pthread locks to handler 64-bit types on that platforms
00160  */
00161 /* *INDENT-OFF* */
00162 # if !defined(__ppc__) && (defined(_INT64_TYPE) || defined(_LP64))
00163 __DRIZZLE_DECL_ATOMIC(long long)
00164 __DRIZZLE_DECL_ATOMIC(unsigned long long)
00165 #  else
00166 #   define __DRIZZLE_DECL_ATOMIC64(T)                                   \
00167   template<> struct atomic<T>                                           \
00168   : internal::atomic_impl<T,T,internal::pthread_traits<T,T> > {         \
00169     atomic<T>()                                                         \
00170       : internal::atomic_impl<T,T,internal::pthread_traits<T,T> >() {}  \
00171     T operator=( T rhs ) { return store_with_release(rhs); }            \
00172   };
00173 __DRIZZLE_DECL_ATOMIC64(long long)
00174 __DRIZZLE_DECL_ATOMIC64(unsigned long long)
00175 #  endif
00176 /* *INDENT-ON* */
00177 
00178 }
00179