Module: E:\source\tmp\fmutex.cpp GROUP: 'DGROUP' CONST,CONST2,_DATA,_BSS,XIB,XI,XIE Segment: _TEXT PARA USE32 00000240 bytes #define INCL_NOPMAPI 0000 void near .fn_init(): 0000 52 push edx 0001 31 D2 xor edx,edx 0003 B8 08 00 00 00 mov eax,offset FastMutex near mux+0x8 0008 89 15 00 00 00 00 mov FastMutex near mux,edx 000E 89 15 04 00 00 00 mov FastMutex near mux+0x4,edx 0014 E8 00 00 00 00 call near FEventSemaphore::FEventSemaphore() 0019 B8 00 00 00 00 mov eax,offset L$18 001E E8 00 00 00 00 call __wcpp_4_lcl_register__ 0023 5A pop edx 0024 C3 ret 0025 8D 40 00 lea eax,[eax] #define WIN32_LEAN_AND_MEAN #define BIFINCL_THREAD #define BIFINCL_SEMAPHORES #define BIFINCL_MAINTHREAD #include // A few low-level operations extern "C" void LockedIncrement(unsigned *p); #pragma aux LockedIncrement = \ ".386p " \ "lock inc dword ptr [eax] " \ parm [eax] modify []; extern "C" void LockedDecrement(unsigned *p); #pragma aux LockedDecrement = \ ".386p "\ "lock dec dword ptr [eax] "\ parm [eax] modify []; extern "C" unsigned LockedExchange(unsigned *p, unsigned v); #pragma aux LockedExchange = \ ".386p "\ "lock xchg ecx,[eax] "\ parm [eax] [ecx] modify [] value [ecx]; //---------------------------------------------------------------------------- // A fast, but friendly, mutex class FastMutex { unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: FastMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; inline void FastMutex::Request() { LockedIncrement(&waiters); for(;;) { if(LockedExchange(&toggle,1)==0) { LockedDecrement(&waiters); return; } try_again.Wait(); try_again.Reset(); } } inline void FastMutex::Release() { toggle=0; if(waiters!=0) try_again.Post(); } //---------------------------------------------------------------------------- // A very fast, but unfriendly, mutex class SpinMutex { enum { spin_retries=100 }; unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: SpinMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; void SpinMutex::Request() { Routine Size: 40 bytes, Routine Base: _TEXT + 0000 0028 void near SpinMutex::Request(): 0028 53 push ebx 0029 51 push ecx 002A 56 push esi 002B 89 C3 mov ebx,eax for(unsigned spin=0; spin #include class MyMain : public FMainThread { public: MyMain(int argc, char **argv) : FMainThread(argc,argv) {} int Main(int, char**); }; class OtherThread : public FThread { public: OtherThread() : FThread() {} void Go(); }; //FMutexSemaphore mux; FastMutex mux; //SpinMutex mux; //SpinLock mux; //NTCritialSection mux; void OtherThread::Go() { Routine Size: 28 bytes, Routine Base: _TEXT + 007C 0098 void near OtherThread::Go(): 0098 53 push ebx 0099 51 push ecx 009A 52 push edx 009B 56 push esi 009C 57 push edi 009D 55 push ebp 009E BE 08 00 00 00 mov esi,offset FastMutex near mux+0x8 for(unsigned i=0; i<500000; i++) { 00A3 31 DB xor ebx,ebx 00A5 BD FF FF FF FF mov ebp,0xffffffff 00AA BF 01 00 00 00 mov edi,0x00000001 mux.Request(); 00AF L$6: 00AF B8 04 00 00 00 mov eax,offset FastMutex near mux+0x4 00B4 F0 FF 00 lock inc dword ptr [eax] 00B7 L$7: 00B7 B8 00 00 00 00 mov eax,offset FastMutex near mux 00BC 89 F9 mov ecx,edi 00BE F0 87 08 lock xchg ecx,[eax] 00C1 85 C9 test ecx,ecx 00C3 74 12 je L$8 00C5 89 EA mov edx,ebp 00C7 89 F0 mov eax,esi 00C9 E8 00 00 00 00 call int near FEventSemaphore::Wait( long ) 00CE 89 F0 mov eax,esi 00D0 E8 00 00 00 00 call int near FEventSemaphore::Reset() 00D5 EB E0 jmp L$7 mux.Release(); } } 00D7 L$8: 00D7 B8 04 00 00 00 mov eax,offset FastMutex near mux+0x4 00DC F0 FF 08 lock dec dword ptr [eax] 00DF 89 0D 00 00 00 00 mov FastMutex near mux,ecx 00E5 83 3D 04 00 00 00 00 cmp dword ptr FastMutex near mux+0x4,0x00000000 00EC 74 07 je L$9 00EE 89 F0 mov eax,esi 00F0 E8 00 00 00 00 call int near FEventSemaphore::Post() 00F5 L$9: 00F5 43 inc ebx 00F6 81 FB 20 A1 07 00 cmp ebx,0x0007a120 00FC 72 B1 jb L$6 00FE 5D pop ebp 00FF 5F pop edi 0100 5E pop esi 0101 5A pop edx 0102 59 pop ecx 0103 5B pop ebx 0104 C3 ret 0105 8D 40 00 lea eax,[eax] int MyMain::Main(int,char **) { Routine Size: 112 bytes, Routine Base: _TEXT + 0098 0108 int near MyMain::Main( int, char near * near * ): 0108 51 push ecx 0109 56 push esi 010A 57 push edi 010B 55 push ebp 010C 83 EC 20 sub esp,0x00000020 clock_t start=clock(); 010F E8 00 00 00 00 call clock_ 0114 BF 08 00 00 00 mov edi,offset FastMutex near mux+0x8 0119 BD 00 00 00 00 mov ebp,offset FastMutex near mux 011E 89 C6 mov esi,eax OtherThread ot; 0120 31 D2 xor edx,edx 0122 89 E0 mov eax,esp ot.Start(); for(unsigned i=0; i<500000; i++) { 0124 31 DB xor ebx,ebx 0126 E8 00 00 00 00 call near FThread::FThread( int unsigned ) 012B BA 04 00 00 00 mov edx,offset void (near * const near __vftbl[])()+0x4 0130 89 E0 mov eax,esp 0132 89 54 24 14 mov 0x14[esp],edx 0136 E8 00 00 00 00 call int near FThread::Start() mux.Request(); 013B L$10: 013B B8 04 00 00 00 mov eax,offset FastMutex near mux+0x4 0140 F0 FF 00 lock inc dword ptr [eax] 0143 L$11: 0143 B9 01 00 00 00 mov ecx,0x00000001 0148 89 E8 mov eax,ebp 014A F0 87 08 lock xchg ecx,[eax] 014D 85 C9 test ecx,ecx 014F 74 15 je L$12 0151 BA FF FF FF FF mov edx,0xffffffff 0156 89 F8 mov eax,edi 0158 E8 00 00 00 00 call int near FEventSemaphore::Wait( long ) 015D 89 F8 mov eax,edi 015F E8 00 00 00 00 call int near FEventSemaphore::Reset() 0164 EB DD jmp L$11 mux.Release(); } ot.Wait(); clock_t end=clock(); printf("running time: %10.3f seconds\n", ((double)(end-start))/CLK_TCK ); return 0; } 0166 L$12: 0166 B8 04 00 00 00 mov eax,offset FastMutex near mux+0x4 016B F0 FF 08 lock dec dword ptr [eax] 016E A1 04 00 00 00 mov eax,FastMutex near mux+0x4 0173 89 0D 00 00 00 00 mov FastMutex near mux,ecx 0179 85 C0 test eax,eax 017B 74 07 je L$13 017D 89 F8 mov eax,edi 017F E8 00 00 00 00 call int near FEventSemaphore::Post() 0184 L$13: 0184 43 inc ebx 0185 81 FB 20 A1 07 00 cmp ebx,0x0007a120 018B 72 AE jb L$10 018D 89 E0 mov eax,esp 018F E8 00 00 00 00 call int near FThread::Wait() 0194 E8 00 00 00 00 call clock_ 0199 31 D2 xor edx,edx 019B 29 F0 sub eax,esi 019D 89 54 24 1C mov 0x1c[esp],edx 01A1 89 44 24 18 mov 0x18[esp],eax 01A5 DF 6C 24 18 fild qword ptr 0x18[esp] 01A9 DC 0D 20 00 00 00 fmul qword ptr L$16 01AF 83 EC 08 sub esp,0x00000008 01B2 DD 1C 24 fstp qword ptr [esp] 01B5 68 00 00 00 00 push offset L$15 01BA E8 00 00 00 00 call printf_ 01BF 83 C4 0C add esp,0x0000000c 01C2 BA 01 00 00 00 mov edx,0x00000001 01C7 89 E0 mov eax,esp 01C9 E8 00 00 00 00 call near FThread::~FThread() 01CE 31 C0 xor eax,eax 01D0 83 C4 20 add esp,0x00000020 01D3 5D pop ebp 01D4 5F pop edi 01D5 5E pop esi 01D6 59 pop ecx 01D7 C3 ret DEFBIFTHREADMAIN(MyMain); Routine Size: 208 bytes, Routine Base: _TEXT + 0108 01D8 FMainThread near * near MakeMainThread( int, char near * near * ): 01D8 53 push ebx 01D9 51 push ecx 01DA 89 C3 mov ebx,eax 01DC 89 D1 mov ecx,edx 01DE B8 30 00 00 00 mov eax,0x00000030 01E3 E8 00 00 00 00 call void near * near operator new( int unsigned ) 01E8 85 C0 test eax,eax 01EA 75 03 jne L$14 01EC 59 pop ecx 01ED 5B pop ebx 01EE C3 ret 01EF L$14: 01EF C7 00 00 00 00 00 mov dword ptr [eax],offset int unsigned const near __vbtbl[] 01F5 31 D2 xor edx,edx 01F7 83 C0 18 add eax,0x00000018 01FA E8 00 00 00 00 call near FThread::FThread( int unsigned ) 01FF BA 01 00 00 00 mov edx,0x00000001 0204 83 E8 18 sub eax,0x00000018 0207 E8 00 00 00 00 call near FMainThread::FMainThread( int, char near * near * ) 020C 8B 08 mov ecx,[eax] 020E 8B 49 04 mov ecx,0x4[ecx] 0211 8D 1C 08 lea ebx,[eax+ecx] 0214 89 4B FC mov -0x4[ebx],ecx 0217 8B 08 mov ecx,[eax] 0219 C7 40 10 04 00 00 00 mov dword ptr 0x10[eax],offset void (near * const near __vftbl[])()+0x4 0220 8B 49 04 mov ecx,0x4[ecx] 0223 C7 44 01 14 04 00 00 00 mov dword ptr 0x14[ecx+eax],offset void (near * const near __vftbl[])()+0x4 022B 59 pop ecx 022C 5B pop ebx 022D C3 ret 022E 8B C0 mov eax,eax Routine Size: 88 bytes, Routine Base: _TEXT + 01D8 0230 main_: 0230 53 push ebx 0231 BB 00 00 00 00 mov ebx,offset FMainThread near * near MakeMainThread( int, char near * near * ) 0236 E8 00 00 00 00 call int near _BIFThreadMain( int, char near * near *, FMainThread near * (near *)()) 023B 5B pop ebx 023C C3 ret 023D 8D 40 00 lea eax,[eax] Routine Size: 16 bytes, Routine Base: _TEXT + 0230 No disassembly errors Segment: CONST BYTE USE32 00000028 bytes 0000 L$15: 0000 72 75 6E 6E 69 6E 67 20 74 69 6D 65 3A 20 25 31 running time: %1 0010 30 2E 33 66 20 73 65 63 6F 6E 64 73 0A 00 00 00 0.3f seconds.... 0020 L$16: 0020 FC A9 F1 D2 4D 62 50 3F ....MbP? Segment: CONST2 PARA USE32 0000000C bytes 0000 L$17: 0000 04 00 00 00 .... 0004 00 00 00 00 DD near FastMutex::~FastMutex() 0008 00 00 00 00 DD FastMutex near mux Segment: _DATA BYTE USE32 00000010 bytes 0000 L$18: 0000 00 00 00 00 .... 0004 00 00 00 00 DD L$17 0008 01 00 00 00 .... 000C 00 00 00 00 DD FastMutex near mux Segment: _BSS DWORD USE32 00000010 bytes 0000 FastMutex near mux: BSS Size: 16 bytes Segment: XI WORD USE32 00000006 bytes 0000 void (near * near .mod_init)(): 0000 00 40 .@ 0002 00 00 00 00 DD void near .fn_init() Comdat: near FastMutex::FastMutex() SEGMENT ANY '_TEXT' 00000019 bytes #define INCL_NOPMAPI #define WIN32_LEAN_AND_MEAN #define BIFINCL_THREAD #define BIFINCL_SEMAPHORES #define BIFINCL_MAINTHREAD #include // A few low-level operations extern "C" void LockedIncrement(unsigned *p); #pragma aux LockedIncrement = \ ".386p " \ "lock inc dword ptr [eax] " \ parm [eax] modify []; extern "C" void LockedDecrement(unsigned *p); #pragma aux LockedDecrement = \ ".386p "\ "lock dec dword ptr [eax] "\ parm [eax] modify []; extern "C" unsigned LockedExchange(unsigned *p, unsigned v); #pragma aux LockedExchange = \ ".386p "\ "lock xchg ecx,[eax] "\ parm [eax] [ecx] modify [] value [ecx]; //---------------------------------------------------------------------------- // A fast, but friendly, mutex class FastMutex { unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: FastMutex() : toggle(0), waiters(0), try_again() {} 0000 L$19: 0000 near FastMutex::FastMutex(): 0000 C7 00 00 00 00 00 mov dword ptr [eax],0x00000000 0006 83 C0 08 add eax,0x00000008 0009 C7 40 FC 00 00 00 00 mov dword ptr -0x4[eax],0x00000000 0010 E8 00 00 00 00 call near FEventSemaphore::FEventSemaphore() 0015 83 E8 08 sub eax,0x00000008 0018 C3 ret Routine Size: 25 bytes, Routine Base: W?$ct:FastMutex$n()_ + 0000 No disassembly errors File contains no line numbers. Comdat: void near * near FThread::__vfthunk() SEGMENT ANY '_TEXT' 00000078 bytes 0000 L$20: 0000 void near * near FThread::__vfthunk(): 0000 53 push ebx 0001 51 push ecx 0002 83 EC 04 sub esp,0x00000004 0005 89 D3 mov ebx,edx 0007 8B 50 FC mov edx,-0x4[eax] 000A 89 1C 24 mov [esp],ebx 000D 29 D0 sub eax,edx 000F 8A 14 24 mov dl,[esp] 0012 89 C1 mov ecx,eax 0014 F6 C2 04 test dl,0x04 0017 75 1F jne L$22 0019 BA 01 00 00 00 mov edx,0x00000001 001E E8 00 00 00 00 call near FMainThread::~FMainThread() 0023 89 C1 mov ecx,eax 0025 F6 C3 01 test bl,0x01 0028 74 1F je L$23 002A F6 04 24 02 test byte ptr [esp],0x02 002E 75 37 jne L$24 0030 L$21: 0030 89 C8 mov eax,ecx 0032 83 C4 04 add esp,0x00000004 0035 59 pop ecx 0036 5B pop ebx 0037 C3 ret 0038 L$22: 0038 BA 00 00 00 00 mov edx,offset char unsigned const near __typesig[] 003D E8 00 00 00 00 call __wcpp_4_dtor_array_store__ 0042 E8 00 00 00 00 call void near operator delete []( void near * ) 0047 EB E7 jmp L$21 0049 L$23: 0049 BA 01 00 00 00 mov edx,0x00000001 004E 83 C0 18 add eax,0x00000018 0051 E8 00 00 00 00 call near FThread::~FThread() 0056 8D 48 E8 lea ecx,-0x18[eax] 0059 F6 04 24 02 test byte ptr [esp],0x02 005D 75 08 jne L$24 005F 89 C8 mov eax,ecx 0061 83 C4 04 add esp,0x00000004 0064 59 pop ecx 0065 5B pop ebx 0066 C3 ret 0067 L$24: 0067 89 C8 mov eax,ecx 0069 E8 00 00 00 00 call void near operator delete( void near * ) 006E 89 C8 mov eax,ecx 0070 83 C4 04 add esp,0x00000004 0073 59 pop ecx 0074 5B pop ebx 0075 C3 ret 0076 8B C0 mov eax,eax Routine Size: 120 bytes, Routine Base: W?$Wvt0n.@dt:MyMain$c$:0$dtn()_$:FThread$n()pnv + 0000 No disassembly errors File contains no line numbers. Comdat: void near FThread::__vfthunk() SEGMENT ANY '_TEXT' 00000008 bytes 0000 L$25: 0000 void near FThread::__vfthunk(): 0000 2B 40 FC sub eax,-0x4[eax] 0003 E9 00 00 00 00 jmp void near FMainThread::Go() Routine Size: 8 bytes, Routine Base: W?$Wvt0wGo:MyMain$c$:FMainThread$Go$n()v$:FThread$n()v + 0000 No disassembly errors Comdat: near OtherThread::OtherThread() SEGMENT ANY '_TEXT' 00000011 bytes #define INCL_NOPMAPI #define WIN32_LEAN_AND_MEAN #define BIFINCL_THREAD #define BIFINCL_SEMAPHORES #define BIFINCL_MAINTHREAD #include // A few low-level operations extern "C" void LockedIncrement(unsigned *p); #pragma aux LockedIncrement = \ ".386p " \ "lock inc dword ptr [eax] " \ parm [eax] modify []; extern "C" void LockedDecrement(unsigned *p); #pragma aux LockedDecrement = \ ".386p "\ "lock dec dword ptr [eax] "\ parm [eax] modify []; extern "C" unsigned LockedExchange(unsigned *p, unsigned v); #pragma aux LockedExchange = \ ".386p "\ "lock xchg ecx,[eax] "\ parm [eax] [ecx] modify [] value [ecx]; //---------------------------------------------------------------------------- // A fast, but friendly, mutex class FastMutex { unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: FastMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; inline void FastMutex::Request() { LockedIncrement(&waiters); for(;;) { if(LockedExchange(&toggle,1)==0) { LockedDecrement(&waiters); return; } try_again.Wait(); try_again.Reset(); } } inline void FastMutex::Release() { toggle=0; if(waiters!=0) try_again.Post(); } //---------------------------------------------------------------------------- // A very fast, but unfriendly, mutex class SpinMutex { enum { spin_retries=100 }; unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: SpinMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; void SpinMutex::Request() { for(unsigned spin=0; spin #include class MyMain : public FMainThread { public: MyMain(int argc, char **argv) : FMainThread(argc,argv) {} int Main(int, char**); }; class OtherThread : public FThread { public: OtherThread() : FThread() {} 0000 L$26: 0000 near OtherThread::OtherThread(): 0000 52 push edx 0001 31 D2 xor edx,edx 0003 E8 00 00 00 00 call near FThread::FThread( int unsigned ) 0008 C7 40 14 04 00 00 00 mov dword ptr 0x14[eax],offset void (near * const near __vftbl[])()+0x4 000F 5A pop edx 0010 C3 ret Routine Size: 17 bytes, Routine Base: W?$ct:OtherThread$n()_ + 0000 No disassembly errors Comdat: near OtherThread::~OtherThread() SEGMENT ANY '_TEXT' 00000040 bytes #define INCL_NOPMAPI #define WIN32_LEAN_AND_MEAN #define BIFINCL_THREAD #define BIFINCL_SEMAPHORES #define BIFINCL_MAINTHREAD #include // A few low-level operations extern "C" void LockedIncrement(unsigned *p); #pragma aux LockedIncrement = \ ".386p " \ "lock inc dword ptr [eax] " \ parm [eax] modify []; extern "C" void LockedDecrement(unsigned *p); #pragma aux LockedDecrement = \ ".386p "\ "lock dec dword ptr [eax] "\ parm [eax] modify []; extern "C" unsigned LockedExchange(unsigned *p, unsigned v); #pragma aux LockedExchange = \ ".386p "\ "lock xchg ecx,[eax] "\ parm [eax] [ecx] modify [] value [ecx]; //---------------------------------------------------------------------------- // A fast, but friendly, mutex class FastMutex { unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: FastMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; inline void FastMutex::Request() { LockedIncrement(&waiters); for(;;) { if(LockedExchange(&toggle,1)==0) { LockedDecrement(&waiters); return; } try_again.Wait(); try_again.Reset(); } } inline void FastMutex::Release() { toggle=0; if(waiters!=0) try_again.Post(); } //---------------------------------------------------------------------------- // A very fast, but unfriendly, mutex class SpinMutex { enum { spin_retries=100 }; unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: SpinMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; void SpinMutex::Request() { for(unsigned spin=0; spin #include class MyMain : public FMainThread { public: MyMain(int argc, char **argv) : FMainThread(argc,argv) {} int Main(int, char**); }; class OtherThread : public FThread { public: OtherThread() : FThread() {} void Go(); }; 0000 L$27: 0000 near OtherThread::~OtherThread(): 0000 53 push ebx 0001 51 push ecx 0002 89 C1 mov ecx,eax 0004 89 D3 mov ebx,edx 0006 F6 C3 04 test bl,0x04 0009 75 16 jne L$28 000B BA 01 00 00 00 mov edx,0x00000001 0010 E8 00 00 00 00 call near FThread::~FThread() 0015 89 C1 mov ecx,eax 0017 F6 C3 02 test bl,0x02 001A 75 19 jne L$29 001C 89 C8 mov eax,ecx 001E 59 pop ecx 001F 5B pop ebx 0020 C3 ret 0021 L$28: 0021 BA 00 00 00 00 mov edx,offset char unsigned const near __typesig[] 0026 E8 00 00 00 00 call __wcpp_4_dtor_array_store__ 002B E8 00 00 00 00 call void near operator delete []( void near * ) 0030 89 C8 mov eax,ecx 0032 59 pop ecx 0033 5B pop ebx 0034 C3 ret 0035 L$29: 0035 E8 00 00 00 00 call void near operator delete( void near * ) 003A 89 C8 mov eax,ecx 003C 59 pop ecx 003D 5B pop ebx 003E C3 ret 003F 90 nop Routine Size: 64 bytes, Routine Base: W?$dt:OtherThread$n()_ + 0000 No disassembly errors Comdat: int unsigned const near __vbtbl[] SEGMENT ANY 'DGROUP:CONST2' 00000008 bytes 0000 int unsigned const near __vbtbl[]: 0000 00 00 00 00 18 00 00 00 ........ Comdat: void (near * const near __vftbl[])() SEGMENT ANY 'DGROUP:CONST2' 00000010 bytes 0000 void (near * const near __vftbl[])(): 0000 00 00 00 00 .... 0004 00 00 00 00 DD near MyMain::~MyMain() 0008 00 00 00 00 DD void near FMainThread::Go() 000C 00 00 00 00 DD int near MyMain::Main( int, char near * near * ) Comdat: void (near * const near __vftbl[])() SEGMENT ANY 'DGROUP:CONST2' 00000018 bytes 0000 void (near * const near __vftbl[])(): 0000 00 00 00 00 .... 0004 00 00 00 00 DD L$20 0008 00 00 00 00 DD int near FThread::OkToGo() 000C 00 00 00 00 DD L$25 0010 00 00 00 00 DD int near FThread::PreGo() 0014 00 00 00 00 DD void near FThread::PostGo() Comdat: void (near * const near __vftbl[])() SEGMENT ANY 'DGROUP:CONST2' 00000018 bytes 0000 void (near * const near __vftbl[])(): 0000 00 00 00 00 .... 0004 00 00 00 00 DD L$27 0008 00 00 00 00 DD int near FThread::OkToGo() 000C 00 00 00 00 DD void near OtherThread::Go() 0010 00 00 00 00 DD int near FThread::PreGo() 0014 00 00 00 00 DD void near FThread::PostGo() Comdat: char unsigned const near __typesig[] SEGMENT ANY 'DGROUP:CONST2' 00000018 bytes 0000 char unsigned const near __typesig[]: 0000 00 01 02 00 .... 0004 00 00 00 00 DD L$19 0008 00 00 00 00 DD near FastMutex::FastMutex( FastMutex const near & ) 000C 00 00 00 00 DD near FastMutex::~FastMutex() 0010 10 00 00 00 .... 0014 04 00 00 00 DD char unsigned near __typeid[]+0x4 Comdat: char unsigned const near __typesig[] SEGMENT ANY 'DGROUP:CONST2' 00000018 bytes 0000 char unsigned const near __typesig[]: 0000 00 01 02 00 .... 0004 00 00 00 00 DD L$26 0008 00 00 00 00 DD near OtherThread::OtherThread( OtherThread const near & ) 000C 00 00 00 00 DD L$27 0010 18 00 00 00 .... 0014 04 00 00 00 DD char unsigned near __typeid[]+0x4 Comdat: char unsigned near __typeid[] SEGMENT ANY 'DGROUP:_DATA' 0000000E bytes 0000 char unsigned near __typeid[]: 0000 00 00 00 00 24 4D 79 4D 61 69 6E 24 24 00 ....$MyMain$$. Comdat: char unsigned near __typeid[] SEGMENT ANY 'DGROUP:_DATA' 00000013 bytes 0000 char unsigned near __typeid[]: 0000 00 00 00 00 24 4F 74 68 65 72 54 68 72 65 61 64 ....$OtherThread 0010 24 24 00 $$. Comdat: near MyMain::~MyMain() SEGMENT ANY '_TEXT' 00000060 bytes #define INCL_NOPMAPI #define WIN32_LEAN_AND_MEAN #define BIFINCL_THREAD #define BIFINCL_SEMAPHORES #define BIFINCL_MAINTHREAD #include // A few low-level operations extern "C" void LockedIncrement(unsigned *p); #pragma aux LockedIncrement = \ ".386p " \ "lock inc dword ptr [eax] " \ parm [eax] modify []; extern "C" void LockedDecrement(unsigned *p); #pragma aux LockedDecrement = \ ".386p "\ "lock dec dword ptr [eax] "\ parm [eax] modify []; extern "C" unsigned LockedExchange(unsigned *p, unsigned v); #pragma aux LockedExchange = \ ".386p "\ "lock xchg ecx,[eax] "\ parm [eax] [ecx] modify [] value [ecx]; //---------------------------------------------------------------------------- // A fast, but friendly, mutex class FastMutex { unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: FastMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; inline void FastMutex::Request() { LockedIncrement(&waiters); for(;;) { if(LockedExchange(&toggle,1)==0) { LockedDecrement(&waiters); return; } try_again.Wait(); try_again.Reset(); } } inline void FastMutex::Release() { toggle=0; if(waiters!=0) try_again.Post(); } //---------------------------------------------------------------------------- // A very fast, but unfriendly, mutex class SpinMutex { enum { spin_retries=100 }; unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: SpinMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; void SpinMutex::Request() { for(unsigned spin=0; spin #include class MyMain : public FMainThread { public: MyMain(int argc, char **argv) : FMainThread(argc,argv) {} int Main(int, char**); }; 0000 near MyMain::~MyMain(): 0000 53 push ebx 0001 51 push ecx 0002 89 C1 mov ecx,eax 0004 89 D3 mov ebx,edx 0006 F6 C3 04 test bl,0x04 0009 75 1B jne L$30 000B BA 01 00 00 00 mov edx,0x00000001 0010 E8 00 00 00 00 call near FMainThread::~FMainThread() 0015 89 C1 mov ecx,eax 0017 F6 C3 01 test bl,0x01 001A 74 1E je L$31 001C F6 C3 02 test bl,0x02 001F 75 33 jne L$32 0021 89 C8 mov eax,ecx 0023 59 pop ecx 0024 5B pop ebx 0025 C3 ret 0026 L$30: 0026 BA 00 00 00 00 mov edx,offset char unsigned const near __typesig[] 002B E8 00 00 00 00 call __wcpp_4_dtor_array_store__ 0030 E8 00 00 00 00 call void near operator delete []( void near * ) 0035 89 C8 mov eax,ecx 0037 59 pop ecx 0038 5B pop ebx 0039 C3 ret 003A L$31: 003A BA 01 00 00 00 mov edx,0x00000001 003F 83 C0 18 add eax,0x00000018 0042 E8 00 00 00 00 call near FThread::~FThread() 0047 8D 48 E8 lea ecx,-0x18[eax] 004A F6 C3 02 test bl,0x02 004D 75 05 jne L$32 004F 89 C8 mov eax,ecx 0051 59 pop ecx 0052 5B pop ebx 0053 C3 ret 0054 L$32: 0054 89 C8 mov eax,ecx 0056 E8 00 00 00 00 call void near operator delete( void near * ) 005B 89 C8 mov eax,ecx 005D 59 pop ecx 005E 5B pop ebx 005F C3 ret Routine Size: 96 bytes, Routine Base: W?$dt:MyMain$n()_ + 0000 No disassembly errors Comdat: near FastMutex::~FastMutex() SEGMENT ANY '_TEXT' 0000000E bytes #define INCL_NOPMAPI #define WIN32_LEAN_AND_MEAN #define BIFINCL_THREAD #define BIFINCL_SEMAPHORES #define BIFINCL_MAINTHREAD #include // A few low-level operations extern "C" void LockedIncrement(unsigned *p); #pragma aux LockedIncrement = \ ".386p " \ "lock inc dword ptr [eax] " \ parm [eax] modify []; extern "C" void LockedDecrement(unsigned *p); #pragma aux LockedDecrement = \ ".386p "\ "lock dec dword ptr [eax] "\ parm [eax] modify []; extern "C" unsigned LockedExchange(unsigned *p, unsigned v); #pragma aux LockedExchange = \ ".386p "\ "lock xchg ecx,[eax] "\ parm [eax] [ecx] modify [] value [ecx]; //---------------------------------------------------------------------------- // A fast, but friendly, mutex class FastMutex { unsigned toggle; unsigned waiters; FEventSemaphore try_again; public: FastMutex() : toggle(0), waiters(0), try_again() {} void Request(); void Release(); }; 0000 near FastMutex::~FastMutex(): 0000 83 C0 08 add eax,0x00000008 0003 31 D2 xor edx,edx 0005 E8 00 00 00 00 call near FEventSemaphore::~FEventSemaphore() 000A 83 E8 08 sub eax,0x00000008 000D C3 ret Routine Size: 14 bytes, Routine Base: W?$dt:FastMutex$n()_ + 0000 No disassembly errors Comdat: char unsigned const near __typesig[] SEGMENT ANY 'DGROUP:CONST2' 00000018 bytes 0000 char unsigned const near __typesig[]: 0000 04 01 02 00 00 00 00 00 ........ 0008 00 00 00 00 DD near MyMain::MyMain( MyMain const near & ) 000C 00 00 00 00 DD near MyMain::~MyMain() 0010 30 00 00 00 0... 0014 04 00 00 00 DD char unsigned near __typeid[]+0x4 Comdat: char unsigned near __typeid[] SEGMENT ANY 'DGROUP:_DATA' 00000011 bytes 0000 char unsigned near __typeid[]: 0000 00 00 00 00 24 46 61 73 74 4D 75 74 65 78 24 24 ....$FastMutex$$ 0010 00 .