Subj : Re: Optimization to Jeffrey Richter's COptex (Windows)? To : comp.programming.threads From : SenderX Date : Thu Jan 27 2005 08:56 pm "Alexander Terekhov" wrote in message news:41F97011.657B8E9E@web.de... > > SenderX wrote: >> >> > You've omitted timedlock(). Why so? ;-) >> > >> >> Here is what it would look like: > > [... more pointless counting ...] Its not really pointless, just unnecessary. >> Are you talking about counting in the CAS loop itself, xchg = old + 1, >> type >> stuff? > > Yes. What do you think of this simple emulation of a waitset bit impl for win32: < pseudo-code > class mutex { public: class guard { public: guard( mutex &_this ) : m_this( _this ) { m_this.lock(); } ~guard() { m_this.unlock(); } private: mutex &m_this; }; public: mutex() : m_state( 0 ), m_waitset( CreateEvent( 0, FALSE, FALSE, 0 ) ) { if ( ! m_waitset ) { throw; } } ~mutex() { if ( ! CloseHandle( m_waitset ) ) { assert( false ); } } public: void lock() { if ( InterlockedExchange( &m_state, 1 ) ) { _asm{ pause }; while ( InterlockedExchange( &m_state, 2 ) ) { if ( ! WaitForSingleObject( m_waitset, INFINITE ) ) { throw; } } } } void unlock() { if ( InterlockedExchange( &m_state, 0 ) == 2 ) { if ( ! SetEvent( m_waitset ) ) { throw; } } } private: volatile LONG m_state; HANDLE m_waitset; }; class waitset { public: waitset() : m_waiters( 0 ), m_queue( CreateSemaphore( 0, 0, 0, 0 ) ) { if ( ! m_queue ) { throw; } } ~waitset() { if ( ! CloseHandle( m_queue ) ) { assert( false ); } } public: bool wait( volatile LPLONG dest, LONG cmp, DWORD timeout ) { { mutex::guard lock( m_mutex ); InterlockedBTS( dest, 0x80000000 ); if ( ( *dest & 0x7FFFFFFF ) != ( cmp & 0x7FFFFFFF ) ) { return false; } ++m_waiters; } DWORD ret = WaitForSingleObject( m_queue, timeout ); if ( ret != WAIT_OBJECT_0 ) { { mutex::guard lock( m_mutex ); if ( --m_waiters ) { InterlockedBTS( dest, 0x80000000 ); } } if ( ret != WAIT_TIMEOUT ) { throw; } return false; } return true; } LONG wake( volatile LPLONG dest, LONG signals ) { { mutex::guard lock( m_mutex ); if ( m_waiters > 0 ) { if ( m_waiters >= signals ) { m_waiters -= signals; } else { signals = m_waiters; m_waiters = 0; } } if ( m_waiters ) { InterlockedBTS( dest, 0x80000000 ); } } if ( signals ) { if ( ! ReleaseSemaphore( m_queue, signals, 0 ) ) { throw; } } return signals; } private: mutex m_mutex; LONG m_waiters; HANDLE m_queue; }; class mutex_with_waitbit { public: mutex_with_waitbit() : m_futex( 0 ) {} public: bool lock( DWORD timeout ) { while ( InterlockedBTS( &m_futex, 1 ) ) { if ( ! m_waitset.wait( &m_futex, 1, timeout ) ) { return false; } } return true; } void unlock() { if ( InterlockedExchange( &m_futex, 0 ) & 0x80000000 ) { m_waitset.wake( &m_futex, 1 ); } } private: volatile LONG m_futex; waitset m_waitset; }; .