123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platformWin32/platformWin32.h"
- #include "platform/threads/thread.h"
- #include "platform/threads/semaphore.h"
- #include "platform/platformIntrinsics.h"
- #include "core/util/safeDelete.h"
- #include <process.h> // [tom, 4/20/2006] for _beginthread()
- ThreadManager::MainThreadId ThreadManager::smMainThreadId;
- //-----------------------------------------------------------------------------
- // Thread data
- //-----------------------------------------------------------------------------
- class PlatformThreadData
- {
- public:
- ThreadRunFunction mRunFunc;
- void* mRunArg;
- Thread* mThread;
- HANDLE mThreadHnd;
- Semaphore mGateway;
- dsize_t mThreadID;
- U32 mDead;
- PlatformThreadData()
- {
- mRunFunc = NULL;
- mRunArg = 0;
- mThread = 0;
- mThreadHnd = 0;
- mThreadID = 0;
- mDead = false;
- };
- };
- //-----------------------------------------------------------------------------
- // Static Functions/Methods
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // Function: ThreadRunHandler
- // Summary: Calls Thread::run() with the thread's specified run argument.
- // Neccesary because Thread::run() is provided as a non-threaded
- // way to execute the thread's run function. So we have to keep
- // track of the thread's lock here.
- static U32 __stdcall ThreadRunHandler(void * arg)
- {
- PlatformThreadData* mData = reinterpret_cast<PlatformThreadData*>(arg);
- mData->mThreadID = GetCurrentThreadId();
- ThreadManager::addThread(mData->mThread);
- mData->mThread->run(mData->mRunArg);
- ThreadManager::removeThread(mData->mThread);
- bool autoDelete = mData->mThread->autoDelete;
- mData->mThreadHnd = NULL; // mark as dead
- dCompareAndSwap( mData->mDead, false, true );
- mData->mGateway.release(); // don't access data after this.
- if( autoDelete )
- delete mData->mThread; // Safe as we own the data.
- _endthreadex( 0 );
- return 0;
- }
- //-----------------------------------------------------------------------------
- // Constructor/Destructor
- //-----------------------------------------------------------------------------
- Thread::Thread(ThreadRunFunction func /* = 0 */, void *arg /* = 0 */, bool start_thread /* = true */, bool autodelete /*= false*/)
- : autoDelete( autodelete )
- {
- AssertFatal( !start_thread, "Thread::Thread() - auto-starting threads from ctor has been disallowed since the run() method is virtual" );
-
- mData = new PlatformThreadData;
- mData->mRunFunc = func;
- mData->mRunArg = arg;
- mData->mThread = this;
- }
- Thread::~Thread()
- {
- stop();
- if( isAlive() )
- join();
- SAFE_DELETE(mData);
- }
- //-----------------------------------------------------------------------------
- // Public Methods
- //-----------------------------------------------------------------------------
- void Thread::start( void* arg )
- {
- AssertFatal( !mData->mThreadHnd,
- "Thread::start() - thread already started" );
- // cause start to block out other pthreads from using this Thread,
- // at least until ThreadRunHandler exits.
- mData->mGateway.acquire();
-
- // reset the shouldStop flag, so we'll know when someone asks us to stop.
- shouldStop = false;
-
- mData->mDead = false;
-
- if( !mData->mRunArg )
- mData->mRunArg = arg;
- mData->mThreadHnd = (HANDLE)_beginthreadex(0, 0, ThreadRunHandler, mData, 0, 0);
- }
- bool Thread::join()
- {
- mData->mGateway.acquire();
- AssertFatal( !isAlive(), "Thread::join() - thread still alive after join" );
- mData->mGateway.release(); // release for further joins
- return true;
- }
- void Thread::run(void *arg /* = 0 */)
- {
- if(mData->mRunFunc)
- mData->mRunFunc(arg);
- }
- bool Thread::isAlive()
- {
- return ( !mData->mDead );
- }
- dsize_t Thread::getId()
- {
- return mData->mThreadID;
- }
- void Thread::_setName( const char* name )
- {
- #if defined( TORQUE_DEBUG ) && defined( TORQUE_COMPILER_VISUALC ) && defined( TORQUE_OS_WIN )
- // See http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
- #define MS_VC_EXCEPTION 0x406D1388
- #pragma pack(push,8)
- typedef struct tagTHREADNAME_INFO
- {
- DWORD dwType; // Must be 0x1000.
- LPCSTR szName; // Pointer to name (in user addr space).
- DWORD dwThreadID; // Thread ID (-1=caller thread).
- DWORD dwFlags; // Reserved for future use, must be zero.
- } THREADNAME_INFO;
- #pragma pack(pop)
- Sleep(10);
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = name;
- info.dwThreadID = getId();
- info.dwFlags = 0;
- __try
- {
- RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- }
- #endif
- }
- dsize_t ThreadManager::getCurrentThreadId()
- {
- return GetCurrentThreadId();
- }
- bool ThreadManager::compare(dsize_t threadId_1, dsize_t threadId_2)
- {
- return (threadId_1 == threadId_2);
- }
|