CDR_Base.inl

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // CDR_Base.inl,v 4.7 2005/10/28 16:14:51 ossama Exp
00004 
00005 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00006 
00007 //
00008 // The ACE_CDR::swap_X and ACE_CDR::swap_X_array routines are broken
00009 // in 4 cases for optimization:
00010 //
00011 // * AMD64 CPU + gnu g++
00012 //   => gcc amd64 inline assembly.
00013 //
00014 // * x86 Pentium CPU + gnu g++
00015 //   (ACE_HAS_PENTIUM && __GNUG__)
00016 //   => gcc x86 inline assembly.
00017 //
00018 // * x86 Pentium CPU and (_MSC_VER) or BORLAND C++)
00019 //   (ACE_HAS_PENTIUM && ( _MSC_VER || __BORLANDC__ )
00020 //   => MSC x86 inline assembly.
00021 //
00022 // * 64 bit architecture
00023 //   (ACE_SIZEOF_LONG == 8)
00024 //   => shift/masks using 64bit words.
00025 //
00026 // * default
00027 //   (none of the above)
00028 //   => shift/masks using 32bit words.
00029 //
00030 //
00031 // Some things you could find useful to know if you intend to mess
00032 // with this optimizations for swaps:
00033 //
00034 //      * MSVC++ don't assume register values are conserved between
00035 //        statements. So you can clobber any register you want,
00036 //        whenever you want (well not *anyone* really, see manual).
00037 //        The MSVC++ optimizer will try to pick different registers
00038 //        for the C++ statements sorrounding your asm block, and if
00039 //        it's not possible will use the stack.
00040 //
00041 //      * If you clobber registers with asm statements in gcc, you
00042 //        better do it in an asm-only function, or save/restore them
00043 //        before/after in the stack. If not, sorrounding C statements
00044 //        could end using the same registers and big-badda-bum (been
00045 //        there, done that...). The big-badda-bum could happen *even
00046 //        if you specify the clobbered register in your asm's*.
00047 //        Even better, use gcc asm syntax for detecting the register
00048 //        asigned to a certain variable so you don't have to clobber any
00049 //        register directly.
00050 //
00051 
00052 ACE_INLINE void
00053 ACE_CDR::swap_2 (const char *orig, char* target)
00054 {
00055 #if (defined(ACE_HAS_PENTIUM) || defined (__amd64__)) && defined(__GNUG__)
00056   unsigned short a =
00057     *reinterpret_cast<const unsigned short*> (orig);
00058   asm( "rolw $8, %0" : "=r" (a) : "0" (a) );
00059   *reinterpret_cast<unsigned short*> (target) = a;
00060 #elif defined (ACE_HAS_PENTIUM) \
00061        && (defined(_MSC_VER) || defined(__BORLANDC__)) \
00062        && !defined(ACE_LACKS_INLINE_ASSEMBLY)
00063   __asm mov ebx, orig;
00064   __asm mov ecx, target;
00065   __asm mov ax, [ebx];
00066   __asm rol ax, 8;
00067   __asm mov [ecx], ax;
00068 #else
00069   register ACE_UINT16 usrc = * reinterpret_cast<const ACE_UINT16*> (orig);
00070   register ACE_UINT16* udst = reinterpret_cast<ACE_UINT16*> (target);
00071   *udst = (usrc << 8) | (usrc >> 8);
00072 #endif /* ACE_HAS_PENTIUM */
00073 }
00074 
00075 ACE_INLINE void
00076 ACE_CDR::swap_4 (const char* orig, char* target)
00077 {
00078 #if (defined(ACE_HAS_PENTIUM) || defined (__amd64__)) && defined(__GNUG__)
00079   // We have ACE_HAS_PENTIUM, so we know the sizeof's.
00080   register unsigned int j =
00081     *reinterpret_cast<const unsigned int*> (orig);
00082   asm ("bswap %1" : "=r" (j) : "0" (j));
00083   *reinterpret_cast<unsigned int*> (target) = j;
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 eax, [ebx];
00090   __asm bswap eax;
00091   __asm mov [ecx], eax;
00092 #else
00093   register ACE_UINT32 x = * reinterpret_cast<const ACE_UINT32*> (orig);
00094   x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
00095   * reinterpret_cast<ACE_UINT32*> (target) = x;
00096 #endif
00097 }
00098 
00099 ACE_INLINE void
00100 ACE_CDR::swap_8 (const char* orig, char* target)
00101 {
00102 #if defined(__amd64__) && defined(__GNUG__)
00103   register unsigned long x =
00104     * reinterpret_cast<const unsigned long*> (orig);
00105   asm ("bswapq %1" : "=r" (x) : "0" (x));
00106   *reinterpret_cast<unsigned long*> (target) = x;
00107 #elif defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
00108   register unsigned int i =
00109     *reinterpret_cast<const unsigned int*> (orig);
00110   register unsigned int j =
00111     *reinterpret_cast<const unsigned int*> (orig + 4);
00112   asm ("bswap %1" : "=r" (i) : "0" (i));
00113   asm ("bswap %1" : "=r" (j) : "0" (j));
00114   *reinterpret_cast<unsigned int*> (target + 4) = i;
00115   *reinterpret_cast<unsigned int*> (target) = j;
00116 #elif defined(ACE_HAS_PENTIUM) \
00117       && (defined(_MSC_VER) || defined(__BORLANDC__)) \
00118       && !defined(ACE_LACKS_INLINE_ASSEMBLY)
00119   __asm mov ecx, orig;
00120   __asm mov edx, target;
00121   __asm mov eax, [ecx];
00122   __asm mov ebx, 4[ecx];
00123   __asm bswap eax;
00124   __asm bswap ebx;
00125   __asm mov 4[edx], eax;
00126   __asm mov [edx], ebx;
00127 #elif ACE_SIZEOF_LONG == 8
00128   // 64 bit architecture.
00129   register unsigned long x =
00130     * reinterpret_cast<const unsigned long*> (orig);
00131   register unsigned long x84 = (x & 0x000000ff000000ffUL) << 24;
00132   register unsigned long x73 = (x & 0x0000ff000000ff00UL) << 8;
00133   register unsigned long x62 = (x & 0x00ff000000ff0000UL) >> 8;
00134   register unsigned long x51 = (x & 0xff000000ff000000UL) >> 24;
00135   x = (x84 | x73 | x62 | x51);
00136   x = (x << 32) | (x >> 32);
00137   *reinterpret_cast<unsigned long*> (target) = x;
00138 #else
00139   register ACE_UINT32 x =
00140     * reinterpret_cast<const ACE_UINT32*> (orig);
00141   register ACE_UINT32 y =
00142     * reinterpret_cast<const ACE_UINT32*> (orig + 4);
00143   x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
00144   y = (y << 24) | ((y & 0xff00) << 8) | ((y & 0xff0000) >> 8) | (y >> 24);
00145   * reinterpret_cast<ACE_UINT32*> (target) = y;
00146   * reinterpret_cast<ACE_UINT32*> (target + 4) = x;
00147 #endif
00148 }
00149 
00150 ACE_INLINE void
00151 ACE_CDR::swap_16 (const char* orig, char* target)
00152 {
00153   swap_8 (orig + 8, target);
00154   swap_8 (orig, target + 8);
00155 }
00156 
00157 ACE_INLINE size_t
00158 ACE_CDR::first_size (size_t minsize)
00159 {
00160   if (minsize == 0)
00161     return ACE_CDR::DEFAULT_BUFSIZE;
00162 
00163   size_t newsize = ACE_CDR::DEFAULT_BUFSIZE;
00164   while (newsize < minsize)
00165     {
00166       if (newsize < ACE_CDR::EXP_GROWTH_MAX)
00167         {
00168           // We grow exponentially at the beginning, this is fast and
00169           // reduces the number of allocations.
00170           newsize *= 2;
00171         }
00172       else
00173         {
00174           // but continuing with exponential growth can result in over
00175           // allocations and easily yield an allocation failure.
00176           // So we grow linearly when the buffer is too big.
00177           newsize += ACE_CDR::LINEAR_GROWTH_CHUNK;
00178         }
00179     }
00180   return newsize;
00181 }
00182 
00183 ACE_INLINE size_t
00184 ACE_CDR::next_size (size_t minsize)
00185 {
00186   size_t newsize =
00187     ACE_CDR::first_size (minsize);
00188 
00189   if (newsize == minsize)
00190     {
00191       // If necessary increment the size
00192       if (newsize < ACE_CDR::EXP_GROWTH_MAX)
00193         newsize *= 2;
00194       else
00195         newsize += ACE_CDR::LINEAR_GROWTH_CHUNK;
00196     }
00197 
00198   return newsize;
00199 }
00200 
00201 ACE_END_VERSIONED_NAMESPACE_DECL
00202 
00203 // ****************************************************************

Generated on Thu Nov 9 09:41:48 2006 for ACE by doxygen 1.3.6