thread.cpp
Engine/source/platformWin32/threads/thread.cpp
Classes:
class
Public Functions
U32 __stdcall
ThreadRunHandler(void * arg)
Detailed Description
Public Functions
ThreadRunHandler(void * arg)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24 25#include "platformWin32/platformWin32.h" 26#include "platform/threads/thread.h" 27#include "platform/threads/semaphore.h" 28#include "platform/platformIntrinsics.h" 29#include "core/util/safeDelete.h" 30 31#include <process.h> // [tom, 4/20/2006] for _beginthread() 32 33ThreadManager::MainThreadId ThreadManager::smMainThreadId; 34 35//----------------------------------------------------------------------------- 36// Thread data 37//----------------------------------------------------------------------------- 38 39class PlatformThreadData 40{ 41public: 42 ThreadRunFunction mRunFunc; 43 void* mRunArg; 44 Thread* mThread; 45 HANDLE mThreadHnd; 46 Semaphore mGateway; 47 U32 mThreadID; 48 U32 mDead; 49 50 PlatformThreadData() 51 { 52 mRunFunc = NULL; 53 mRunArg = 0; 54 mThread = 0; 55 mThreadHnd = 0; 56 mThreadID = 0; 57 mDead = false; 58 }; 59}; 60 61//----------------------------------------------------------------------------- 62// Static Functions/Methods 63//----------------------------------------------------------------------------- 64 65 66//----------------------------------------------------------------------------- 67// Function: ThreadRunHandler 68// Summary: Calls Thread::run() with the thread's specified run argument. 69// Neccesary because Thread::run() is provided as a non-threaded 70// way to execute the thread's run function. So we have to keep 71// track of the thread's lock here. 72static U32 __stdcall ThreadRunHandler(void * arg) 73{ 74 PlatformThreadData* mData = reinterpret_cast<PlatformThreadData*>(arg); 75 mData->mThreadID = GetCurrentThreadId(); 76 77 ThreadManager::addThread(mData->mThread); 78 mData->mThread->run(mData->mRunArg); 79 ThreadManager::removeThread(mData->mThread); 80 81 bool autoDelete = mData->mThread->autoDelete; 82 83 mData->mThreadHnd = NULL; // mark as dead 84 dCompareAndSwap( mData->mDead, false, true ); 85 mData->mGateway.release(); // don't access data after this. 86 87 if( autoDelete ) 88 delete mData->mThread; // Safe as we own the data. 89 90 _endthreadex( 0 ); 91 return 0; 92} 93 94//----------------------------------------------------------------------------- 95// Constructor/Destructor 96//----------------------------------------------------------------------------- 97 98Thread::Thread(ThreadRunFunction func /* = 0 */, void *arg /* = 0 */, bool start_thread /* = true */, bool autodelete /*= false*/) 99 : autoDelete( autodelete ) 100{ 101 AssertFatal( !start_thread, "Thread::Thread() - auto-starting threads from ctor has been disallowed since the run() method is virtual" ); 102 103 mData = new PlatformThreadData; 104 mData->mRunFunc = func; 105 mData->mRunArg = arg; 106 mData->mThread = this; 107} 108 109Thread::~Thread() 110{ 111 stop(); 112 if( isAlive() ) 113 join(); 114 115 SAFE_DELETE(mData); 116} 117 118//----------------------------------------------------------------------------- 119// Public Methods 120//----------------------------------------------------------------------------- 121 122void Thread::start( void* arg ) 123{ 124 AssertFatal( !mData->mThreadHnd, 125 "Thread::start() - thread already started" ); 126 127 // cause start to block out other pthreads from using this Thread, 128 // at least until ThreadRunHandler exits. 129 mData->mGateway.acquire(); 130 131 // reset the shouldStop flag, so we'll know when someone asks us to stop. 132 shouldStop = false; 133 134 mData->mDead = false; 135 136 if( !mData->mRunArg ) 137 mData->mRunArg = arg; 138 139 mData->mThreadHnd = (HANDLE)_beginthreadex(0, 0, ThreadRunHandler, mData, 0, 0); 140} 141 142bool Thread::join() 143{ 144 mData->mGateway.acquire(); 145 AssertFatal( !isAlive(), "Thread::join() - thread still alive after join" ); 146 mData->mGateway.release(); // release for further joins 147 return true; 148} 149 150void Thread::run(void *arg /* = 0 */) 151{ 152 if(mData->mRunFunc) 153 mData->mRunFunc(arg); 154} 155 156bool Thread::isAlive() 157{ 158 return ( !mData->mDead ); 159} 160 161U32 Thread::getId() 162{ 163 return mData->mThreadID; 164} 165 166void Thread::_setName( const char* name ) 167{ 168#if defined( TORQUE_DEBUG ) && defined( TORQUE_COMPILER_VISUALC ) && defined( TORQUE_OS_WIN ) 169 170 // See http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx 171 172 #define MS_VC_EXCEPTION 0x406D1388 173 174 #pragma pack(push,8) 175 typedef struct tagTHREADNAME_INFO 176 { 177 DWORD dwType; // Must be 0x1000. 178 LPCSTR szName; // Pointer to name (in user addr space). 179 DWORD dwThreadID; // Thread ID (-1=caller thread). 180 DWORD dwFlags; // Reserved for future use, must be zero. 181 } THREADNAME_INFO; 182 #pragma pack(pop) 183 184 Sleep(10); 185 THREADNAME_INFO info; 186 info.dwType = 0x1000; 187 info.szName = name; 188 info.dwThreadID = getId(); 189 info.dwFlags = 0; 190 191 __try 192 { 193 RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); 194 } 195 __except(EXCEPTION_EXECUTE_HANDLER) 196 { 197 } 198#endif 199} 200 201U32 ThreadManager::getCurrentThreadId() 202{ 203 return GetCurrentThreadId(); 204} 205 206bool ThreadManager::compare(U32 threadId_1, U32 threadId_2) 207{ 208 return (threadId_1 == threadId_2); 209} 210