diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/public/vstdlib | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/public/vstdlib')
| -rw-r--r-- | mp/src/public/vstdlib/IKeyValuesSystem.h | 48 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/coroutine.h | 69 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/cvar.h | 25 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/iprocessutils.h | 64 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/jobthread.h | 1344 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/osversion.h | 60 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/pch_vstdlib.h | 51 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/random.h | 111 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/vcover.h | 125 | ||||
| -rw-r--r-- | mp/src/public/vstdlib/vstdlib.h | 33 |
10 files changed, 1930 insertions, 0 deletions
diff --git a/mp/src/public/vstdlib/IKeyValuesSystem.h b/mp/src/public/vstdlib/IKeyValuesSystem.h new file mode 100644 index 00000000..893be6cd --- /dev/null +++ b/mp/src/public/vstdlib/IKeyValuesSystem.h @@ -0,0 +1,48 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#ifndef VSTDLIB_IKEYVALUESSYSTEM_H
+#define VSTDLIB_IKEYVALUESSYSTEM_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vstdlib/vstdlib.h"
+
+// handle to a KeyValues key name symbol
+typedef int HKeySymbol;
+#define INVALID_KEY_SYMBOL (-1)
+
+//-----------------------------------------------------------------------------
+// Purpose: Interface to shared data repository for KeyValues (included in vgui_controls.lib)
+// allows for central data storage point of KeyValues symbol table
+//-----------------------------------------------------------------------------
+class IKeyValuesSystem
+{
+public:
+ // registers the size of the KeyValues in the specified instance
+ // so it can build a properly sized memory pool for the KeyValues objects
+ // the sizes will usually never differ but this is for versioning safety
+ virtual void RegisterSizeofKeyValues(int size) = 0;
+
+ // allocates/frees a KeyValues object from the shared mempool
+ virtual void *AllocKeyValuesMemory(int size) = 0;
+ virtual void FreeKeyValuesMemory(void *pMem) = 0;
+
+ // symbol table access (used for key names)
+ virtual HKeySymbol GetSymbolForString( const char *name, bool bCreate = true ) = 0;
+ virtual const char *GetStringForSymbol(HKeySymbol symbol) = 0;
+
+ // for debugging, adds KeyValues record into global list so we can track memory leaks
+ virtual void AddKeyValuesToMemoryLeakList(void *pMem, HKeySymbol name) = 0;
+ virtual void RemoveKeyValuesFromMemoryLeakList(void *pMem) = 0;
+};
+
+VSTDLIB_INTERFACE IKeyValuesSystem *KeyValuesSystem();
+
+// #define KEYVALUESSYSTEM_INTERFACE_VERSION "KeyValuesSystem002"
+
+#endif // VSTDLIB_IKEYVALUESSYSTEM_H
diff --git a/mp/src/public/vstdlib/coroutine.h b/mp/src/public/vstdlib/coroutine.h new file mode 100644 index 00000000..c367ffa2 --- /dev/null +++ b/mp/src/public/vstdlib/coroutine.h @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: setjmp/longjmp based cooperative multitasking system
+//
+//=============================================================================
+
+#ifndef COROUTINE_H
+#define COROUTINE_H
+#pragma once
+
+#include "vstdlib/vstdlib.h"
+
+// enable this to do coroutine tracing
+// this will tell coroutine API users to set coroutine names
+// #define COROUTINE_TRACE
+
+//-----------------------------------------------------------------------------
+// Purpose: handles running coroutines
+// setjmp/longjmp based cooperative multitasking system
+//-----------------------------------------------------------------------------
+
+// coroutine callback
+typedef void (__cdecl *CoroutineFunc_t )(void *);
+
+// handle to a coroutine
+typedef int32 HCoroutine;
+
+// creates a new coroutine
+// no coroutine code is executed until Coroutine_Continue() is called
+VSTDLIB_INTERFACE HCoroutine Coroutine_Create( CoroutineFunc_t pFunc, void *pvParam );
+
+// continues the specified coroutine
+// returns true if the coroutine is still running, false otherwise
+VSTDLIB_INTERFACE bool Coroutine_Continue( HCoroutine hCoroutine, const char *pchName = NULL );
+
+// cancels a currently running coroutine
+VSTDLIB_INTERFACE void Coroutine_Cancel( HCoroutine hCoroutine );
+
+// 'load' a coroutine only to debug it - immediately breaks into debugger
+// when continued, pops back to the prior coroutine
+VSTDLIB_INTERFACE void Coroutine_DebugBreak( HCoroutine hCoroutine );
+
+// Load a coroutine and generate an assert. Used to get a minidump of a job
+VSTDLIB_INTERFACE void Coroutine_DebugAssert( HCoroutine hCoroutine, const char *pchMsg );
+
+// called from the coroutine to return control to the main thread
+VSTDLIB_INTERFACE void Coroutine_YieldToMain();
+
+// returns true if the code is currently running inside of a coroutine
+VSTDLIB_INTERFACE bool Coroutine_IsActive();
+
+// returns a handle the currently active coroutine
+VSTDLIB_INTERFACE HCoroutine Coroutine_GetCurrentlyActive();
+
+// call when a thread is quiting to release any per-thread memory
+VSTDLIB_INTERFACE void Coroutine_ReleaseThreadMemory();
+
+// runs a self-test of the coroutine system
+VSTDLIB_INTERFACE bool Coroutine_Test();
+
+// memory validation
+VSTDLIB_INTERFACE void Coroutine_ValidateGlobals( class CValidator &validator );
+
+// for debugging purposes - returns stack depth of current coroutine
+VSTDLIB_INTERFACE size_t Coroutine_GetStackDepth();
+
+
+
+#endif // COROUTINE_H
diff --git a/mp/src/public/vstdlib/cvar.h b/mp/src/public/vstdlib/cvar.h new file mode 100644 index 00000000..57a39adc --- /dev/null +++ b/mp/src/public/vstdlib/cvar.h @@ -0,0 +1,25 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#if !defined( CVAR_H )
+#define CVAR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vstdlib/vstdlib.h"
+#include "icvar.h"
+
+
+//-----------------------------------------------------------------------------
+// Returns a CVar dictionary for tool usage
+//-----------------------------------------------------------------------------
+VSTDLIB_INTERFACE CreateInterfaceFn VStdLib_GetICVarFactory();
+
+
+#endif // CVAR_H
diff --git a/mp/src/public/vstdlib/iprocessutils.h b/mp/src/public/vstdlib/iprocessutils.h new file mode 100644 index 00000000..6eb64486 --- /dev/null +++ b/mp/src/public/vstdlib/iprocessutils.h @@ -0,0 +1,64 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef IPROCESSUTILS_H
+#define IPROCESSUTILS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "appframework/IAppSystem.h"
+
+
+//-----------------------------------------------------------------------------
+// Handle to a process
+//-----------------------------------------------------------------------------
+typedef int ProcessHandle_t;
+enum
+{
+ PROCESS_HANDLE_INVALID = 0,
+};
+
+
+//-----------------------------------------------------------------------------
+// Interface version
+//-----------------------------------------------------------------------------
+#define PROCESS_UTILS_INTERFACE_VERSION "VProcessUtils001"
+
+
+//-----------------------------------------------------------------------------
+// Interface for makefiles to build differently depending on where they are run from
+//-----------------------------------------------------------------------------
+abstract_class IProcessUtils : public IAppSystem
+{
+public:
+ // Starts, stops a process
+ virtual ProcessHandle_t StartProcess( const char *pCommandLine, bool bConnectStdPipes ) = 0;
+ virtual ProcessHandle_t StartProcess( int argc, const char **argv, bool bConnectStdPipes ) = 0;
+ virtual void CloseProcess( ProcessHandle_t hProcess ) = 0;
+ virtual void AbortProcess( ProcessHandle_t hProcess ) = 0;
+
+ // Returns true if a process is complete
+ virtual bool IsProcessComplete( ProcessHandle_t hProcess ) = 0;
+
+ // Waits until a process is complete
+ virtual void WaitUntilProcessCompletes( ProcessHandle_t hProcess ) = 0;
+
+ // Methods used to write input into a process
+ virtual int SendProcessInput( ProcessHandle_t hProcess, char *pBuf, int nBufLen ) = 0;
+
+ // Methods used to read output back from a process
+ virtual int GetProcessOutputSize( ProcessHandle_t hProcess ) = 0;
+ virtual int GetProcessOutput( ProcessHandle_t hProcess, char *pBuf, int nBufLen ) = 0;
+
+ // Returns the exit code for the process. Doesn't work unless the process is complete
+ virtual int GetProcessExitCode( ProcessHandle_t hProcess ) = 0;
+};
+
+
+#endif // IPROCESSUTILS_H
diff --git a/mp/src/public/vstdlib/jobthread.h b/mp/src/public/vstdlib/jobthread.h new file mode 100644 index 00000000..ed453cf9 --- /dev/null +++ b/mp/src/public/vstdlib/jobthread.h @@ -0,0 +1,1344 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A utility for a discrete job-oriented worker thread.
+//
+// The class CThreadPool is both the job queue, and the
+// worker thread. Except when the main thread attempts to
+// synchronously execute a job, most of the inter-thread locking
+// on the queue.
+//
+// The queue threading model uses a manual reset event for optimal
+// throughput. Adding to the queue is guarded by a semaphore that
+// will block the inserting thread if the queue has overflown.
+// This prevents the worker thread from being starved out even if
+// not running at a higher priority than the master thread.
+//
+// The thread function waits for jobs, services jobs, and manages
+// communication between the worker and master threads. The nature
+// of the work is opaque to the Executer.
+//
+// CJob instances actually do the work. The base class
+// calls virtual methods for job primitives, so derivations don't
+// need to worry about threading models. All of the variants of
+// job and OS can be expressed in this hierarchy. Instances of
+// CJob are the items placed in the queue, and by
+// overriding the job primitives they are the manner by which
+// users of the Executer control the state of the job.
+//
+//=============================================================================
+
+#include <limits.h>
+#include "tier0/threadtools.h"
+#include "tier1/refcount.h"
+#include "tier1/utllinkedlist.h"
+#include "tier1/utlvector.h"
+#include "tier1/functors.h"
+#include "tier0/vprof_telemetry.h"
+
+#include "vstdlib/vstdlib.h"
+
+#ifndef JOBTHREAD_H
+#define JOBTHREAD_H
+
+#ifdef AddJob // windows.h print function collisions
+#undef AddJob
+#undef GetJob
+#endif
+
+#ifdef VSTDLIB_DLL_EXPORT
+#define JOB_INTERFACE DLL_EXPORT
+#define JOB_OVERLOAD DLL_GLOBAL_EXPORT
+#define JOB_CLASS DLL_CLASS_EXPORT
+#else
+#define JOB_INTERFACE DLL_IMPORT
+#define JOB_OVERLOAD DLL_GLOBAL_IMPORT
+#define JOB_CLASS DLL_CLASS_IMPORT
+#endif
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+class CJob;
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+enum JobStatusEnum_t
+{
+ // Use negative for errors
+ JOB_OK, // operation is successful
+ JOB_STATUS_PENDING, // file is properly queued, waiting for service
+ JOB_STATUS_INPROGRESS, // file is being accessed
+ JOB_STATUS_ABORTED, // file was aborted by caller
+ JOB_STATUS_UNSERVICED, // file is not yet queued
+};
+
+typedef int JobStatus_t;
+
+enum JobFlags_t
+{
+ JF_IO = ( 1 << 0 ), // The job primarily blocks on IO or hardware
+ JF_BOOST_THREAD = ( 1 << 1 ), // Up the thread priority to max allowed while processing task
+ JF_SERIAL = ( 1 << 2 ), // Job cannot be executed out of order relative to other "strict" jobs
+ JF_QUEUE = ( 1 << 3 ), // Queue it, even if not an IO job
+};
+
+enum JobPriority_t
+{
+ JP_LOW,
+ JP_NORMAL,
+ JP_HIGH
+};
+
+#define TP_MAX_POOL_THREADS 64
+struct ThreadPoolStartParams_t
+{
+ ThreadPoolStartParams_t( bool bIOThreads = false, unsigned nThreads = -1, int *pAffinities = NULL, ThreeState_t fDistribute = TRS_NONE, unsigned nStackSize = -1, int iThreadPriority = SHRT_MIN )
+ : bIOThreads( bIOThreads ), nThreads( nThreads ), fDistribute( fDistribute ), nStackSize( nStackSize ), iThreadPriority( iThreadPriority ), nThreadsMax( -1 )
+ {
+ bExecOnThreadPoolThreadsOnly = false;
+
+ bUseAffinityTable = ( pAffinities != NULL ) && ( fDistribute == TRS_TRUE ) && ( nThreads != -1 );
+ if ( bUseAffinityTable )
+ {
+ // user supplied an optional 1:1 affinity mapping to override normal distribute behavior
+ nThreads = MIN( TP_MAX_POOL_THREADS, nThreads );
+ for ( unsigned int i = 0; i < nThreads; i++ )
+ {
+ iAffinityTable[i] = pAffinities[i];
+ }
+ }
+ }
+
+ int nThreads;
+ int nThreadsMax;
+ ThreeState_t fDistribute;
+ int nStackSize;
+ int iThreadPriority;
+ int iAffinityTable[TP_MAX_POOL_THREADS];
+
+ bool bIOThreads : 1;
+ bool bUseAffinityTable : 1;
+ bool bExecOnThreadPoolThreadsOnly : 1;
+};
+
+//-----------------------------------------------------------------------------
+//
+// IThreadPool
+//
+//-----------------------------------------------------------------------------
+
+typedef bool (*JobFilter_t)( CJob * );
+
+//---------------------------------------------------------
+// Messages supported through the CallWorker() method
+//---------------------------------------------------------
+enum ThreadPoolMessages_t
+{
+ TPM_EXIT, // Exit the thread
+ TPM_SUSPEND, // Suspend after next operation
+ TPM_RUNFUNCTOR, // Run functor, reply when done.
+};
+
+//---------------------------------------------------------
+
+abstract_class IThreadPool : public IRefCounted
+{
+public:
+ virtual ~IThreadPool() {};
+
+ //-----------------------------------------------------
+ // Thread functions
+ //-----------------------------------------------------
+ virtual bool Start( const ThreadPoolStartParams_t &startParams = ThreadPoolStartParams_t() ) = 0;
+ virtual bool Stop( int timeout = TT_INFINITE ) = 0;
+
+ //-----------------------------------------------------
+ // Functions for any thread
+ //-----------------------------------------------------
+ virtual unsigned GetJobCount() = 0;
+ virtual int NumThreads() = 0;
+ virtual int NumIdleThreads() = 0;
+
+ //-----------------------------------------------------
+ // Pause/resume processing jobs
+ //-----------------------------------------------------
+ virtual int SuspendExecution() = 0;
+ virtual int ResumeExecution() = 0;
+
+ //-----------------------------------------------------
+ // Offer the current thread to the pool
+ //-----------------------------------------------------
+ virtual int YieldWait( CThreadEvent **pEvents, int nEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) = 0;
+ virtual int YieldWait( CJob **, int nJobs, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) = 0;
+ virtual void Yield( unsigned timeout ) = 0;
+
+ bool YieldWait( CThreadEvent &event, unsigned timeout = TT_INFINITE );
+ bool YieldWait( CJob *, unsigned timeout = TT_INFINITE );
+
+ //-----------------------------------------------------
+ // Add a native job to the queue (master thread)
+ //-----------------------------------------------------
+ virtual void AddJob( CJob * ) = 0;
+
+ //-----------------------------------------------------
+ // All threads execute pFunctor asap. Thread will either wake up
+ // and execute or execute pFunctor right after completing current job and
+ // before looking for another job.
+ //-----------------------------------------------------
+ virtual void ExecuteHighPriorityFunctor( CFunctor *pFunctor ) = 0;
+
+ //-----------------------------------------------------
+ // Add an function object to the queue (master thread)
+ //-----------------------------------------------------
+ virtual void AddFunctor( CFunctor *pFunctor, CJob **ppJob = NULL, const char *pszDescription = NULL, unsigned flags = 0 ) { AddFunctorInternal( RetAddRef( pFunctor ), ppJob, pszDescription, flags ); }
+
+ //-----------------------------------------------------
+ // Change the priority of an active job
+ //-----------------------------------------------------
+ virtual void ChangePriority( CJob *p, JobPriority_t priority ) = 0;
+
+ //-----------------------------------------------------
+ // Bulk job manipulation (blocking)
+ //-----------------------------------------------------
+ int ExecuteAll( JobFilter_t pfnFilter = NULL ) { return ExecuteToPriority( JP_LOW, pfnFilter ); }
+ virtual int ExecuteToPriority( JobPriority_t toPriority, JobFilter_t pfnFilter = NULL ) = 0;
+ virtual int AbortAll() = 0;
+
+ //-----------------------------------------------------
+ virtual void Reserved1() = 0;
+
+ //-----------------------------------------------------
+ // Add an arbitrary call to the queue (master thread)
+ //
+ // Avert thy eyes! Imagine rather:
+ //
+ // CJob *AddCall( <function>, [args1, [arg2,]...]
+ // CJob *AddCall( <object>, <function>, [args1, [arg2,]...]
+ // CJob *AddRefCall( <object>, <function>, [args1, [arg2,]...]
+ // CJob *QueueCall( <function>, [args1, [arg2,]...]
+ // CJob *QueueCall( <object>, <function>, [args1, [arg2,]...]
+ //-----------------------------------------------------
+
+ #define DEFINE_NONMEMBER_ADD_CALL(N) \
+ template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *AddCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ if ( !NumIdleThreads() ) \
+ { \
+ pJob = GetDummyJob(); \
+ FunctorDirectCall( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ } \
+ else \
+ { \
+ AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \
+ } \
+ \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_MEMBER_ADD_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ if ( !NumIdleThreads() ) \
+ { \
+ pJob = GetDummyJob(); \
+ FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ } \
+ else \
+ { \
+ AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \
+ } \
+ \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_CONST_MEMBER_ADD_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ if ( !NumIdleThreads() ) \
+ { \
+ pJob = GetDummyJob(); \
+ FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ } \
+ else \
+ { \
+ AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \
+ } \
+ \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_REF_COUNTING_MEMBER_ADD_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ if ( !NumIdleThreads() ) \
+ { \
+ pJob = GetDummyJob(); \
+ FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ } \
+ else \
+ { \
+ AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \
+ } \
+ \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ if ( !NumIdleThreads() ) \
+ { \
+ pJob = GetDummyJob(); \
+ FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ } \
+ else \
+ { \
+ AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \
+ } \
+ \
+ return pJob; \
+ }
+
+ //-----------------------------------------------------------------------------
+
+ #define DEFINE_NONMEMBER_QUEUE_CALL(N) \
+ template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_CONST_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \
+ return pJob; \
+ }
+
+ //-------------------------------------
+
+ #define DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ CJob *pJob; \
+ AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \
+ \
+ return pJob; \
+ }
+
+ FUNC_GENERATE_ALL( DEFINE_NONMEMBER_ADD_CALL );
+ FUNC_GENERATE_ALL( DEFINE_MEMBER_ADD_CALL );
+ FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_ADD_CALL );
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_ADD_CALL );
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL );
+ FUNC_GENERATE_ALL( DEFINE_NONMEMBER_QUEUE_CALL );
+ FUNC_GENERATE_ALL( DEFINE_MEMBER_QUEUE_CALL );
+ FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_QUEUE_CALL );
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL );
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL );
+
+ #undef DEFINE_NONMEMBER_ADD_CALL
+ #undef DEFINE_MEMBER_ADD_CALL
+ #undef DEFINE_CONST_MEMBER_ADD_CALL
+ #undef DEFINE_REF_COUNTING_MEMBER_ADD_CALL
+ #undef DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL
+ #undef DEFINE_NONMEMBER_QUEUE_CALL
+ #undef DEFINE_MEMBER_QUEUE_CALL
+ #undef DEFINE_CONST_MEMBER_QUEUE_CALL
+ #undef DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL
+ #undef DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL
+
+private:
+ virtual void AddFunctorInternal( CFunctor *, CJob ** = NULL, const char *pszDescription = NULL, unsigned flags = 0 ) = 0;
+
+ //-----------------------------------------------------
+ // Services for internal use by job instances
+ //-----------------------------------------------------
+ friend class CJob;
+
+ virtual CJob *GetDummyJob() = 0;
+
+public:
+ virtual void Distribute( bool bDistribute = true, int *pAffinityTable = NULL ) = 0;
+
+ virtual bool Start( const ThreadPoolStartParams_t &startParams, const char *pszNameOverride ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+
+JOB_INTERFACE IThreadPool *CreateThreadPool();
+JOB_INTERFACE void DestroyThreadPool( IThreadPool *pPool );
+
+//-------------------------------------
+
+JOB_INTERFACE void RunThreadPoolTests();
+
+//-----------------------------------------------------------------------------
+
+JOB_INTERFACE IThreadPool *g_pThreadPool;
+
+//-----------------------------------------------------------------------------
+// Class to combine the metadata for an operation and the ability to perform
+// the operation. Meant for inheritance. All functions inline, defers to executor
+//-----------------------------------------------------------------------------
+DECLARE_POINTER_HANDLE( ThreadPoolData_t );
+#define JOB_NO_DATA ((ThreadPoolData_t)-1)
+
+class CJob : public CRefCounted1<IRefCounted, CRefCountServiceMT>
+{
+public:
+ CJob( JobPriority_t priority = JP_NORMAL )
+ : m_status( JOB_STATUS_UNSERVICED ),
+ m_ThreadPoolData( JOB_NO_DATA ),
+ m_priority( priority ),
+ m_flags( 0 ),
+ m_pThreadPool( NULL ),
+ m_CompleteEvent( true ),
+ m_iServicingThread( -1 )
+ {
+ m_szDescription[ 0 ] = 0;
+ }
+
+ //-----------------------------------------------------
+ // Priority (not thread safe)
+ //-----------------------------------------------------
+ void SetPriority( JobPriority_t priority ) { m_priority = priority; }
+ JobPriority_t GetPriority() const { return m_priority; }
+
+ //-----------------------------------------------------
+
+ void SetFlags( unsigned flags ) { m_flags = flags; }
+ unsigned GetFlags() const { return m_flags; }
+
+ //-----------------------------------------------------
+
+ void SetServiceThread( int iServicingThread ) { m_iServicingThread = (char)iServicingThread; }
+ int GetServiceThread() const { return m_iServicingThread; }
+ void ClearServiceThread() { m_iServicingThread = -1; }
+
+ //-----------------------------------------------------
+ // Fast queries
+ //-----------------------------------------------------
+ bool Executed() const { return ( m_status == JOB_OK ); }
+ bool CanExecute() const { return ( m_status == JOB_STATUS_PENDING || m_status == JOB_STATUS_UNSERVICED ); }
+ bool IsFinished() const { return ( m_status != JOB_STATUS_PENDING && m_status != JOB_STATUS_INPROGRESS && m_status != JOB_STATUS_UNSERVICED ); }
+ JobStatus_t GetStatus() const { return m_status; }
+
+ /// Slam the status to a particular value. This is named "slam" instead of "set,"
+ /// to warn you that it should only be used in unusual situations. Otherwise, the
+ /// job manager really should manage the status for you, and you should not manhandle it.
+ void SlamStatus(JobStatus_t s) { m_status = s; }
+
+ //-----------------------------------------------------
+ // Try to acquire ownership (to satisfy). If you take the lock, you must either execute or abort.
+ //-----------------------------------------------------
+ bool TryLock() { return m_mutex.TryLock(); }
+ void Lock() { m_mutex.Lock(); }
+ void Unlock() { m_mutex.Unlock(); }
+
+ //-----------------------------------------------------
+ // Thread event support (safe for NULL this to simplify code )
+ //-----------------------------------------------------
+ bool WaitForFinish( uint32 dwTimeout = TT_INFINITE ) { if (!this) return true; return ( !IsFinished() ) ? g_pThreadPool->YieldWait( this, dwTimeout ) : true; }
+ bool WaitForFinishAndRelease( uint32 dwTimeout = TT_INFINITE ) { if (!this) return true; bool bResult = WaitForFinish( dwTimeout); Release(); return bResult; }
+ CThreadEvent *AccessEvent() { return &m_CompleteEvent; }
+
+ //-----------------------------------------------------
+ // Perform the job
+ //-----------------------------------------------------
+ JobStatus_t Execute();
+ JobStatus_t TryExecute();
+ JobStatus_t ExecuteAndRelease() { JobStatus_t status = Execute(); Release(); return status; }
+ JobStatus_t TryExecuteAndRelease() { JobStatus_t status = TryExecute(); Release(); return status; }
+
+ //-----------------------------------------------------
+ // Terminate the job, discard if partially or wholly fulfilled
+ //-----------------------------------------------------
+ JobStatus_t Abort( bool bDiscard = true );
+
+ virtual char const *Describe() { return m_szDescription[ 0 ] ? m_szDescription : "Job"; }
+ virtual void SetDescription( const char *pszDescription )
+ {
+ if( pszDescription )
+ {
+ Q_strncpy( m_szDescription, pszDescription, sizeof( m_szDescription ) );
+ }
+ else
+ {
+ m_szDescription[ 0 ] = 0;
+ }
+ }
+
+private:
+ //-----------------------------------------------------
+ friend class CThreadPool;
+
+ JobStatus_t m_status;
+ JobPriority_t m_priority;
+ CThreadMutex m_mutex;
+ unsigned char m_flags;
+ char m_iServicingThread;
+ short m_reserved;
+ ThreadPoolData_t m_ThreadPoolData;
+ IThreadPool * m_pThreadPool;
+ CThreadEvent m_CompleteEvent;
+ char m_szDescription[ 32 ];
+
+private:
+ //-----------------------------------------------------
+ CJob( const CJob &fromRequest );
+ void operator=(const CJob &fromRequest );
+
+ virtual JobStatus_t DoExecute() = 0;
+ virtual JobStatus_t DoAbort( bool bDiscard ) { return JOB_STATUS_ABORTED; }
+ virtual void DoCleanup() {}
+};
+
+//-----------------------------------------------------------------------------
+
+class CFunctorJob : public CJob
+{
+public:
+ CFunctorJob( CFunctor *pFunctor, const char *pszDescription = NULL )
+ : m_pFunctor( pFunctor )
+ {
+ if ( pszDescription )
+ {
+ Q_strncpy( m_szDescription, pszDescription, sizeof(m_szDescription) );
+ }
+ else
+ {
+ m_szDescription[0] = 0;
+ }
+ }
+
+ virtual JobStatus_t DoExecute()
+ {
+ (*m_pFunctor)();
+ return JOB_OK;
+ }
+
+ const char *Describe()
+ {
+ return m_szDescription;
+ }
+
+private:
+ CRefPtr<CFunctor> m_pFunctor;
+ char m_szDescription[16];
+};
+
+//-----------------------------------------------------------------------------
+// Utility for managing multiple jobs
+//-----------------------------------------------------------------------------
+
+class CJobSet
+{
+public:
+ CJobSet( CJob *pJob = NULL )
+ {
+ if ( pJob )
+ {
+ m_jobs.AddToTail( pJob );
+ }
+ }
+
+ CJobSet( CJob **ppJobs, int nJobs )
+ {
+ if ( ppJobs )
+ {
+ m_jobs.AddMultipleToTail( nJobs, ppJobs );
+ }
+ }
+
+ ~CJobSet()
+ {
+ for ( int i = 0; i < m_jobs.Count(); i++ )
+ {
+ m_jobs[i]->Release();
+ }
+ }
+
+ void operator+=( CJob *pJob )
+ {
+ m_jobs.AddToTail( pJob );
+ }
+
+ void operator-=( CJob *pJob )
+ {
+ m_jobs.FindAndRemove( pJob );
+ }
+
+ void Execute( bool bRelease = true )
+ {
+ for ( int i = 0; i < m_jobs.Count(); i++ )
+ {
+ m_jobs[i]->Execute();
+ if ( bRelease )
+ {
+ m_jobs[i]->Release();
+ }
+ }
+
+ if ( bRelease )
+ {
+ m_jobs.RemoveAll();
+ }
+ }
+
+ void Abort( bool bRelease = true )
+ {
+ for ( int i = 0; i < m_jobs.Count(); i++ )
+ {
+ m_jobs[i]->Abort();
+ if ( bRelease )
+ {
+ m_jobs[i]->Release();
+ }
+ }
+
+ if ( bRelease )
+ {
+ m_jobs.RemoveAll();
+ }
+ }
+
+ void WaitForFinish( bool bRelease = true )
+ {
+ for ( int i = 0; i < m_jobs.Count(); i++ )
+ {
+ m_jobs[i]->WaitForFinish();
+ if ( bRelease )
+ {
+ m_jobs[i]->Release();
+ }
+ }
+
+ if ( bRelease )
+ {
+ m_jobs.RemoveAll();
+ }
+ }
+
+ void WaitForFinish( IThreadPool *pPool, bool bRelease = true )
+ {
+ pPool->YieldWait( m_jobs.Base(), m_jobs.Count() );
+
+ if ( bRelease )
+ {
+ for ( int i = 0; i < m_jobs.Count(); i++ )
+ {
+ m_jobs[i]->Release();
+ }
+
+ m_jobs.RemoveAll();
+ }
+ }
+
+private:
+ CUtlVectorFixed<CJob *, 16> m_jobs;
+};
+
+//-----------------------------------------------------------------------------
+// Job helpers
+//-----------------------------------------------------------------------------
+
+#define ThreadExecute g_pThreadPool->QueueCall
+#define ThreadExecuteRef g_pThreadPool->QueueRefCall
+
+#define BeginExecuteParallel() do { CJobSet jobSet
+#define EndExecuteParallel() jobSet.WaitForFinish( g_pThreadPool ); } while (0)
+
+#define ExecuteParallel jobSet += g_pThreadPool->QueueCall
+#define ExecuteRefParallel jobSet += g_pThreadPool->QueueCallRef
+
+
+//-----------------------------------------------------------------------------
+// Work splitting: array split, best when cost per item is roughly equal
+//-----------------------------------------------------------------------------
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389)
+#pragma warning(disable:4018)
+#pragma warning(disable:4701)
+#endif
+
+#define DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL(N) \
+ template <typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N, typename ITERTYPE1, typename ITERTYPE2> \
+ void IterRangeParallel(FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_ADDL_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ const int MAX_THREADS = 16; \
+ int nIdle = g_pThreadPool->NumIdleThreads(); \
+ ITERTYPE1 range = to - from; \
+ int nThreads = MIN( nIdle + 1, range ); \
+ if ( nThreads > MAX_THREADS ) \
+ { \
+ nThreads = MAX_THREADS; \
+ } \
+ if ( nThreads < 2 ) \
+ { \
+ FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ } \
+ else \
+ { \
+ ITERTYPE1 nIncrement = range / nThreads; \
+ \
+ CJobSet jobSet; \
+ while ( --nThreads ) \
+ { \
+ ITERTYPE2 thisTo = from + nIncrement; \
+ jobSet += g_pThreadPool->AddCall( pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ from = thisTo; \
+ } \
+ FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ jobSet.WaitForFinish( g_pThreadPool ); \
+ } \
+ \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL );
+
+#define DEFINE_MEMBER_ITER_RANGE_PARALLEL(N) \
+ template <typename OBJECT_TYPE, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N, typename ITERTYPE1, typename ITERTYPE2> \
+ void IterRangeParallel(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_ADDL_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ const int MAX_THREADS = 16; \
+ int nIdle = g_pThreadPool->NumIdleThreads(); \
+ ITERTYPE1 range = to - from; \
+ int nThreads = MIN( nIdle + 1, range ); \
+ if ( nThreads > MAX_THREADS ) \
+ { \
+ nThreads = MAX_THREADS; \
+ } \
+ if ( nThreads < 2 ) \
+ { \
+ FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ } \
+ else \
+ { \
+ ITERTYPE1 nIncrement = range / nThreads; \
+ \
+ CJobSet jobSet; \
+ while ( --nThreads ) \
+ { \
+ ITERTYPE2 thisTo = from + nIncrement; \
+ jobSet += g_pThreadPool->AddCall( pObject, pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ from = thisTo; \
+ } \
+ FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ jobSet.WaitForFinish( g_pThreadPool ); \
+ } \
+ \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_MEMBER_ITER_RANGE_PARALLEL );
+
+//-----------------------------------------------------------------------------
+// Work splitting: competitive, best when cost per item varies a lot
+//-----------------------------------------------------------------------------
+
+template <typename T>
+class CJobItemProcessor
+{
+public:
+ typedef T ItemType_t;
+ void Begin() {}
+ // void Process( ItemType_t & ) {}
+ void End() {}
+};
+
+template <typename T>
+class CFuncJobItemProcessor : public CJobItemProcessor<T>
+{
+public:
+ void Init(void (*pfnProcess)( T & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL )
+ {
+ m_pfnProcess = pfnProcess;
+ m_pfnBegin = pfnBegin;
+ m_pfnEnd = pfnEnd;
+ }
+
+ //CFuncJobItemProcessor(OBJECT_TYPE_PTR pObject, void (FUNCTION_CLASS::*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL );
+ void Begin() { if ( m_pfnBegin ) (*m_pfnBegin)(); }
+ void Process( T &item ) { (*m_pfnProcess)( item ); }
+ void End() { if ( m_pfnEnd ) (*m_pfnEnd)(); }
+
+protected:
+ void (*m_pfnProcess)( T & );
+ void (*m_pfnBegin)();
+ void (*m_pfnEnd)();
+};
+
+template <typename T, class OBJECT_TYPE, class FUNCTION_CLASS = OBJECT_TYPE >
+class CMemberFuncJobItemProcessor : public CJobItemProcessor<T>
+{
+public:
+ void Init( OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( T & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL )
+ {
+ m_pObject = pObject;
+ m_pfnProcess = pfnProcess;
+ m_pfnBegin = pfnBegin;
+ m_pfnEnd = pfnEnd;
+ }
+
+ void Begin() { if ( m_pfnBegin ) ((*m_pObject).*m_pfnBegin)(); }
+ void Process( T &item ) { ((*m_pObject).*m_pfnProcess)( item ); }
+ void End() { if ( m_pfnEnd ) ((*m_pObject).*m_pfnEnd)(); }
+
+protected:
+ OBJECT_TYPE *m_pObject;
+ void (FUNCTION_CLASS::*m_pfnProcess)( T & );
+ void (FUNCTION_CLASS::*m_pfnBegin)();
+ void (FUNCTION_CLASS::*m_pfnEnd)();
+};
+
+template <typename ITEM_TYPE, class ITEM_PROCESSOR_TYPE>
+class CParallelProcessor
+{
+public:
+ CParallelProcessor( const char *pszDescription )
+ {
+ m_pItems = m_pLimit= 0;
+ m_szDescription = pszDescription;
+ }
+
+ void Run( ITEM_TYPE *pItems, unsigned nItems, int nMaxParallel = INT_MAX, IThreadPool *pThreadPool = NULL )
+ {
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "Run %s %d", m_szDescription, nItems );
+
+ if ( nItems == 0 )
+ return;
+
+ if ( !pThreadPool )
+ {
+ pThreadPool = g_pThreadPool;
+ }
+
+ m_pItems = pItems;
+ m_pLimit = pItems + nItems;
+
+ int nJobs = nItems - 1;
+
+ if ( nJobs > nMaxParallel )
+ {
+ nJobs = nMaxParallel;
+ }
+
+ if (! pThreadPool ) // only possible on linux
+ {
+ DoExecute( );
+ return;
+ }
+
+ int nThreads = pThreadPool->NumThreads();
+ if ( nJobs > nThreads )
+ {
+ nJobs = nThreads;
+ }
+
+ if ( nJobs > 1 )
+ {
+ CJob **jobs = (CJob **)stackalloc( nJobs * sizeof(CJob **) );
+ int i = nJobs;
+
+ while( i-- )
+ {
+ jobs[i] = pThreadPool->QueueCall( this, &CParallelProcessor<ITEM_TYPE, ITEM_PROCESSOR_TYPE>::DoExecute );
+ jobs[i]->SetDescription( m_szDescription );
+ }
+
+ DoExecute();
+
+ for ( i = 0; i < nJobs; i++ )
+ {
+ jobs[i]->Abort(); // will either abort ones that never got a thread, or noop on ones that did
+ jobs[i]->Release();
+ }
+ }
+ else
+ {
+ DoExecute();
+ }
+ }
+
+ ITEM_PROCESSOR_TYPE m_ItemProcessor;
+
+private:
+ void DoExecute()
+ {
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "DoExecute %s", m_szDescription );
+
+ if ( m_pItems < m_pLimit )
+ {
+ m_ItemProcessor.Begin();
+
+ ITEM_TYPE *pLimit = m_pLimit;
+
+ for (;;)
+ {
+ ITEM_TYPE *pCurrent = m_pItems++;
+ if ( pCurrent < pLimit )
+ {
+ m_ItemProcessor.Process( *pCurrent );
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ m_ItemProcessor.End();
+ }
+ }
+ CInterlockedPtr<ITEM_TYPE> m_pItems;
+ ITEM_TYPE * m_pLimit;
+ const char * m_szDescription;
+};
+
+template <typename ITEM_TYPE>
+inline void ParallelProcess( const char *pszDescription, ITEM_TYPE *pItems, unsigned nItems, void (*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX )
+{
+ CParallelProcessor<ITEM_TYPE, CFuncJobItemProcessor<ITEM_TYPE> > processor( pszDescription );
+ processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd );
+ processor.Run( pItems, nItems, nMaxParallel );
+
+}
+
+template <typename ITEM_TYPE, typename OBJECT_TYPE, typename FUNCTION_CLASS >
+inline void ParallelProcess( const char *pszDescription, ITEM_TYPE *pItems, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( ITEM_TYPE & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX )
+{
+ CParallelProcessor<ITEM_TYPE, CMemberFuncJobItemProcessor<ITEM_TYPE, OBJECT_TYPE, FUNCTION_CLASS> > processor( pszDescription );
+ processor.m_ItemProcessor.Init( pObject, pfnProcess, pfnBegin, pfnEnd );
+ processor.Run( pItems, nItems, nMaxParallel );
+}
+
+// Parallel Process that lets you specify threadpool
+template <typename ITEM_TYPE>
+inline void ParallelProcess( const char *pszDescription, IThreadPool *pPool, ITEM_TYPE *pItems, unsigned nItems, void (*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX )
+{
+ CParallelProcessor<ITEM_TYPE, CFuncJobItemProcessor<ITEM_TYPE> > processor( pszDescription );
+ processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd );
+ processor.Run( pItems, nItems, nMaxParallel, pPool );
+}
+
+
+template <class ITEM_PROCESSOR_TYPE>
+class CParallelLoopProcessor
+{
+public:
+ CParallelLoopProcessor( const char *pszDescription )
+ {
+ m_lIndex = m_lLimit= 0;
+ m_nActive = 0;
+ m_szDescription = pszDescription;
+ }
+
+ void Run( long lBegin, long nItems, int nMaxParallel = INT_MAX )
+ {
+ if ( nItems )
+ {
+ m_lIndex = lBegin;
+ m_lLimit = lBegin + nItems;
+ int i = g_pThreadPool->NumIdleThreads();
+
+ if ( nMaxParallel < i)
+ {
+ i = nMaxParallel;
+ }
+
+ while( i-- )
+ {
+ ++m_nActive;
+ ThreadExecute( this, &CParallelLoopProcessor<ITEM_PROCESSOR_TYPE>::DoExecute )->Release();
+ }
+
+ ++m_nActive;
+ DoExecute();
+
+ while ( m_nActive )
+ {
+ ThreadPause();
+ }
+ }
+ }
+
+ ITEM_PROCESSOR_TYPE m_ItemProcessor;
+
+private:
+ void DoExecute()
+ {
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "DoExecute %s", m_szDescription );
+
+ m_ItemProcessor.Begin();
+
+ long lLimit = m_lLimit;
+
+ for (;;)
+ {
+ long lIndex = m_lIndex ++;
+ if ( lIndex < lLimit )
+ {
+ m_ItemProcessor.Process( lIndex );
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ m_ItemProcessor.End();
+
+ --m_nActive;
+ }
+ CInterlockedInt m_lIndex;
+ long m_lLimit;
+ CInterlockedInt m_nActive;
+ const char * m_szDescription;
+};
+
+inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, void (*pfnProcess)( long const & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX )
+{
+ CParallelLoopProcessor< CFuncJobItemProcessor< long const > > processor( szDescription );
+ processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd );
+ processor.Run( lBegin, nItems, nMaxParallel );
+
+}
+
+template < typename OBJECT_TYPE, typename FUNCTION_CLASS >
+inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( long const & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX )
+{
+ CParallelLoopProcessor< CMemberFuncJobItemProcessor<long const, OBJECT_TYPE, FUNCTION_CLASS> > processor( szDescription );
+ processor.m_ItemProcessor.Init( pObject, pfnProcess, pfnBegin, pfnEnd );
+ processor.Run( lBegin, nItems, nMaxParallel );
+}
+
+
+template <class Derived>
+class CParallelProcessorBase
+{
+protected:
+ typedef CParallelProcessorBase<Derived> ThisParallelProcessorBase_t;
+ typedef Derived ThisParallelProcessorDerived_t;
+
+public:
+ CParallelProcessorBase()
+ {
+ m_nActive = 0;
+ m_szDescription = NULL;
+ }
+ void SetDescription( const char *pszDescription )
+ {
+ m_szDescription = pszDescription;
+ }
+
+protected:
+ void Run( int nMaxParallel = INT_MAX, int threadOverride = -1 )
+ {
+ int i = g_pThreadPool->NumIdleThreads();
+
+ if ( nMaxParallel < i)
+ {
+ i = nMaxParallel;
+ }
+
+ while( i -- > 0 )
+ {
+ if ( threadOverride == -1 || i == threadOverride - 1 )
+ {
+ ++ m_nActive;
+ ThreadExecute( this, &ThisParallelProcessorBase_t::DoExecute )->Release();
+ }
+ }
+
+ if ( threadOverride == -1 || threadOverride == 0 )
+ {
+ ++ m_nActive;
+ DoExecute();
+ }
+
+ while ( m_nActive )
+ {
+ ThreadPause();
+ }
+ }
+
+protected:
+ void OnBegin() {}
+ bool OnProcess() { return false; }
+ void OnEnd() {}
+
+private:
+ void DoExecute()
+ {
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "DoExecute %s", m_szDescription );
+
+ static_cast<Derived *>( this )->OnBegin();
+
+ while ( static_cast<Derived *>( this )->OnProcess() )
+ continue;
+
+ static_cast<Derived *>(this)->OnEnd();
+
+ -- m_nActive;
+ }
+
+ CInterlockedInt m_nActive;
+ const char * m_szDescription;
+};
+
+
+
+
+//-----------------------------------------------------------------------------
+// Raw thread launching
+//-----------------------------------------------------------------------------
+
+inline unsigned FunctorExecuteThread( void *pParam )
+{
+ CFunctor *pFunctor = (CFunctor *)pParam;
+ (*pFunctor)();
+ pFunctor->Release();
+ return 0;
+}
+
+inline ThreadHandle_t ThreadExecuteSoloImpl( CFunctor *pFunctor, const char *pszName = NULL )
+{
+ ThreadHandle_t hThread;
+ ThreadId_t threadId;
+ hThread = CreateSimpleThread( FunctorExecuteThread, pFunctor, &threadId );
+ if ( pszName )
+ {
+ ThreadSetDebugName( threadId, pszName );
+ }
+ return hThread;
+}
+
+inline ThreadHandle_t ThreadExecuteSolo( CJob *pJob ) { return ThreadExecuteSoloImpl( CreateFunctor( pJob, &CJob::Execute ), pJob->Describe() ); }
+
+template <typename T1>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1 ), pszName ); }
+
+template <typename T1, typename T2>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2 ), pszName ); }
+
+template <typename T1, typename T2, typename T3>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6, a7 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6, a7, a8 ), pszName ); }
+
+template <typename T1, typename T2>
+inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2 ), pszName ); }
+
+template <typename T1, typename T2, typename T3>
+inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4>
+inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7 ), pszName ); }
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7, a8 ), pszName ); }
+
+//-----------------------------------------------------------------------------
+
+inline bool IThreadPool::YieldWait( CThreadEvent &event, unsigned timeout )
+{
+ CThreadEvent *pEvent = &event;
+ return ( YieldWait( &pEvent, 1, true, timeout ) != TW_TIMEOUT );
+}
+
+inline bool IThreadPool::YieldWait( CJob *pJob, unsigned timeout )
+{
+ return ( YieldWait( &pJob, 1, true, timeout ) != TW_TIMEOUT );
+}
+
+//-----------------------------------------------------------------------------
+
+inline JobStatus_t CJob::Execute()
+{
+ if ( IsFinished() )
+ {
+ return m_status;
+ }
+
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %s %d", __FUNCTION__, Describe(), m_status );
+
+ AUTO_LOCK( m_mutex );
+ AddRef();
+
+ JobStatus_t result;
+
+ switch ( m_status )
+ {
+ case JOB_STATUS_UNSERVICED:
+ case JOB_STATUS_PENDING:
+ {
+ // Service it
+ m_status = JOB_STATUS_INPROGRESS;
+ result = m_status = DoExecute();
+ DoCleanup();
+ m_CompleteEvent.Set();
+ break;
+ }
+
+ case JOB_STATUS_INPROGRESS:
+ AssertMsg(0, "Mutex Should have protected use while processing");
+ // fall through...
+
+ case JOB_OK:
+ case JOB_STATUS_ABORTED:
+ result = m_status;
+ break;
+
+ default:
+ AssertMsg( m_status < JOB_OK, "Unknown job state");
+ result = m_status;
+ }
+
+ Release();
+
+ return result;
+}
+
+
+//---------------------------------------------------------
+
+inline JobStatus_t CJob::TryExecute()
+{
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %s %d", __FUNCTION__, Describe(), m_status );
+
+ // TryLock() would only fail if another thread has entered
+ // Execute() or Abort()
+ if ( !IsFinished() && TryLock() )
+ {
+ // ...service the request
+ Execute();
+ Unlock();
+ }
+ return m_status;
+}
+
+//---------------------------------------------------------
+
+inline JobStatus_t CJob::Abort( bool bDiscard )
+{
+ if ( IsFinished() )
+ {
+ return m_status;
+ }
+
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %s %d", __FUNCTION__, Describe(), m_status );
+
+ AUTO_LOCK( m_mutex );
+ AddRef();
+
+ JobStatus_t result;
+
+ switch ( m_status )
+ {
+ case JOB_STATUS_UNSERVICED:
+ case JOB_STATUS_PENDING:
+ {
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "CJob::DoAbort" );
+
+ result = m_status = DoAbort( bDiscard );
+ if ( bDiscard )
+ DoCleanup();
+ m_CompleteEvent.Set();
+ }
+ break;
+
+ case JOB_STATUS_ABORTED:
+ case JOB_STATUS_INPROGRESS:
+ case JOB_OK:
+ result = m_status;
+ break;
+
+ default:
+ AssertMsg( m_status < JOB_OK, "Unknown job state");
+ result = m_status;
+ }
+
+ Release();
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+
+#endif // JOBTHREAD_H
diff --git a/mp/src/public/vstdlib/osversion.h b/mp/src/public/vstdlib/osversion.h new file mode 100644 index 00000000..52be4216 --- /dev/null +++ b/mp/src/public/vstdlib/osversion.h @@ -0,0 +1,60 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef OSVERSION_H
+#define OSVERSION_H
+#pragma once
+
+#include "vstdlib/vstdlib.h"
+
+// OS types we know about
+// Must be in ascending capability order, we use this for min OS requirements
+enum EOSType
+{
+ k_eOSUnknown = -1,
+ k_eMacOSUnknown = -102,
+ k_eMacOS104 = -101,
+ k_eMacOS105 = -100,
+ k_eMacOS1058 = -99,
+ k_eMacOS106 = -95,
+ k_eMacOS1063 = -94,
+ k_eMacOS107 = -90,
+ // k_eMacOSMax = -1
+ k_eLinuxUnknown = -203,
+ k_eLinux22 = -202,
+ k_eLinux24 = -201,
+ k_eLinux26 = -200,
+ // k_eLinuxMax = -103
+ k_eWinUnknown = 0,
+ k_eWin311 = 1,
+ k_eWin95,
+ k_eWin98,
+ k_eWinME,
+ k_eWinNT,
+ k_eWin2000,
+ k_eWinXP,
+ k_eWin2003,
+ k_eWinVista,
+ k_eWindows7,
+ k_eWin2008,
+ k_eWinMAX,
+ k_eOSTypeMax = k_eWinMAX + 11 // win types + other ifdef'd types
+};
+
+VSTDLIB_INTERFACE const char *GetNameFromOSType( EOSType eOSType );
+VSTDLIB_INTERFACE const char *GetOSDetailString( char *pchOutBuf, int cchOutBuf );
+VSTDLIB_INTERFACE EOSType GetOSType();
+VSTDLIB_INTERFACE bool OSTypesAreCompatible( EOSType eOSTypeDetected, EOSType eOSTypeRequired );
+VSTDLIB_INTERFACE const char *GetPlatformName( bool *pbIs64Bit );
+
+#endif // OSVERSION_H
diff --git a/mp/src/public/vstdlib/pch_vstdlib.h b/mp/src/public/vstdlib/pch_vstdlib.h new file mode 100644 index 00000000..72d70939 --- /dev/null +++ b/mp/src/public/vstdlib/pch_vstdlib.h @@ -0,0 +1,51 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose:
+//
+// $Workfile: $
+// $NoKeywords: $
+//=============================================================================
+
+
+#pragma warning(disable: 4514)
+
+// First include standard libraries
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <malloc.h>
+#include <memory.h>
+#include <ctype.h>
+
+// Next, include public
+#include "tier0/basetypes.h"
+#include "tier0/dbg.h"
+#include "tier0/valobject.h"
+
+// Next, include vstdlib
+#include "vstdlib/vstdlib.h"
+#include "tier1/strtools.h"
+#include "vstdlib/random.h"
+#include "tier1/KeyValues.h"
+#include "tier1/utlmemory.h"
+#include "tier1/utlrbtree.h"
+#include "tier1/utlvector.h"
+#include "tier1/utllinkedlist.h"
+#include "tier1/utlmultilist.h"
+#include "tier1/utlsymbol.h"
+#include "tier0/icommandline.h"
+#include "tier1/netadr.h"
+#include "tier1/mempool.h"
+#include "tier1/utlbuffer.h"
+#include "tier1/utlstring.h"
+#include "tier1/utlmap.h"
+
+#include "tier0/memdbgon.h"
+
+
+
diff --git a/mp/src/public/vstdlib/random.h b/mp/src/public/vstdlib/random.h new file mode 100644 index 00000000..5c56eb12 --- /dev/null +++ b/mp/src/public/vstdlib/random.h @@ -0,0 +1,111 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Random number generator
+//
+// $Workfile: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef VSTDLIB_RANDOM_H
+#define VSTDLIB_RANDOM_H
+
+#include "vstdlib/vstdlib.h"
+#include "tier0/basetypes.h"
+#include "tier0/threadtools.h"
+#include "tier1/interface.h"
+
+#define NTAB 32
+
+#pragma warning(push)
+#pragma warning( disable:4251 )
+
+//-----------------------------------------------------------------------------
+// A generator of uniformly distributed random numbers
+//-----------------------------------------------------------------------------
+class IUniformRandomStream
+{
+public:
+ // Sets the seed of the random number generator
+ virtual void SetSeed( int iSeed ) = 0;
+
+ // Generates random numbers
+ virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ) = 0;
+ virtual int RandomInt( int iMinVal, int iMaxVal ) = 0;
+ virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// The standard generator of uniformly distributed random numbers
+//-----------------------------------------------------------------------------
+class VSTDLIB_CLASS CUniformRandomStream : public IUniformRandomStream
+{
+public:
+ CUniformRandomStream();
+
+ // Sets the seed of the random number generator
+ virtual void SetSeed( int iSeed );
+
+ // Generates random numbers
+ virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f );
+ virtual int RandomInt( int iMinVal, int iMaxVal );
+ virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f );
+
+private:
+ int GenerateRandomNumber();
+
+ int m_idum;
+ int m_iy;
+ int m_iv[NTAB];
+
+ CThreadFastMutex m_mutex;
+};
+
+
+//-----------------------------------------------------------------------------
+// A generator of gaussian distributed random numbers
+//-----------------------------------------------------------------------------
+class VSTDLIB_CLASS CGaussianRandomStream
+{
+public:
+ // Passing in NULL will cause the gaussian stream to use the
+ // installed global random number generator
+ CGaussianRandomStream( IUniformRandomStream *pUniformStream = NULL );
+
+ // Attaches to a random uniform stream
+ void AttachToStream( IUniformRandomStream *pUniformStream = NULL );
+
+ // Generates random numbers
+ float RandomFloat( float flMean = 0.0f, float flStdDev = 1.0f );
+
+private:
+ IUniformRandomStream *m_pUniformStream;
+ bool m_bHaveValue;
+ float m_flRandomValue;
+
+ CThreadFastMutex m_mutex;
+};
+
+
+//-----------------------------------------------------------------------------
+// A couple of convenience functions to access the library's global uniform stream
+//-----------------------------------------------------------------------------
+VSTDLIB_INTERFACE void RandomSeed( int iSeed );
+VSTDLIB_INTERFACE float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f );
+VSTDLIB_INTERFACE float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f );
+VSTDLIB_INTERFACE int RandomInt( int iMinVal, int iMaxVal );
+VSTDLIB_INTERFACE float RandomGaussianFloat( float flMean = 0.0f, float flStdDev = 1.0f );
+
+
+//-----------------------------------------------------------------------------
+// Installs a global random number generator, which will affect the Random functions above
+//-----------------------------------------------------------------------------
+VSTDLIB_INTERFACE void InstallUniformRandomStream( IUniformRandomStream *pStream );
+
+
+#pragma warning(pop)
+
+#endif // VSTDLIB_RANDOM_H
+
+
+
diff --git a/mp/src/public/vstdlib/vcover.h b/mp/src/public/vstdlib/vcover.h new file mode 100644 index 00000000..a705d776 --- /dev/null +++ b/mp/src/public/vstdlib/vcover.h @@ -0,0 +1,125 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A simple tool for coverage tests
+//
+//=============================================================================
+
+#ifndef VCOVER_H
+#define VCOVER_H
+
+#include "tier1/utlrbtree.h"
+#include "vstdlib.h"
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+class CVCoverage
+{
+public:
+ CVCoverage() :
+ m_bActive( false ),
+ m_depth( 0 ),
+ m_token( 1 )
+ {
+ }
+
+ bool IsActive() const
+ {
+ return m_bActive;
+ }
+
+ void SetActive( bool bActive )
+ {
+ Assert( bActive != m_bActive );
+ m_bActive = bActive;
+ if ( bActive )
+ ++m_token;
+ }
+
+ void Begin()
+ {
+ ++m_depth;
+ }
+
+ void End()
+ {
+ --m_depth;
+ }
+
+ void Reset()
+ {
+ m_locations.RemoveAll();
+ }
+
+ bool ShouldCover( unsigned token ) const
+ {
+ return ( m_bActive && m_depth > 0 && token != m_token );
+ }
+
+ unsigned Cover( const char *pszFile, int line )
+ {
+ Location_t location = { pszFile, line };
+
+ m_locations.Insert( location );
+
+ return m_token;
+ }
+
+ void Report()
+ {
+ for ( int i = m_locations.FirstInorder(); i != m_locations.InvalidIndex(); i = m_locations.NextInorder( i ) )
+ {
+ Msg( "%s(%d) :\n", m_locations[i].pszFile, m_locations[i].line );
+ }
+ }
+
+private:
+ struct Location_t
+ {
+ const char *pszFile;
+ int line;
+
+ };
+
+ class CLocationLess
+ {
+ public:
+ CLocationLess( int ignored ) {}
+ bool operator!() { return false; }
+
+ bool operator()( const Location_t &lhs, const Location_t &rhs ) const
+ {
+ if ( lhs.line < rhs.line )
+ {
+ return true;
+ }
+
+ return CaselessStringLessThan( lhs.pszFile, rhs.pszFile );
+ }
+ };
+
+ bool m_bActive;
+ int m_depth;
+ unsigned m_token;
+
+ CUtlRBTree< Location_t, unsigned short, CLocationLess > m_locations;
+};
+
+VSTDLIB_INTERFACE CVCoverage g_VCoverage;
+
+#ifdef VCOVER_ENABLED
+#define VCOVER() \
+ do \
+ { \
+ static token; \
+ if ( g_VCoverage.ShouldCover( token ) ) \
+ { \
+ token = g_VCoverage.Cover( __FILE__, __LINE__ ); \
+ } \
+ } while( 0 )
+#else
+#define VCOVER() ((void)0)
+#endif
+
+#endif // VCOVER_H
diff --git a/mp/src/public/vstdlib/vstdlib.h b/mp/src/public/vstdlib/vstdlib.h new file mode 100644 index 00000000..94b71a6e --- /dev/null +++ b/mp/src/public/vstdlib/vstdlib.h @@ -0,0 +1,33 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef VSTDLIB_H
+#define VSTDLIB_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+//-----------------------------------------------------------------------------
+// dll export stuff
+//-----------------------------------------------------------------------------
+#ifdef VSTDLIB_DLL_EXPORT
+#define VSTDLIB_INTERFACE DLL_EXPORT
+#define VSTDLIB_OVERLOAD DLL_GLOBAL_EXPORT
+#define VSTDLIB_CLASS DLL_CLASS_EXPORT
+#define VSTDLIB_GLOBAL DLL_GLOBAL_EXPORT
+#else
+#define VSTDLIB_INTERFACE DLL_IMPORT
+#define VSTDLIB_OVERLOAD DLL_GLOBAL_IMPORT
+#define VSTDLIB_CLASS DLL_CLASS_IMPORT
+#define VSTDLIB_GLOBAL DLL_GLOBAL_IMPORT
+#endif
+
+#endif // VSTDLIB_H
|