library of assembled shared sources

http://lass.cocamware.com

atomic_impl.h

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 #include "../../num/basic_types.h"
00044 
00045 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
00046 #   pragma warning(push)
00047 #   pragma warning(disable: 4035)
00048 #endif
00049 
00050 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC && (LASS_ADDRESS_SIZE == 64)
00051 #   define LASS_UTIL_IMPL_ATOMIC_MSVC_X64
00052 #   include <intrin.h>
00053 #   pragma intrinsic(_InterlockedCompareExchange)
00054 #   pragma intrinsic(_InterlockedCompareExchange16)
00055 #   pragma intrinsic(_InterlockedCompareExchange64)
00056 #   pragma intrinsic(_InterlockedIncrement)
00057 #   pragma intrinsic(_InterlockedIncrement16)
00058 #   pragma intrinsic(_InterlockedIncrement64)
00059 #   pragma intrinsic(_InterlockedDecrement)
00060 #   pragma intrinsic(_InterlockedDecrement16)
00061 #   pragma intrinsic(_InterlockedDecrement64)
00062 #   pragma intrinsic(__ll_rshift)
00063 
00064 extern "C"
00065 {
00066     lass::num::Tuint8 lass_cas8(volatile lass::num::Tuint8*, lass::num::Tuint8, lass::num::Tuint8);
00067     void lass_inc8(volatile lass::num::Tuint8*);
00068     void lass_dec8(volatile lass::num::Tuint8*);
00069     bool lass_dcas8(volatile lass::num::Tuint8*, lass::num::Tuint8, lass::num::Tuint8, lass::num::Tuint8, lass::num::Tuint8);
00070     bool lass_dcas16(volatile lass::num::Tuint16*, lass::num::Tuint16, lass::num::Tuint16, lass::num::Tuint16, lass::num::Tuint16);
00071     bool lass_dcas32(volatile lass::num::Tuint32*, lass::num::Tuint32, lass::num::Tuint32, lass::num::Tuint32, lass::num::Tuint32);
00072 }
00073 
00074 #endif
00075 
00076 namespace lass
00077 {
00078 namespace util
00079 {
00080 
00081 namespace impl
00082 {
00083 
00084 /** @ingroup atomic
00085  *  @internal 
00086  */
00087 template <int byteSize> struct AtomicOperations;
00088 
00089 /** @ingroup atomic
00090  *  @internal 
00091  */
00092 template <>
00093 struct AtomicOperations<1>
00094 {
00095     template <typename T> inline 
00096     static T LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
00097     {
00098 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00099         __asm__ __volatile__(
00100             "lock; cmpxchgb %2, %0;"
00101             : "=m"(dest), "=a"(expectedValue)
00102             : "q"(newValue), "1"(expectedValue), "m"(dest)
00103             : "cc", "memory");
00104         return expectedValue;
00105 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00106         __asm 
00107         {
00108             mov al, expectedValue
00109             mov dl, newValue
00110             mov edi, dest
00111             lock cmpxchg [edi], dl
00112         }
00113         /* return eax */
00114 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00115         return lass_cas8(reinterpret_cast<volatile num::Tuint8*>(&dest), 
00116             *reinterpret_cast<num::Tuint8*>(&newValue), *reinterpret_cast<num::Tuint8*>(&expectedValue));
00117 #else
00118 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00119 #endif
00120     }
00121 
00122     template <typename T1, typename T2> inline 
00123     static bool LASS_CALL compareAndSwap(
00124             volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
00125     {
00126 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00127         bool result;
00128         __asm__ __volatile__(
00129             "movb %%bl, %%ah;"
00130             "movb %%cl, %%dh;"
00131             "lock; cmpxchgw %%dx, %0;"
00132             "sete %1;"
00133             : "=m"(reinterpret_cast<volatile num::Tuint16&>(dest1)), "=q"(result)
00134             : "a"(expected1), "d"(new1), "b"(expected2), "c"(new2), 
00135               "m"(reinterpret_cast<volatile num::Tuint16&>(dest1))
00136             : "cc", "memory");
00137         return result;      
00138 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00139         __asm 
00140         {
00141             mov al, expected1
00142             mov dl, new1
00143             mov ah, expected2
00144             mov dh, new2
00145             mov edi, dest1
00146             lock cmpxchg [edi], dx
00147             mov eax, 0
00148             sete al
00149         }
00150         /* return eax */
00151 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00152         return lass_dcas8(
00153             reinterpret_cast<volatile num::Tuint8*>(&dest1), 
00154             *reinterpret_cast<num::Tuint8*>(&new1), *reinterpret_cast<num::Tuint8*>(&new2), 
00155             *reinterpret_cast<num::Tuint8*>(&expected1), *reinterpret_cast<num::Tuint8*>(&expected2));
00156 #else
00157 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00158 #endif
00159     }
00160 
00161     template <typename T> inline
00162     static void LASS_CALL increment(volatile T& value)
00163     {
00164 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00165         __asm__ __volatile__(
00166             "lock; incb %0;"
00167             : "=m"(value)
00168             : "m"(value)
00169             : "cc", "memory");
00170 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00171         __asm 
00172         {
00173             mov edi, value
00174             lock inc byte ptr [edi]
00175         }
00176 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00177         lass_inc8(reinterpret_cast<volatile num::Tuint8*>(&value));
00178 #else
00179 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00180 #endif      
00181     }
00182 
00183     template <typename T> inline
00184     static void LASS_CALL decrement(volatile T& value)
00185     {
00186 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00187         __asm__ __volatile__(
00188             "lock; decb %0;"
00189             : "=m"(value)
00190             : "m"(value)
00191             : "cc", "memory");
00192 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00193         __asm 
00194         {
00195             mov edi, value
00196             lock dec byte ptr [edi]
00197         }
00198 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00199         lass_dec8(reinterpret_cast<volatile num::Tuint8*>(&value));
00200 #else
00201 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00202 #endif
00203     }
00204 };
00205 
00206 
00207 
00208 
00209 // -------------------------------------------------------------------------------------------------
00210 
00211 /** @ingroup atomic
00212  *  @internal 
00213  */
00214 template <>
00215 struct AtomicOperations<2>
00216 {
00217     template <typename T> inline 
00218     static T LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
00219     {
00220 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00221         __asm__ __volatile__(
00222             "lock; cmpxchgw %2, %0;"
00223             : "=m"(dest), "=a"(expectedValue)
00224             : "q"(newValue), "1"(expectedValue), "m"(dest)
00225             : "cc", "memory");
00226         return expectedValue;
00227 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00228         __asm 
00229         {
00230             mov ax, expectedValue
00231             mov dx, newValue
00232             mov edi, dest
00233             lock cmpxchg [edi], dx
00234         }
00235         /* return eax */
00236 
00237 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00238         return _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(&dest), 
00239             *reinterpret_cast<short*>(&newValue), *reinterpret_cast<short*>(&expectedValue));
00240 #else
00241 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00242 #endif
00243     }
00244 
00245     template <typename T1, typename T2> inline 
00246     static bool LASS_CALL compareAndSwap(
00247             volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
00248     {
00249 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00250         bool result;
00251         __asm__ __volatile__(
00252             "shll $16, %%eax;"
00253             "shll $16, %%edx;"
00254             "movw %4, %%ax;"
00255             "movw %5, %%dx;"
00256             "lock; cmpxchgl %%edx, %0;"
00257             "sete %1;"
00258             : "=m"(reinterpret_cast<volatile num::Tuint32&>(dest1)), "=q"(result)
00259             : "a"(expected2), "d"(new2), "g"(expected1), "g"(new1),
00260               "m"(reinterpret_cast<volatile num::Tuint32&>(dest1))
00261             : "cc", "memory");
00262         return result;  
00263 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00264         __asm 
00265         {
00266             mov ax, expected2
00267             mov dx, new2
00268             shl eax, 16
00269             shl edx, 16
00270             mov ax, expected1
00271             mov dx, new1
00272             mov edi, dest1
00273             lock cmpxchg [edi], edx
00274             mov eax, 0
00275             sete al
00276         }
00277         /* return eax */    
00278 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00279         return lass_dcas16(
00280             reinterpret_cast<volatile num::Tuint16*>(&dest1), 
00281             *reinterpret_cast<num::Tuint16*>(&new1), *reinterpret_cast<num::Tuint16*>(&new2), 
00282             *reinterpret_cast<num::Tuint16*>(&expected1), *reinterpret_cast<num::Tuint16*>(&expected2));
00283 #else
00284 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00285 #endif
00286     }
00287 
00288     template <typename T> inline
00289     static void LASS_CALL increment(volatile T& value)
00290     {
00291 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00292         __asm__ __volatile__(
00293             "lock; incw %0;"
00294             : "=m"(value)
00295             : "m"(value)
00296             : "cc", "memory");
00297 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00298         __asm 
00299         {
00300             mov edi, value
00301             lock inc word ptr [edi]
00302         }
00303 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00304         _InterlockedIncrement16(reinterpret_cast<volatile short*>(&value));
00305 #else
00306 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00307 #endif      
00308     }
00309 
00310     template <typename T> inline
00311     static void LASS_CALL decrement(volatile T& value)
00312     {
00313 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00314         __asm__ __volatile__(
00315             "lock; decw %0;"
00316             : "=m"(value)
00317             : "m"(value)
00318             : "cc", "memory");
00319 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00320         __asm 
00321         {
00322             mov edi, value
00323             lock dec word ptr [edi]
00324         }
00325 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00326         _InterlockedDecrement16(reinterpret_cast<volatile short*>(&value));
00327 #else
00328 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00329 #endif
00330     }
00331 };
00332 
00333 
00334 
00335 // -------------------------------------------------------------------------------------------------
00336 
00337 /** @ingroup atomic
00338  *  @internal 
00339  */
00340 template <>
00341 struct AtomicOperations<4>
00342 {
00343     template <typename T> inline 
00344     static T LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
00345     {
00346 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00347         __asm__ __volatile__(
00348             "lock; cmpxchgl %2, %0;"
00349             : "=m"(dest), "=a"(expectedValue)
00350             : "q"(newValue), "1"(expectedValue), "m"(dest)
00351             : "cc", "memory");
00352         return expectedValue;
00353 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00354         __asm 
00355         {
00356             mov eax, expectedValue
00357             mov edx, newValue
00358             mov edi, dest
00359             lock cmpxchg [edi], edx
00360         }
00361         /* return eax */
00362 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00363         return _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&dest), 
00364             *reinterpret_cast<long*>(&newValue), *reinterpret_cast<long*>(&expectedValue));
00365 #else
00366 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00367 #endif
00368     }
00369 
00370     template <typename T1, typename T2> inline 
00371     static bool LASS_CALL compareAndSwap(
00372             volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
00373     {
00374 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00375         bool result;
00376 
00377         // cmpxchg8b and PIC mode don't play nice.  Push ebx before use!
00378         // see http://www.technovelty.org/code/arch/pic-cas.html
00379         //
00380 #   ifdef __PIC__
00381         __asm__ __volatile__(
00382             "pushl %%ebx;"
00383             "movl %4,%%ebx;"
00384             "lock; cmpxchg8b %0;"
00385             "sete %1;"
00386             "pop %%ebx;"
00387             : "=m"(dest1), "=q"(result)
00388             : "a"(expected1), "d"(expected2), "m"(new1), "c"(new2), "m"(dest1)
00389             : "cc", "memory");
00390 #   else
00391         __asm__ __volatile__(
00392             "lock; cmpxchg8b %0;"
00393             "sete %1;"
00394             : "=m"(dest1), "=q"(result)
00395             : "a"(expected1), "d"(expected2), "b"(new1), "c"(new2), "m"(dest1)
00396             : "cc", "memory");
00397 #   endif
00398         return result;
00399 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00400         __asm 
00401         {
00402             mov eax, expected1
00403             mov edx, expected2
00404             mov ebx, new1
00405             mov ecx, new2
00406             mov edi, dest1
00407             lock cmpxchg8b [edi]
00408             mov eax, 0
00409             sete al
00410         }
00411         /* return eax */
00412 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00413         return lass_dcas32(
00414             reinterpret_cast<volatile num::Tuint32*>(&dest1), 
00415             *reinterpret_cast<num::Tuint32*>(&new1), *reinterpret_cast<num::Tuint32*>(&new2), 
00416             *reinterpret_cast<num::Tuint32*>(&expected1), *reinterpret_cast<num::Tuint32*>(&expected2));
00417 #else
00418 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00419 #endif
00420     }
00421 
00422     template <typename T> inline
00423     static void LASS_CALL increment(volatile T& value)
00424     {
00425 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00426         __asm__ __volatile__(
00427             "lock; incl %0;"
00428             : "=m"(value)
00429             : "m"(value)
00430             : "cc", "memory");
00431 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00432         __asm 
00433         {
00434             mov edi, value
00435             lock inc dword ptr [edi]
00436         }
00437 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00438         _InterlockedIncrement(reinterpret_cast<volatile long*>(&value));
00439 #else
00440 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00441 #endif      
00442     }
00443 
00444     template <typename T> inline
00445     static void LASS_CALL decrement(volatile T& value)
00446     {
00447 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00448         __asm__ __volatile__(
00449             "lock; decl %0;"
00450             : "=m"(value)
00451             : "m"(value)
00452             : "cc", "memory");
00453 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00454         __asm 
00455         {
00456             mov edi, value
00457             lock dec dword ptr [edi]
00458         }
00459 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00460         _InterlockedDecrement(reinterpret_cast<volatile long*>(&value));
00461 #else
00462 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00463 #endif
00464     }
00465 };
00466 
00467 
00468 
00469 // -------------------------------------------------------------------------------------------------
00470 
00471 /** @ingroup atomic
00472  *  @internal 
00473  */
00474 template <>
00475 struct AtomicOperations<8>
00476 {
00477     template <typename T> inline 
00478     static T LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
00479     {
00480 #if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC) && (LASS_ADDRESS_SIZE == 32)
00481         // cmpxchg8b and PIC mode don't play nice.  Push ebx before use!
00482         // see http://www.technovelty.org/code/arch/pic-cas.html
00483         //
00484 #   ifdef __PIC__
00485         __asm__ __volatile__(
00486             "pushl %%ebx;"
00487             "movl %5,%%ebx;"
00488             "lock; cmpxchg8b %0;"
00489             "pop %%ebx;"
00490             : "=m"(dest), "=A"(expectedValue)
00491             : "m"(dest),
00492               "a"(reinterpret_cast<volatile num::Tuint32*>((void*)&expectedValue)[0]), 
00493               "d"(reinterpret_cast<volatile num::Tuint32*>((void*)&expectedValue)[1]),  
00494               "m"(reinterpret_cast<volatile num::Tuint32*>((void*)&newValue)[0]), 
00495               "c"(reinterpret_cast<volatile num::Tuint32*>((void*)&newValue)[1])    
00496             : "cc", "memory");
00497 #   else
00498         __asm__ __volatile__(
00499             "lock; cmpxchg8b %0;"
00500             : "=m"(dest), "=A"(expectedValue)
00501             : "m"(dest),
00502               "a"(reinterpret_cast<volatile num::Tuint32*>((void*)&expectedValue)[0]), 
00503               "d"(reinterpret_cast<volatile num::Tuint32*>((void*)&expectedValue)[1]),  
00504               "b"(reinterpret_cast<volatile num::Tuint32*>((void*)&newValue)[0]), 
00505               "c"(reinterpret_cast<volatile num::Tuint32*>((void*)&newValue)[1])    
00506             : "cc", "memory");
00507 #   endif
00508         return expectedValue;
00509 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_GCC) && (LASS_ADDRESS_SIZE == 64)
00510         __asm__ __volatile__(
00511             "lock; cmpxchgq %2, %0;"
00512             : "=m"(dest), "=a"(expectedValue)
00513             : "q"(newValue), "1"(expectedValue), "m"(dest)
00514             : "cc", "memory");
00515         return expectedValue;
00516 #elif defined(LASS_HAVE_INLINE_ASSEMBLY_MSVC) && (LASS_ADDRESS_SIZE == 32)
00517         __asm 
00518         {
00519             lea esi, expectedValue
00520             lea edi, newValue
00521             mov eax, [esi]
00522             mov edx, 4[esi]
00523             mov ebx, [edi]
00524             mov ecx, 4[edi]
00525             mov edi, dest
00526             lock cmpxchg8b [edi]
00527         }
00528         /* return edx:eax */
00529 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00530     return _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(&dest), 
00531         *reinterpret_cast<__int64*>(&newValue), *reinterpret_cast<__int64*>(&expectedValue));
00532 #else
00533 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00534 #endif
00535     }
00536 
00537     // we assume we don't have a cmpxchg16b
00538     //
00539     //template <typename T1, typename T2> inline 
00540     //static bool LASS_CALL compareAndSwap(
00541     //      T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2);
00542     
00543     template <typename T> inline
00544     static void LASS_CALL increment(volatile T& value)
00545     {
00546 #if (LASS_ADDRESS_SIZE == 32)
00547         // not knowing any better, we emulate incq with cas loop
00548         T old, fresh;
00549         do
00550         {
00551             old = value;
00552             fresh = old + 1;
00553         }
00554         while (!atomicCompareAndSwap(value, old, fresh));       
00555 #elif (LASS_ADDRESS_SIZE == 64) && defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00556         __asm__ __volatile__(
00557             "lock; incq %0;"
00558             : "=m"(value)
00559             : "m"(value)
00560             : "cc", "memory");
00561 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00562         _InterlockedIncrement64(reinterpret_cast<volatile __int64*>(&value));
00563 #else
00564 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00565 #endif      
00566     }
00567 
00568     template <typename T> inline
00569     static void LASS_CALL decrement(volatile T& value)
00570     {
00571 #if (LASS_ADDRESS_SIZE == 32)
00572         // not knowing any better, we emulate decq with cas loop
00573         T old, fresh;
00574         do
00575         {
00576             old = value;
00577             fresh = old - 1;
00578         }
00579         while (!atomicCompareAndSwap(value, old, fresh));       
00580 #elif (LASS_ADDRESS_SIZE == 64) && defined(LASS_HAVE_INLINE_ASSEMBLY_GCC)
00581         __asm__ __volatile__(
00582             "lock; decq %0;"
00583             : "=m"(value)
00584             : "m"(value)
00585             : "cc", "memory");
00586 #elif defined(LASS_UTIL_IMPL_ATOMIC_MSVC_X64)
00587         _InterlockedDecrement64(reinterpret_cast<volatile __int64*>(&value));
00588 #else
00589 #   error [LASS BUILD MSG] lass/util/impl/atomic_impl.h: missing implementation
00590 #endif
00591     }
00592 };
00593 
00594 
00595 
00596 }
00597 }
00598 }
00599 
00600 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
00601 #   pragma warning(pop)
00602 #endif
00603 
00604 // EOF

Generated on Mon Nov 10 14:20:00 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo