diff options
Diffstat (limited to 'public/tier1/callqueue.h')
| -rw-r--r-- | public/tier1/callqueue.h | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/public/tier1/callqueue.h b/public/tier1/callqueue.h new file mode 100644 index 0000000..5e0e994 --- /dev/null +++ b/public/tier1/callqueue.h @@ -0,0 +1,203 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef CALLQUEUE_H +#define CALLQUEUE_H + +#include "tier0/tslist.h" +#include "functors.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +//----------------------------------------------------- +// Avert thy eyes! Imagine rather: +// +// void QueueCall( <function>, [args1, [arg2,]...] +// void QueueCall( <object>, <function>, [args1, [arg2,]...] +// void QueueRefCall( <object>, <<function>, [args1, [arg2,]...] +//----------------------------------------------------- + +#define DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL(N) \ + template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \ + void QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + } + +//------------------------------------- + +#define DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL(N) \ + template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \ + void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + } + +//------------------------------------- + +#define DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL(N) \ + template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \ + void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + } + +//------------------------------------- + +#define DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \ + template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \ + void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + } + +//------------------------------------- + +#define DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \ + template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \ + void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + \ + } + +#define FUNC_GENERATE_QUEUE_METHODS() \ + FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL ); \ + FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL ); \ + FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL );\ + FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL ); \ + FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL ) + +//----------------------------------------------------- + +template <typename QUEUE_TYPE = CTSQueue<CFunctor *> > +class CCallQueueT +{ +public: + CCallQueueT() + : m_bNoQueue( false ) + { +#ifdef _DEBUG + m_nCurSerialNumber = 0; + m_nBreakSerialNumber = (unsigned)-1; +#endif + } + + void DisableQueue( bool bDisable ) + { + if ( m_bNoQueue == bDisable ) + { + return; + } + if ( !m_bNoQueue ) + CallQueued(); + + m_bNoQueue = bDisable; + } + + bool IsDisabled() const + { + return m_bNoQueue; + } + + int Count() + { + return m_queue.Count(); + } + + void CallQueued() + { + if ( !m_queue.Count() ) + { + return; + } + + m_queue.PushItem( NULL ); + + CFunctor *pFunctor; + + while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL ) + { +#ifdef _DEBUG + if ( pFunctor->m_nUserID == m_nBreakSerialNumber) + { + m_nBreakSerialNumber = (unsigned)-1; + } +#endif + (*pFunctor)(); + pFunctor->Release(); + } + + } + + void QueueFunctor( CFunctor *pFunctor ) + { + Assert( pFunctor ); + QueueFunctorInternal( RetAddRef( pFunctor ) ); + } + + void Flush() + { + m_queue.PushItem( NULL ); + + CFunctor *pFunctor; + + while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL ) + { + pFunctor->Release(); + } + } + + FUNC_GENERATE_QUEUE_METHODS(); + +private: + void QueueFunctorInternal( CFunctor *pFunctor ) + { + if ( !m_bNoQueue ) + { +#ifdef _DEBUG + pFunctor->m_nUserID = m_nCurSerialNumber++; +#endif + m_queue.PushItem( pFunctor ); + } + else + { + (*pFunctor)(); + pFunctor->Release(); + } + } + + QUEUE_TYPE m_queue; + bool m_bNoQueue; + unsigned m_nCurSerialNumber; + unsigned m_nBreakSerialNumber; +}; + +class CCallQueue : public CCallQueueT<> +{ +}; + +//----------------------------------------------------- +// Optional interface that can be bound to concrete CCallQueue +//----------------------------------------------------- + +class ICallQueue +{ +public: + void QueueFunctor( CFunctor *pFunctor ) + { + QueueFunctorInternal( RetAddRef( pFunctor ) ); + } + + FUNC_GENERATE_QUEUE_METHODS(); + +private: + virtual void QueueFunctorInternal( CFunctor *pFunctor ) = 0; +}; + +#endif // CALLQUEUE_H |