torque引擎内核 线程 pool

//-----------------------------------------------------------------------------
// Torque Game Engine Advanced
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "platform/types.h"
#include "core/util/tVector.h"
#include "platform/threads/mutex.h"

#ifndef _PLATFORM_THREADS_THREAD_H_
#define _PLATFORM_THREADS_THREAD_H_

// Forward ref used by platform code
class PlatformThreadData;

// Typedefs
typedef void (*ThreadRunFunction)(void *data);

class Thread
{
protected:
   PlatformThreadData*  mData;

   /// Used to signal threads need to stop.
   /// Threads set this flag to false in start()
   bool shouldStop;

public:
   /// If set, the thread will delete itself once it has finished running.
   bool autoDelete;

   /// Create a thread.
   /// @param func The starting function for the thread.
   /// @param arg Data to be passed to func, when the thread starts.
   /// @param start_thread Whether to start the Thread immediately.
   Thread(ThreadRunFunction func = 0, void *arg = 0, bool start_thread = true, bool autodelete = false);
  
   /// Destroy a thread.
   /// The thread MUST be allowed to exit before it is destroyed.
   virtual ~Thread();

   /// Start a thread.
   /// Sets shouldStop to false and calls run() in a new thread of execution.
   void start();

   /// Ask a thread to stop running.
   void stop() { shouldStop = true; }

   /// Block until the thread stops running.
   bool join();

   /// Threads may call checkForStop() periodically to check if they've been
   /// asked to stop. As soon as checkForStop() returns true, the thread should
   /// clean up and return.
   bool checkForStop() {  return shouldStop; }

   /// Run the Thread's entry point function.
   /// Override this method in a subclass of Thread to create threaded code in
   /// an object oriented way, and without passing a function ptr to Thread().
   /// Also, you can call this method directly to execute the thread's
   /// code in a non-threaded way.
   virtual void run(void *arg = 0);

   /// Returns true if the thread is running.
   bool isAlive();

   /// Returns the platform specific thread id for this thread.
   U32 getId();
};

class ThreadManager
{
   static ThreadManager* singleton()
   {
      static ThreadManager* man = NULL;
      if(!man) man = new ThreadManager;
      AssertISV(man, "Thread manager doesn't exist.");
      return man;
   }

   Vector<Thread*> threadPool;
   Mutex poolLock;
  
public:

   /// Returns true if threadId is the same as the calling thread's id.
   static bool isCurrentThread(U32 threadId);

   /// Returns true if the 2 thread ids represent the same thread. Some thread
   /// APIs return an opaque object as a thread id, so the == operator cannot
   /// reliably compare thread ids.
   // this comparator is needed by pthreads and ThreadManager.
   static bool compare(U32 threadId_1, U32 threadId_2);
     
   /// Returns the platform specific thread id of the calling thread. Some
   /// platforms do not guarantee that this ID stays the same over the life of
   /// the thread, so use ThreadManager::compare() to compare thread ids.
   static U32 getCurrentThreadId();
  
   /// Each thread should add itself to the thread pool the first time it runs.
   static void addThread(Thread* thread)
   {
      ThreadManager &manager = *singleton();
      manager.poolLock.lock();
      Thread *alreadyAdded = getThreadById(thread->getId());
      if(!alreadyAdded)
         manager.threadPool.push_back(thread);
      manager.poolLock.unlock();
   }

   static void removeThread(Thread* thread)
   {
      ThreadManager &manager = *singleton();
      manager.poolLock.lock();
     
      U32 threadID = thread->getId();
      for(U32 i = 0;i < manager.threadPool.size();++i)
      {
         if(manager.threadPool[i]->getId() == threadID)
         {
            manager.threadPool.erase(i);
            break;
         }
      }
     
      manager.poolLock.unlock();
   }
  
   /// Searches the pool of known threads for a thread whose id is equivalent to
   /// the given threadid. Compares thread ids with ThreadManager::compare().
   static Thread* getThreadById(U32 threadid)
   {
      AssertFatal(threadid != 0, "ThreadManager::getThreadById() Searching for a bad thread id.");
      Thread* ret = NULL;
     
      singleton()->poolLock.lock();
      Vector<Thread*> &pool = singleton()->threadPool;
      for( S32 i = pool.size() - 1; i >= 0; i--)
      {
         Thread* p = pool[i];
         if(compare(p->getId(), threadid))
         {
            ret = p;
            break;
         }
      }
      singleton()->poolLock.unlock();
      return ret;
   }

   static Thread* getCurrentThread()
   {
      return getThreadById(ThreadManager::getCurrentThreadId());
   }
};

inline bool ThreadManager::isCurrentThread(U32 threadId)
{
   U32 current = getCurrentThreadId();
   return compare(current, threadId);
}

#endif // _PLATFORM_THREADS_THREAD_H_

 

 

 

 

 

//-----------------------------------------------------------------------------
// Torque Game Engine Advanced
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "platform/threads/thread.h"
#include "platform/threads/semaphore.h"
#include "platformWin32/platformWin32.h"
#include "core/util/safeDelete.h"

#include <process.h> // [tom, 4/20/2006] for _beginthread()

//-----------------------------------------------------------------------------
// Thread data
//-----------------------------------------------------------------------------

class PlatformThreadData
{
public:
   ThreadRunFunction       mRunFunc;
   void*                   mRunArg;
   Thread*                 mThread;
   HANDLE                  mThreadHnd;
   Semaphore               mGateway;
   U32                     mThreadID;

   PlatformThreadData()
   {
      mRunFunc    = NULL;
      mRunArg     = 0;
      mThread     = 0;
      mThreadHnd  = 0;
   };
};

//-----------------------------------------------------------------------------
// 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 unsigned int __stdcall ThreadRunHandler(void * arg)
{
   PlatformThreadData* mData = reinterpret_cast<PlatformThreadData*>(arg);
   mData->mThreadID = ThreadManager::getCurrentThreadId();
  
   ThreadManager::addThread(mData->mThread);
   mData->mThread->run(mData->mRunArg);
   ThreadManager::removeThread(mData->mThread);

   // we could delete the Thread here, if it wants to be auto-deleted...
   mData->mGateway.release();
   // the end of this function is where the created win32 thread will die.

   _endthreadex( 0 );
   return 0;
}

//-----------------------------------------------------------------------------
// Constructor/Destructor
//-----------------------------------------------------------------------------

Thread::Thread(ThreadRunFunction func /* = 0 */, void *arg /* = 0 */, bool start_thread /* = true */, bool autodelete /*= false*/)
{
   mData = new PlatformThreadData;
   mData->mRunFunc = func;
   mData->mRunArg = arg;
   mData->mThread = this;

   if(start_thread)
      start();
}

Thread::~Thread()
{
   stop();
   join();

   SAFE_DELETE(mData);
}

//-----------------------------------------------------------------------------
// Public Methods
//-----------------------------------------------------------------------------

void Thread::start()
{
   if(isAlive())
      return;

   // 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->mThreadHnd = (HANDLE)_beginthreadex(0, 0, ThreadRunHandler, mData, 0, 0);
}

bool Thread::join()
{
   if(!isAlive())
      return true;

   bool res = ( WaitForSingleObject(mData->mThreadHnd, INFINITE) != WAIT_FAILED );
   CloseHandle( mData->mThreadHnd );

   return res;
}

void Thread::run(void *arg /* = 0 */)
{
   if(mData->mRunFunc)
      mData->mRunFunc(arg);
}

bool Thread::isAlive()
{
   if(mData->mThreadHnd == 0)
      return false;

   DWORD res = WaitForSingleObject(mData->mThreadHnd, 0);
   return res != WAIT_OBJECT_0 && res != WAIT_FAILED;
}

U32 Thread::getId()
{
   return mData->mThreadID;
}

U32 ThreadManager::getCurrentThreadId()
{
   return GetCurrentThreadId();
}

bool ThreadManager::compare(U32 threadId_1, U32 threadId_2)
{
   return (threadId_1 == threadId_2);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值