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/utils/common/threads.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/utils/common/threads.cpp')
| -rw-r--r-- | mp/src/utils/common/threads.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/mp/src/utils/common/threads.cpp b/mp/src/utils/common/threads.cpp new file mode 100644 index 00000000..344943c9 --- /dev/null +++ b/mp/src/utils/common/threads.cpp @@ -0,0 +1,257 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#define USED
+
+#include <windows.h>
+#include "cmdlib.h"
+#define NO_THREAD_NAMES
+#include "threads.h"
+#include "pacifier.h"
+
+#define MAX_THREADS 16
+
+
+class CRunThreadsData
+{
+public:
+ int m_iThread;
+ void *m_pUserData;
+ RunThreadsFn m_Fn;
+};
+
+CRunThreadsData g_RunThreadsData[MAX_THREADS];
+
+
+int dispatch;
+int workcount;
+qboolean pacifier;
+
+qboolean threaded;
+bool g_bLowPriorityThreads = false;
+
+HANDLE g_ThreadHandles[MAX_THREADS];
+
+
+
+/*
+=============
+GetThreadWork
+
+=============
+*/
+int GetThreadWork (void)
+{
+ int r;
+
+ ThreadLock ();
+
+ if (dispatch == workcount)
+ {
+ ThreadUnlock ();
+ return -1;
+ }
+
+ UpdatePacifier( (float)dispatch / workcount );
+
+ r = dispatch;
+ dispatch++;
+ ThreadUnlock ();
+
+ return r;
+}
+
+
+ThreadWorkerFn workfunction;
+
+void ThreadWorkerFunction( int iThread, void *pUserData )
+{
+ int work;
+
+ while (1)
+ {
+ work = GetThreadWork ();
+ if (work == -1)
+ break;
+
+ workfunction( iThread, work );
+ }
+}
+
+void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, ThreadWorkerFn func)
+{
+ if (numthreads == -1)
+ ThreadSetDefault ();
+
+ workfunction = func;
+ RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
+}
+
+
+/*
+===================================================================
+
+WIN32
+
+===================================================================
+*/
+
+int numthreads = -1;
+CRITICAL_SECTION crit;
+static int enter;
+
+
+class CCritInit
+{
+public:
+ CCritInit()
+ {
+ InitializeCriticalSection (&crit);
+ }
+} g_CritInit;
+
+
+
+void SetLowPriority()
+{
+ SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
+}
+
+
+void ThreadSetDefault (void)
+{
+ SYSTEM_INFO info;
+
+ if (numthreads == -1) // not set manually
+ {
+ GetSystemInfo (&info);
+ numthreads = info.dwNumberOfProcessors;
+ if (numthreads < 1 || numthreads > 32)
+ numthreads = 1;
+ }
+
+ Msg ("%i threads\n", numthreads);
+}
+
+
+void ThreadLock (void)
+{
+ if (!threaded)
+ return;
+ EnterCriticalSection (&crit);
+ if (enter)
+ Error ("Recursive ThreadLock\n");
+ enter = 1;
+}
+
+void ThreadUnlock (void)
+{
+ if (!threaded)
+ return;
+ if (!enter)
+ Error ("ThreadUnlock without lock\n");
+ enter = 0;
+ LeaveCriticalSection (&crit);
+}
+
+
+// This runs in the thread and dispatches a RunThreadsFn call.
+DWORD WINAPI InternalRunThreadsFn( LPVOID pParameter )
+{
+ CRunThreadsData *pData = (CRunThreadsData*)pParameter;
+ pData->m_Fn( pData->m_iThread, pData->m_pUserData );
+ return 0;
+}
+
+
+void RunThreads_Start( RunThreadsFn fn, void *pUserData, ERunThreadsPriority ePriority )
+{
+ Assert( numthreads > 0 );
+ threaded = true;
+
+ if ( numthreads > MAX_TOOL_THREADS )
+ numthreads = MAX_TOOL_THREADS;
+
+ for ( int i=0; i < numthreads ;i++ )
+ {
+ g_RunThreadsData[i].m_iThread = i;
+ g_RunThreadsData[i].m_pUserData = pUserData;
+ g_RunThreadsData[i].m_Fn = fn;
+
+ DWORD dwDummy;
+ g_ThreadHandles[i] = CreateThread(
+ NULL, // LPSECURITY_ATTRIBUTES lpsa,
+ 0, // DWORD cbStack,
+ InternalRunThreadsFn, // LPTHREAD_START_ROUTINE lpStartAddr,
+ &g_RunThreadsData[i], // LPVOID lpvThreadParm,
+ 0, // DWORD fdwCreate,
+ &dwDummy );
+
+ if ( ePriority == k_eRunThreadsPriority_UseGlobalState )
+ {
+ if( g_bLowPriorityThreads )
+ SetThreadPriority( g_ThreadHandles[i], THREAD_PRIORITY_LOWEST );
+ }
+ else if ( ePriority == k_eRunThreadsPriority_Idle )
+ {
+ SetThreadPriority( g_ThreadHandles[i], THREAD_PRIORITY_IDLE );
+ }
+ }
+}
+
+
+void RunThreads_End()
+{
+ WaitForMultipleObjects( numthreads, g_ThreadHandles, TRUE, INFINITE );
+ for ( int i=0; i < numthreads; i++ )
+ CloseHandle( g_ThreadHandles[i] );
+
+ threaded = false;
+}
+
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn( int workcnt, qboolean showpacifier, RunThreadsFn fn, void *pUserData )
+{
+ int start, end;
+
+ start = Plat_FloatTime();
+ dispatch = 0;
+ workcount = workcnt;
+ StartPacifier("");
+ pacifier = showpacifier;
+
+#ifdef _PROFILE
+ threaded = false;
+ (*func)( 0 );
+ return;
+#endif
+
+
+ RunThreads_Start( fn, pUserData );
+ RunThreads_End();
+
+
+ end = Plat_FloatTime();
+ if (pacifier)
+ {
+ EndPacifier(false);
+ printf (" (%i)\n", end-start);
+ }
+}
+
+
|