thread.cpp

Engine/source/platformX86UNIX/threads/thread.cpp

More...

Classes:

Public Functions

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