thread.cpp
Engine/source/platformX86UNIX/threads/thread.cpp
Classes:
class
Public Functions
void *
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#include <pthread.h> 25#include "platform/threads/thread.h" 26#include "platform/threads/semaphore.h" 27#include "platform/threads/mutex.h" 28#include <stdlib.h> 29 30class PlatformThreadData 31{ 32public: 33 ThreadRunFunction mRunFunc; 34 void* mRunArg; 35 Thread* mThread; 36 Semaphore mGateway; // default count is 1 37 pthread_t mThreadID; 38 bool mDead; 39}; 40 41ThreadManager::MainThreadId ThreadManager::smMainThreadId; 42 43//----------------------------------------------------------------------------- 44// Function: ThreadRunHandler 45// Summary: Calls Thread::run() with the thread's specified run argument. 46// Neccesary because Thread::run() is provided as a non-threaded 47// way to execute the thread's run function. So we have to keep 48// track of the thread's lock here. 49static void *ThreadRunHandler(void * arg) 50{ 51 PlatformThreadData *mData = reinterpret_cast<PlatformThreadData*>(arg); 52 Thread *thread = mData->mThread; 53 54 // mThreadID is filled in twice, once here and once in pthread_create(). 55 // We fill in mThreadID here as well as in pthread_create() because addThread() 56 // can execute before pthread_create() returns and sets mThreadID. 57 // The value from pthread_create() and pthread_self() are guaranteed to be equivalent (but not identical) 58 mData->mThreadID = pthread_self(); 59 60 ThreadManager::addThread(thread); 61 thread->run(mData->mRunArg); 62 ThreadManager::removeThread(thread); 63 64 bool autoDelete = thread->autoDelete; 65 66 mData->mThreadID = 0; 67 mData->mDead = true; 68 mData->mGateway.release(); 69 70 if( autoDelete ) 71 delete thread; 72 73 // return value for pthread lib's benefit 74 return NULL; 75 // the end of this function is where the created pthread will die. 76} 77 78//----------------------------------------------------------------------------- 79Thread::Thread(ThreadRunFunction func, void* arg, bool start_thread, bool autodelete) 80{ 81 AssertFatal( !start_thread, "Thread::Thread() - auto-starting threads from ctor has been disallowed since the run() method is virtual" ); 82 83 mData = new PlatformThreadData; 84 mData->mRunFunc = func; 85 mData->mRunArg = arg; 86 mData->mThread = this; 87 mData->mThreadID = 0; 88 mData->mDead = false; 89 autoDelete = autodelete; 90} 91 92Thread::~Thread() 93{ 94 stop(); 95 if( isAlive() ) 96 join(); 97 98 delete mData; 99} 100 101void Thread::start( void* arg ) 102{ 103 // cause start to block out other pthreads from using this Thread, 104 // at least until ThreadRunHandler exits. 105 mData->mGateway.acquire(); 106 107 // reset the shouldStop flag, so we'll know when someone asks us to stop. 108 shouldStop = false; 109 110 mData->mDead = false; 111 112 if( !mData->mRunArg ) 113 mData->mRunArg = arg; 114 115 pthread_create(&mData->mThreadID, NULL, ThreadRunHandler, mData); 116} 117 118bool Thread::join() 119{ 120 // not using pthread_join here because pthread_join cannot deal 121 // with multiple simultaneous calls. 122 123 mData->mGateway.acquire(); 124 AssertFatal( !isAlive(), "Thread::join() - thread not dead after join()" ); 125 mData->mGateway.release(); 126 127 return true; 128} 129 130void Thread::run(void* arg) 131{ 132 if(mData->mRunFunc) 133 mData->mRunFunc(arg); 134} 135 136bool Thread::isAlive() 137{ 138 return ( !mData->mDead ); 139} 140 141U32 Thread::getId() 142{ 143 return (U32)mData->mThreadID; 144} 145 146void Thread::_setName( const char* ) 147{ 148 // Not supported. Wading through endless lists of Thread-1, Thread-2, Thread-3, ... trying to find 149 // that one thread you are looking for is just so much fun. 150} 151 152U32 ThreadManager::getCurrentThreadId() 153{ 154 return (U32)pthread_self(); 155} 156 157bool ThreadManager::compare(U32 threadId_1, U32 threadId_2) 158{ 159 return pthread_equal((pthread_t)threadId_1, (pthread_t)threadId_2); 160} 161