As I said above, check the assembly. I did before I posted.You are the second (possibly third) person who reads this code and thinks that if (sizeof(T) == 4) { } introduces extra overhead... I don't see anyone providing any evidence of this however and it does not make any sense.
Code: Select all
bool cas (const T &old, const T &nu)
{
51128F40 push ebp
51128F41 mov ebp,esp
51128F43 push 0FFFFFFFFh
51128F45 push offset __ehhandler$?cas@?$AtomicScalar@W4LoadingState@Resource@Ogre@@@Ogre@@QAE_NABW4LoadingState@Resource@2@0@Z (51775510h)
51128F4A mov eax,dword ptr fs:[00000000h]
51128F50 push eax
51128F51 sub esp,118h
51128F57 push ebx
51128F58 push esi
51128F59 push edi
51128F5A push ecx
51128F5B lea edi,[ebp-124h]
51128F61 mov ecx,46h
51128F66 mov eax,0CCCCCCCCh
51128F6B rep stos dword ptr es:[edi]
51128F6D pop ecx
51128F6E mov eax,dword ptr [___security_cookie (51CF0CA0h)]
51128F73 xor eax,ebp
51128F75 mov dword ptr [ebp-10h],eax
51128F78 push eax
51128F79 lea eax,[ebp-0Ch]
51128F7C mov dword ptr fs:[00000000h],eax
51128F82 mov dword ptr [ebp-14h],ecx
if (sizeof(T)==2) {
51128F85 xor eax,eax
51128F87 je Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+77h (51128FB7h)
return _InterlockedCompareExchange16((SHORT*)&mField, static_cast<SHORT>(nu), static_cast<SHORT>(old)) == static_cast<SHORT>(old);
51128F89 mov ecx,dword ptr [ebp+8]
51128F8C mov ax,word ptr [ecx]
51128F8F mov edx,dword ptr [ebp+0Ch]
51128F92 mov cx,word ptr [edx]
51128F95 mov edx,dword ptr [ebp-14h]
51128F98 lock cmpxchg word ptr [edx],cx
51128F9D cwde
51128F9E mov ecx,dword ptr [ebp+8]
51128FA1 movsx edx,word ptr [ecx]
51128FA4 xor ecx,ecx
51128FA6 cmp eax,edx
51128FA8 sete cl
51128FAB mov al,cl
51128FAD jmp Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+1C2h (51129102h)
51128FB2 jmp Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+1C2h (51129102h)
}
else if (sizeof(T)==4)
51128FB7 mov edx,1
51128FBC test edx,edx
51128FBE je Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+0A7h (51128FE7h)
{
return _InterlockedCompareExchange((LONG*)&mField, static_cast<LONG>(nu), static_cast<LONG>(old)) == static_cast<LONG>(old);
51128FC0 mov eax,dword ptr [ebp+8]
51128FC3 mov eax,dword ptr [eax]
51128FC5 mov ecx,dword ptr [ebp+0Ch]
51128FC8 mov edx,dword ptr [ecx]
51128FCA mov ecx,dword ptr [ebp-14h]
51128FCD lock cmpxchg dword ptr [ecx],edx
51128FD1 mov edx,dword ptr [ebp+8]
51128FD4 xor ecx,ecx
51128FD6 cmp eax,dword ptr [edx]
51128FD8 sete cl
51128FDB mov al,cl
51128FDD jmp Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+1C2h (51129102h)
51128FE2 jmp Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+1C2h (51129102h)
}
else if (sizeof(T)==8) {
51128FE7 xor edx,edx
51128FE9 je Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+140h (51129080h)
return _InterlockedCompareExchange64((LONGLONG*)&mField, static_cast<LONGLONG>(nu), static_cast<LONGLONG>(old)) == static_cast<LONGLONG>(old);
51128FEF mov eax,dword ptr [ebp+8]
51128FF2 mov eax,dword ptr [eax]
51128FF4 cdq
51128FF5 mov ecx,eax
51128FF7 mov esi,edx
51128FF9 mov edx,dword ptr [ebp+0Ch]
51128FFC mov eax,dword ptr [edx]
51128FFE cdq
51128FFF mov edi,eax
51129001 mov eax,edx
51129003 mov dword ptr [ebp-110h],eax
51129009 mov eax,ecx
5112900B mov edx,esi
5112900D mov esi,dword ptr [ebp-14h]
51129010 mov ebx,edi
51129012 mov ecx,dword ptr [ebp-110h]
51129018 lock cmpxchg8b qword ptr [esi]
5112901C mov ecx,eax
5112901E mov esi,edx
51129020 mov edx,dword ptr [ebp+8]
51129023 mov eax,dword ptr [edx]
51129025 cdq
51129026 mov dword ptr [ebp-118h],ecx
5112902C mov dword ptr [ebp-114h],esi
51129032 mov dword ptr [ebp-120h],eax
51129038 mov dword ptr [ebp-11Ch],edx
5112903E mov eax,dword ptr [ebp-118h]
51129044 cmp eax,dword ptr [ebp-120h]
5112904A jne Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+126h (51129066h)
5112904C mov ecx,dword ptr [ebp-114h]
51129052 cmp ecx,dword ptr [ebp-11Ch]
51129058 jne Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+126h (51129066h)
5112905A mov dword ptr [ebp-124h],1
51129064 jmp Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+130h (51129070h)
51129066 mov dword ptr [ebp-124h],0
51129070 mov al,byte ptr [ebp-124h]
51129076 jmp Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+1C2h (51129102h)
}
else {
5112907B jmp Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+1C2h (51129102h)
OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::cas");
51129080 push offset string "AtomicScalar::cas" (518DF8A8h)
51129085 lea ecx,[ebp-34h]
51129088 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (50AC8FA6h)
5112908D mov dword ptr [ebp-4],0
51129094 push offset string "Only 16, 32, and 64 bit scalars "... (518DF868h)
51129099 lea ecx,[ebp-54h]
5112909C call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (50AC8FA6h)
511290A1 mov byte ptr [ebp-4],1
511290A5 xor edx,edx
511290A7 mov byte ptr [ebp-109h],dl
511290AD push 112h
511290B2 push offset string "d:\\work\\qgf5_2013\\dev\\sdk\\includ"... (518DF820h)
511290B7 lea eax,[ebp-34h]
511290BA push eax
511290BB lea ecx,[ebp-54h]
511290BE push ecx
511290BF movzx edx,byte ptr [ebp-109h]
511290C6 push edx
511290C7 lea eax,[ebp-108h]
511290CD push eax
511290CE call Ogre::ExceptionFactory::create (50AABECEh)
511290D3 add esp,18h
511290D6 push offset __TI3?AVUnimplementedException@Ogre@@ (51A88998h)
511290DB lea ecx,[ebp-108h]
511290E1 push ecx
511290E2 call _CxxThrowException (5163EF60h)
511290E7 mov byte ptr [ebp-4],0
511290EB lea ecx,[ebp-54h]
511290EE call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (50ABD561h)
511290F3 mov dword ptr [ebp-4],0FFFFFFFFh
511290FA lea ecx,[ebp-34h]
511290FD call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (50ABD561h)
}
}
Code: Select all
if (sizeof(T)==2) {
51128F85 xor eax,eax
51128F87 je Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+77h (51128FB7h)
return _InterlockedCompareExchange16((SHORT*)&mField, static_cast<SHORT>(nu), static_cast<SHORT>(old)) == static_cast<SHORT>(old);
Code: Select all
else if (sizeof(T)==4)
51128FB7 mov edx,1
51128FBC test edx,edx
51128FBE je Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+0A7h (51128FE7h)
{
return _InterlockedCompareExchange((LONG*)&mField, static_cast<LONG>(nu), static_cast<LONG>(old)) == static_cast<LONG>(old);
Code: Select all
else if (sizeof(T)==8) {
51128FE7 xor edx,edx
51128FE9 je Ogre::AtomicScalar<enum Ogre::Resource::LoadingState>::cas+140h (51129080h)
return _InterlockedCompareExchange64((LONGLONG*)&mField, static_cast<LONGLONG>(nu), static_cast<LONGLONG>(old)) == static_cast<LONGLONG>(old);
xor eax,eax (makes eax = 0)
je (jump if eax is zero)
equivalent to if(false), it skips the code for size 2
move edx,1 (makes edx = 1)
test edx,edx (edx & edx)
je (jump if edx is zero, which is never will be)
equivalent to if(true)
So the assembly is explicitly doing:
if(false)
{
_InterlockedCompareExchange16
}
else if(true)
{
_InterlockedCompareExchange
}
else if(false)
{
_InterlockedCompareExchange64
}