text: ////////////////////////////////////////////////////////////////////////////
  //	Created		: 24.02.2012
  //	Author		: Dmitriy Iassenev
  //	Copyright (C) GSC Game World - 2012
  ////////////////////////////////////////////////////////////////////////////
  
  #ifndef XRAY_NETWORK_INTRUSIVE_SPSC_QUEUE_INLINE_H_INCLUDED
  #define XRAY_NETWORK_INTRUSIVE_SPSC_QUEUE_INLINE_H_INCLUDED
  
  namespace xray {
  namespace network {
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline intrusive_spsc_queue< T, BaseWithMember, MemberNext >::intrusive_spsc_queue		( ) :
  	m_head					( 0 ),
  	m_tail					( 0 ),
  	m_push_thread_id		( -1 ),
  	m_pop_thread_id			( -1 )
  {
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline intrusive_spsc_queue< T, BaseWithMember, MemberNext >::~intrusive_spsc_queue		( )
  {
  	ASSERT					( m_head == 0, "do not forget call pop_null_node before destroying queue" );
  	ASSERT					( m_tail == 0, "unexpected situation" );
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline void intrusive_spsc_queue< T, BaseWithMember, MemberNext >::push_back				( T* const value )
  {
  	ASSERT					( m_head != 0, "do not call push_back after pop_null_node or before push_null_node called" );
  	ASSERT					( m_tail != 0, "unexpected situation" );
  	ASSERT					( m_push_thread_id == (long)threading::current_thread_id() );
  
  	ASSERT					( *(u32*)(&value) != 0xcccccccc );
  
  	value->*MemberNext		= 0;
  	BOOST_INTERLOCKED_EXCHANGE_POINTER	( &(pvoid&)(m_head->*MemberNext), value );
  	m_head					= value;
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline T* intrusive_spsc_queue< T, BaseWithMember, MemberNext >::pop_front				( T*& item_to_delete )
  {
  	ASSERT					( m_head != 0, "do not call pop_front after pop_null_node or before push_null_node called" );
  	ASSERT					( m_tail != 0, "unexpected situation" );
  	ASSERT					( m_pop_thread_id == (long)threading::current_thread_id(), 
  							 "pop_thread_id = %d, current_thread_id = %d", m_pop_thread_id, (u32)threading::current_thread_id() );
  
  	T* const node			= m_tail;
  	T* const value			= node->*MemberNext;
  	if ( !value )
  		return				0;
  
  	item_to_delete			= node;
  	m_tail					= value;
  	return					value;
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline void intrusive_spsc_queue< T, BaseWithMember, MemberNext >::push_null_node			( T* const null_node )
  {
  	ASSERT					( m_head == 0, "do not call push_null_node when pop_null_node hasn't been called" );
  	ASSERT					( m_tail == 0, "unexpected situation" );
  //	ASSERT					( m_push_thread_id == (long)threading::current_thread_id() );
  
  	null_node->*MemberNext	= 0;
  	m_head = m_tail			= null_node;
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline T* intrusive_spsc_queue< T, BaseWithMember, MemberNext >::pop_null_node			( )
  {
  	ASSERT					( m_head != 0, "do not call pop_null_node after pop_null_node or before push_null_node called" );
  	ASSERT					( m_tail != 0, "unexpected situation" );
  	ASSERT					( m_head == m_tail );
  	ASSERT					( m_pop_thread_id == (threading::atomic32_value_type)threading::current_thread_id() );
  
  	T* const result			= m_head;
  	m_head = m_tail			= 0;
  	return					result;
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline void intrusive_spsc_queue< T, BaseWithMember, MemberNext >::set_push_thread_id		( )
  {
  	BOOST_INTERLOCKED_EXCHANGE	( &m_push_thread_id, threading::current_thread_id() );
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline void intrusive_spsc_queue< T, BaseWithMember, MemberNext >::set_pop_thread_id		( )
  {
  	BOOST_INTERLOCKED_EXCHANGE	( &m_pop_thread_id, threading::current_thread_id() );
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline bool intrusive_spsc_queue< T, BaseWithMember, MemberNext >::empty					( ) const
  {
  	ASSERT					( m_head != 0, "do not call push_back after pop_null_node or before push_null_node called" );
  	ASSERT					( m_tail != 0, "unexpected situation" );
  	return					!(m_tail->*MemberNext);
  }
  
  template < typename T, typename BaseWithMember, T* BaseWithMember::*MemberNext >
  inline T* intrusive_spsc_queue< T, BaseWithMember, MemberNext >::null_node					( ) const
  {
  	return					m_tail;
  }
  
  } // namespace network
  } // namespace xray
  
  #endif // #ifndef XRAY_NETWORK_INTRUSIVE_SPSC_QUEUE_INLINE_H_INCLUDED