Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
inline CQueueLock::CQueueLock( ) : m_pHead( &m_special ), m_pTail( &m_special ) {
// // This function initializes the queue to an empty state. // In the empty state the queue contains one element which // has a Next pointer of 'LOCKVAL'. // The next pointer is initialized to LOCKVAL so that the first // append to the Queue owns the removal lock. // m_special.m_pNext = (CQElement*)((DWORD_PTR)LOCKVAL) ; }
inline CQueueLock::CQueueLock( BOOL fSet ) : m_pHead( &m_special ), m_pTail( &m_special ) {
if( fSet ) { m_special.m_pNext = (CQElement*)((DWORD_PTR)LOCKVAL) ; } else { m_special.m_pNext = 0 ; } }
#ifdef LOCKQ_DEBUG
CQueueLock::~CQueueLock( ) { // _ASSERT( m_pHead == m_pTail ) ; // _ASSERT( m_pHead == &m_special ) ; // _ASSERT( m_dwOwningThread == 0 || m_dwOwningThread == GetCurrentThreadId() ) ;
} #endif
inline void CQueueLock::Reset( ) {
m_pTail->m_pNext = (CQElement*)((DWORD_PTR)LOCKVAL) ;
}
inline BOOL CQueueLock::Append( CQElement* pAppend ) { // // We must set the Next pointer to NULL so that the next // we come to append the tail pointer is properly set up. // // _ASSERT( pAppend->m_pNext == 0 ) ; pAppend->m_pNext = 0 ;
// Get the old tail pointer. This guy won't be touched by the // remove thread if his next pointer is still NULL. CQElement* pTemp = (CQElement*)InterlockedExchangePointer( (LPVOID *)&m_pTail, pAppend ) ;
// After we set the old tail pointer's next pointer to NON NULL // he becomes fair game for whoever is removing from the queue. // We may become the thread removing from the queue if whoever was // previously removing got to the last element and changed its next pointer // to LOCKVAL. // // NOTE : This thread and any thread doing removals should be the only // threads touching the pNext field of the pTemp element. // PVOID l = InterlockedExchangePointer( (LPVOID *)&(pTemp->m_pNext), pAppend ) ;
return l == (PVOID)LOCKVAL ; }
inline CQElement* CQueueLock::RemoveAndRelease( void ) {
CQElement* p = (CQElement*)InterlockedCompareExchangePointer( (LPVOID*)&m_pHead->m_pNext, (LPVOID)LOCKVAL, 0 ) ;
_ASSERT( (DWORD_PTR)p != LOCKVAL ) ;
if( p != 0 ) {
// // There is an element following the head element - // so we can safely examine the head element has nobody // will touch its next pointer but us ! //
CQElement* pReturn = m_pHead ; m_pHead = p ; pReturn->m_pNext = 0 ;
if( pReturn == &m_special ) {
// // We can ignore the return value of Append - // it must always succeed as we are the only thread // that is allowed to relinquish the lock, and we ain't going to // do so ! // Append( pReturn ) ;
// // Now, we must offer ownership again ! //
p = (CQElement*)InterlockedCompareExchangePointer( (LPVOID*)&m_pHead->m_pNext, (LPVOID)LOCKVAL, 0 ) ;
_ASSERT( (DWORD_PTR)p != LOCKVAL ) ;
if( p != 0 ) {
// // The head element must not be the special element - // we took pains already to see that that didn't happen - // so we can safely remove the element from the head of the queue. //
pReturn = m_pHead ; m_pHead = p ; pReturn->m_pNext = 0 ; return pReturn ; }
} else {
return pReturn ;
} }
// // _ASSERT( p==0 ) ; //
return p ; }
inline CQElement* CQueueLock::Remove( void ) {
CQElement* p = m_pHead->m_pNext ; if( p != 0 ) {
// // There is an element following the head element - // so we can safely examine the head element has nobody // will touch its next pointer but us ! // p = m_pHead ;
if( p == &m_special ) {
// // The head element is the special element, so we want // to send it to the back and try examining the front again ! //
m_pHead = p->m_pNext ; p->m_pNext = 0 ;
// // We can ignore the return value of Append - // it must always succeed as we are the only thread // that is allowed to relinquish the lock, and we ain't going to // do so ! // Append( p ) ;
// // Ok, lets see if we can remove the head element now ! //
p = m_pHead->m_pNext ; } // // If this ain't 0, then the next pointer is set // and no other threads will be touching the next pointer, // so we can safely advance the head pointer and return // the first element. // if( p != 0 ) {
p = m_pHead ; // // The head element must not be the special element - // we took pains already to see that that didn't happen - // so we can safely remove the element from the head of the queue. // m_pHead = p->m_pNext ; p->m_pNext = 0 ; return p ; } }
return 0 ; }
template< class Element > inline TLockQueue< Element >::TLockQueue( ) { }
template< class Element > inline TLockQueue< Element >::TLockQueue( BOOL fSet ) : m_queue( fSet ) { }
template< class Element > inline void TLockQueue< Element >::Reset() { m_queue.Reset() ; }
template< class Element > inline BOOL TLockQueue< Element >::Append( Element *p ) { return m_queue.Append( (CQElement*)p ) ; }
template< class Element > inline Element* TLockQueue< Element >::Remove( ) { return (Element*) m_queue.Remove( ) ; }
template< class Element > inline Element* TLockQueue< Element >::RemoveAndRelease( ) { return (Element*) m_queue.RemoveAndRelease( ) ; }
#ifndef _NO_TEMPLATES_
template< class Element > inline TLockQueueV1< Element >::TLockQueueV1( ) { }
template< class Element > inline TLockQueueV1< Element >::~TLockQueueV1( ) { }
template< class Element > inline BOOL TLockQueueV1< Element >::Append( Element *p ) { return m_queue.Append( (CQElement*)p ) ; }
template< class Element > inline void TLockQueueV1< Element >::Remove( ) { m_queue.Remove( ) ; }
template< class Element > inline BOOL TLockQueueV1< Element >::GetHead( Element* &p ) { CQElement *pTemp = 0 ; BOOL fTemp = m_queue.GetHead( pTemp ) ; p = (Element*)pTemp ; return fTemp ; }
template< class Element > inline BOOL TLockQueueV1< Element >::RemoveAndRelease( ) { return m_queue.RemoveAndRelease( ) ; }
#endif
|