CDR_Base.inl

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // $Id: CDR_Base.inl 80826 2008-03-04 14:51:23Z wotte $
00004 
00005 #if defined (ACE_HAS_INTRINSIC_BYTESWAP)
00006 // Take advantage of MSVC++ byte swapping compiler intrinsics (found
00007 // in <stdlib.h>).
00008 # pragma intrinsic (_byteswap_ushort, _byteswap_ulong, _byteswap_uint64)
00009 #endif  /* ACE_HAS_INTRINSIC_BYTESWAP */
00010 
00011 #if defined (ACE_HAS_BSWAP_16) || defined (ACE_HAS_BSWAP_32) || defined (ACE_HAS_BSWAP_64)
00012 # include "ace/os_include/os_byteswap.h"
00013 #endif
00014 
00015 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00016 
00017 //
00018 // The ACE_CDR::swap_X and ACE_CDR::swap_X_array routines are broken
00019 // in 5 cases for optimization:
00020 //
00021 // * MSVC++ 7.1 or better
00022 //   => Compiler intrinsics
00023 //
00024 // * AMD64 CPU + gnu g++
00025 //   => gcc amd64 inline assembly.
00026 //
00027 // * x86 Pentium CPU + gnu g++
00028 //   (ACE_HAS_PENTIUM && __GNUG__)
00029 //   => gcc x86 inline assembly.
00030 //
00031 // * x86 Pentium CPU and (_MSC_VER) or BORLAND C++)
00032 //   (ACE_HAS_PENTIUM && ( _MSC_VER || __BORLANDC__ )
00033 //   => MSC x86 inline assembly.
00034 //
00035 // * 64 bit architecture
00036 //   (ACE_SIZEOF_LONG == 8)
00037 //   => shift/masks using 64bit words.
00038 //
00039 // * default
00040 //   (none of the above)
00041 //   => shift/masks using 32bit words.
00042 //
00043 //
00044 // Some things you could find useful to know if you intend to mess
00045 // with this optimizations for swaps:
00046 //
00047 //      * MSVC++ don't assume register values are conserved between
00048 //        statements. So you can clobber any register you want,
00049 //        whenever you want (well not *anyone* really, see manual).
00050 //        The MSVC++ optimizer will try to pick different registers
00051 //        for the C++ statements sorrounding your asm block, and if
00052 //        it's not possible will use the stack.
00053 //
00054 //      * If you clobber registers with asm statements in gcc, you
00055 //        better do it in an asm-only function, or save/restore them
00056 //        before/after in the stack. If not, sorrounding C statements
00057 //        could end using the same registers and big-badda-bum (been
00058 //        there, done that...). The big-badda-bum could happen *even
00059 //        if you specify the clobbered register in your asm's*.
00060 //        Even better, use gcc asm syntax for detecting the register
00061 //        asigned to a certain variable so you don't have to clobber any
00062 //        register directly.
00063 //
00064 
00065 ACE_INLINE void
00066 ACE_CDR::swap_2 (const char *orig, char* target)
00067 {
00068 #if defined (ACE_HAS_INTRINSIC_BYTESWAP)
00069   // Take advantage of MSVC++ compiler intrinsic byte swapping
00070   // function.
00071   *reinterpret_cast<unsigned short *> (target) =
00072     _byteswap_ushort (*reinterpret_cast<unsigned short const *> (orig));
00073 #elif defined (ACE_HAS_BSWAP16)
00074   *reinterpret_cast<uint16_t *> (target) =
00075     bswap16 (*reinterpret_cast<uint16_t const *> (orig));
00076 #elif defined (ACE_HAS_BSWAP_16)
00077   *reinterpret_cast<uint16_t *> (target) =
00078     bswap_16 (*reinterpret_cast<uint16_t const *> (orig));
00079 #elif defined(ACE_HAS_INTEL_ASSEMBLY)
00080   unsigned short a =
00081     *reinterpret_cast<const unsigned short*> (orig);
00082   asm( "rolw $8, %0" : "=r" (a) : "0" (a) );
00083   *reinterpret_cast<unsigned short*> (target) = a;
00084 #elif defined (ACE_HAS_PENTIUM) \
00085        && (defined(_MSC_VER) || defined(__BORLANDC__)) \
00086        && !defined(ACE_LACKS_INLINE_ASSEMBLY)
00087   __asm mov ebx, orig;
00088   __asm mov ecx, target;
00089   __asm mov ax, [ebx];
00090   __asm rol ax, 8;
00091   __asm mov [ecx], ax;
00092 #else
00093   register ACE_UINT16 usrc = * reinterpret_cast<const ACE_UINT16*> (orig);
00094   register ACE_UINT16* udst = reinterpret_cast<ACE_UINT16*> (target);
00095   *udst = (usrc << 8) | (usrc >> 8);
00096 #endif /* ACE_HAS_PENTIUM */
00097 }
00098 
00099 ACE_INLINE void
00100 ACE_CDR::swap_4 (const char* orig, char* target)
00101 {
00102 #if defined (ACE_HAS_INTRINSIC_BYTESWAP)
00103   // Take advantage of MSVC++ compiler intrinsic byte swapping
00104   // function.
00105   *reinterpret_cast<unsigned long *> (target) =
00106     _byteswap_ulong (*reinterpret_cast<unsigned long const *> (orig));
00107 #elif defined (ACE_HAS_BSWAP32)
00108   *reinterpret_cast<uint32_t *> (target) =
00109     bswap32 (*reinterpret_cast<uint32_t const *> (orig));
00110 #elif defined (ACE_HAS_BSWAP_32)
00111   *reinterpret_cast<uint32_t *> (target) =
00112     bswap_32 (*reinterpret_cast<uint32_t const *> (orig));
00113 #elif defined(ACE_HAS_INTEL_ASSEMBLY)
00114   // We have ACE_HAS_PENTIUM, so we know the sizeof's.
00115   register unsigned int j =
00116     *reinterpret_cast<const unsigned int*> (orig);
00117   asm ("bswap %1" : "=r" (j) : "0" (j));
00118   *reinterpret_cast<unsigned int*> (target) = j;
00119 #elif defined(ACE_HAS_PENTIUM) \
00120       && (defined(_MSC_VER) || defined(__BORLANDC__)) \
00121       && !defined(ACE_LACKS_INLINE_ASSEMBLY)
00122   __asm mov ebx, orig;
00123   __asm mov ecx, target;
00124   __asm mov eax, [ebx];
00125   __asm bswap eax;
00126   __asm mov [ecx], eax;
00127 #else
00128   register ACE_UINT32 x = * reinterpret_cast<const ACE_UINT32*> (orig);
00129   x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
00130   * reinterpret_cast<ACE_UINT32*> (target) = x;
00131 #endif /* ACE_HAS_INTRINSIC_BYTESWAP */
00132 }
00133 
00134 ACE_INLINE void
00135 ACE_CDR::swap_8 (const char* orig, char* target)
00136 {
00137 #if defined (ACE_HAS_INTRINSIC_BYTESWAP)
00138   // Take advantage of MSVC++ compiler intrinsic byte swapping
00139   // function.
00140   *reinterpret_cast<unsigned __int64 *> (target) =
00141     _byteswap_uint64 (*reinterpret_cast<unsigned __int64 const *> (orig));
00142 #elif defined (ACE_HAS_BSWAP64)
00143   *reinterpret_cast<uint64_t *> (target) =
00144     bswap64 (*reinterpret_cast<uint64_t const *> (orig));
00145 #elif defined (ACE_HAS_BSWAP_64)
00146   *reinterpret_cast<uint64_t *> (target) =
00147     bswap_64 (*reinterpret_cast<uint64_t const *> (orig));
00148 #elif (defined (__amd64__) || defined (__x86_64__)) && defined(__GNUG__)
00149   register unsigned long x =
00150     * reinterpret_cast<const unsigned long*> (orig);
00151   asm ("bswapq %1" : "=r" (x) : "0" (x));
00152   *reinterpret_cast<unsigned long*> (target) = x;
00153 #elif defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
00154   register unsigned int i =
00155     *reinterpret_cast<const unsigned int*> (orig);
00156   register unsigned int j =
00157     *reinterpret_cast<const unsigned int*> (orig + 4);
00158   asm ("bswap %1" : "=r" (i) : "0" (i));
00159   asm ("bswap %1" : "=r" (j) : "0" (j));
00160   *reinterpret_cast<unsigned int*> (target + 4) = i;
00161   *reinterpret_cast<unsigned int*> (target) = j;
00162 #elif defined(ACE_HAS_PENTIUM) \
00163       && (defined(_MSC_VER) || defined(__BORLANDC__)) \
00164       && !defined(ACE_LACKS_INLINE_ASSEMBLY)
00165   __asm mov ecx, orig;
00166   __asm mov edx, target;
00167   __asm mov eax, [ecx];
00168   __asm mov ebx, 4[ecx];
00169   __asm bswap eax;
00170   __asm bswap ebx;
00171   __asm mov 4[edx], eax;
00172   __asm mov [edx], ebx;
00173 #elif ACE_SIZEOF_LONG == 8
00174   // 64 bit architecture.
00175   register unsigned long x =
00176     * reinterpret_cast<const unsigned long*> (orig);
00177   register unsigned long x84 = (x & 0x000000ff000000ffUL) << 24;
00178   register unsigned long x73 = (x & 0x0000ff000000ff00UL) << 8;
00179   register unsigned long x62 = (x & 0x00ff000000ff0000UL) >> 8;
00180   register unsigned long x51 = (x & 0xff000000ff000000UL) >> 24;
00181   x = (x84 | x73 | x62 | x51);
00182   x = (x << 32) | (x >> 32);
00183   *reinterpret_cast<unsigned long*> (target) = x;
00184 #else
00185   register ACE_UINT32 x =
00186     * reinterpret_cast<const ACE_UINT32*> (orig);
00187   register ACE_UINT32 y =
00188     * reinterpret_cast<const ACE_UINT32*> (orig + 4);
00189   x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
00190   y = (y << 24) | ((y & 0xff00) << 8) | ((y & 0xff0000) >> 8) | (y >> 24);
00191   * reinterpret_cast<ACE_UINT32*> (target) = y;
00192   * reinterpret_cast<ACE_UINT32*> (target + 4) = x;
00193 #endif /* ACE_HAS_INTRINSIC_BYTESWAP */
00194 }
00195 
00196 ACE_INLINE void
00197 ACE_CDR::swap_16 (const char* orig, char* target)
00198 {
00199   swap_8 (orig + 8, target);
00200   swap_8 (orig, target + 8);
00201 }
00202 
00203 ACE_INLINE size_t
00204 ACE_CDR::first_size (size_t minsize)
00205 {
00206   if (minsize == 0)
00207     return ACE_CDR::DEFAULT_BUFSIZE;
00208 
00209   size_t newsize = ACE_CDR::DEFAULT_BUFSIZE;
00210   while (newsize < minsize)
00211     {
00212       if (newsize < ACE_CDR::EXP_GROWTH_MAX)
00213         {
00214           // We grow exponentially at the beginning, this is fast and
00215           // reduces the number of allocations.
00216 
00217           // Quickly multiply by two using a bit shift.  This is
00218           // guaranteed to work since the variable is an unsigned
00219           // integer.
00220           newsize <<= 1;
00221         }
00222       else
00223         {
00224           // but continuing with exponential growth can result in over
00225           // allocations and easily yield an allocation failure.
00226           // So we grow linearly when the buffer is too big.
00227           newsize += ACE_CDR::LINEAR_GROWTH_CHUNK;
00228         }
00229     }
00230   return newsize;
00231 }
00232 
00233 ACE_INLINE size_t
00234 ACE_CDR::next_size (size_t minsize)
00235 {
00236   size_t newsize = ACE_CDR::first_size (minsize);
00237 
00238   if (newsize == minsize)
00239     {
00240       // If necessary increment the size
00241       if (newsize < ACE_CDR::EXP_GROWTH_MAX)
00242         // Quickly multiply by two using a bit shift.  This is
00243         // guaranteed to work since the variable is an unsigned
00244         // integer.
00245         newsize <<= 1;
00246       else
00247         newsize += ACE_CDR::LINEAR_GROWTH_CHUNK;
00248     }
00249 
00250   return newsize;
00251 }
00252 
00253 ACE_END_VERSIONED_NAMESPACE_DECL
00254 
00255 // ****************************************************************

Generated on Tue Feb 2 17:18:38 2010 for ACE by  doxygen 1.4.7