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 
00039 namespace drizzled {
00040 
00041 namespace internal {
00042 
00043 
00044 template<typename I>            // Primary template
00045 struct atomic_base {
00046   volatile I my_value;
00047   atomic_base() : my_value(0) {}
00048   virtual ~atomic_base() {}
00049 };
00050 
00051 template<typename I, typename D, typename T >
00052 class atomic_impl: private atomic_base<I>
00053 {
00054   T traits;
00055 public:
00056   typedef I value_type;
00057 
00058   atomic_impl() : atomic_base<I>(), traits() {}
00059 
00060   value_type add_and_fetch( D addend )
00061   {
00062     return traits.add_and_fetch(&this->my_value, addend);
00063   }
00064 
00065   value_type fetch_and_add( D addend )
00066   {
00067     return traits.fetch_and_add(&this->my_value, addend);
00068   }
00069 
00070   value_type fetch_and_increment()
00071   {
00072     return traits.fetch_and_increment(&this->my_value);
00073   }
00074 
00075   value_type fetch_and_decrement()
00076   {
00077     return traits.fetch_and_decrement(&this->my_value);
00078   }
00079 
00080   value_type fetch_and_store( value_type value )
00081   {
00082     return traits.fetch_and_store(&this->my_value, value);
00083   }
00084 
00085   bool compare_and_swap( value_type value, value_type comparand )
00086   {
00087     return traits.compare_and_swap(&this->my_value, value, comparand);
00088   }
00089 
00090   operator value_type() const volatile
00091   {
00092     return traits.fetch(&this->my_value);
00093   }
00094 
00095   value_type& _internal_reference() const
00096   {
00097     return this->my_value;
00098   }
00099 
00100 protected:
00101   value_type store_with_release( value_type rhs )
00102   {
00103     return traits.store_with_release(&this->my_value, rhs);
00104   }
00105 
00106 public:
00107   atomic_impl<I,D,T>& operator+=( D addend )
00108   {
00109     increment(addend);
00110     return *this;
00111   }
00112 
00113   atomic_impl<I,D,T>& operator-=( D addend )
00114   {
00115     // Additive inverse of addend computed using binary minus,
00116     // instead of unary minus, for sake of avoiding compiler warnings.
00117     return operator+=(D(0)-addend);
00118   }
00119 
00120   value_type increment()
00121   {
00122     return add_and_fetch(1);
00123   }
00124 
00125   value_type decrement()
00126   {
00127     return add_and_fetch(D(-1));
00128   }
00129 };
00130 
00131 } /* namespace internal */
00132 
00134 
00136 template<typename T>
00137 struct atomic {
00138 };
00139 
00140 /* *INDENT-OFF* */
00141 #define __DRIZZLE_DECL_ATOMIC(T)                                        \
00142   template<> struct atomic<T>                                           \
00143   : internal::atomic_impl<T,T,ATOMIC_TRAITS<T,T> > {                    \
00144     atomic<T>() : internal::atomic_impl<T,T,ATOMIC_TRAITS<T,T> >() {}   \
00145     atomic<T>& operator=( T rhs ) { store_with_release(rhs); return *this; } \
00146   };
00147 /* *INDENT-ON* */
00148 
00149 
00150 __DRIZZLE_DECL_ATOMIC(long)
00151 __DRIZZLE_DECL_ATOMIC(unsigned long)
00152 __DRIZZLE_DECL_ATOMIC(unsigned int)
00153 __DRIZZLE_DECL_ATOMIC(int)
00154 __DRIZZLE_DECL_ATOMIC(unsigned short)
00155 __DRIZZLE_DECL_ATOMIC(short)
00156 __DRIZZLE_DECL_ATOMIC(char)
00157 __DRIZZLE_DECL_ATOMIC(signed char)
00158 __DRIZZLE_DECL_ATOMIC(unsigned char)
00159 __DRIZZLE_DECL_ATOMIC(bool)
00160 
00161 /* 32-bit platforms don't have a GCC atomic operation for 64-bit types,
00162  * so we'll use pthread locks to handler 64-bit types on that platforms
00163  */
00164 /* *INDENT-OFF* */
00165 # if !defined(__ppc__) && (defined(_INT64_TYPE) || defined(_LP64))
00166 __DRIZZLE_DECL_ATOMIC(long long)
00167 __DRIZZLE_DECL_ATOMIC(unsigned long long)
00168 #  else
00169 #   define __DRIZZLE_DECL_ATOMIC64(T)                                   \
00170   template<> struct atomic<T>                                           \
00171   : internal::atomic_impl<T,T,internal::pthread_traits<T,T> > {         \
00172     atomic<T>()                                                         \
00173       : internal::atomic_impl<T,T,internal::pthread_traits<T,T> >() {}  \
00174     T operator=( T rhs ) { return store_with_release(rhs); }            \
00175   };
00176 __DRIZZLE_DECL_ATOMIC64(long long)
00177 __DRIZZLE_DECL_ATOMIC64(unsigned long long)
00178 #  endif
00179 /* *INDENT-ON* */
00180 
00181 }
00182