Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

Thread.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * スレッド実装
00022  * @author Junpee
00023  */
00024 
00025 #include "LampBasic.h"
00026 #include <process.h>
00027 #include "Core/Thread/Thread.h"
00028 #include "Core/Thread/SynchronizedBlock.h"
00029 
00030 // timeBeginPeriod, timeEndPeriod
00031 #include <windows.h>
00032 #pragma comment(lib, "winmm.lib")
00033 
00034 namespace Lamp{
00035 
00036 /**
00037  * スレッドコールバック
00038  * @param userData ユーザデータ
00039  * @return 終了コード
00040  */
00041 u_int __stdcall threadCallback(void* userData){
00042     Thread* thread = (Thread*)userData;
00043     return thread->executeWrapper();
00044 }
00045 
00046 // 不正なスレッドハンドル
00047 const HANDLE Thread::invalidThreadHandle = (HANDLE)-1L;
00048 
00049 //------------------------------------------------------------------------------
00050 // 初期化、終了処理
00051 //------------------------------------------------------------------------------
00052 // 初期化
00053 void Thread::initialize(){
00054     // Windowsタイマの精度を上げる
00055     ::timeBeginPeriod(1);
00056 }
00057 //------------------------------------------------------------------------------
00058 // 後始末
00059 void Thread::finalize(){
00060     // Windowsタイマの精度を下げる
00061     ::timeEndPeriod(1);
00062 }
00063 //------------------------------------------------------------------------------
00064 // コンストラクタ
00065 Thread::Thread() : Runnable(),
00066     threadHandle_(invalidThreadHandle), threadID_(0), isFinished_(false){
00067     runnable_ = this;
00068     createThread();
00069 }
00070 //------------------------------------------------------------------------------
00071 // コンストラクタ
00072 Thread::Thread(Runnable* runnable) : Runnable(),
00073     threadHandle_(invalidThreadHandle), threadID_(0), isFinished_(false){
00074     runnable_ = runnable;
00075     createThread();
00076 }
00077 //------------------------------------------------------------------------------
00078 // コンストラクタ
00079 Thread::Thread(LockObject* lockObject, bool deleteLockObject) :
00080     Runnable(lockObject, deleteLockObject),
00081     threadHandle_(invalidThreadHandle), threadID_(0), isFinished_(false){
00082     runnable_ = this;
00083     createThread();
00084 }
00085 //------------------------------------------------------------------------------
00086 // コンストラクタ
00087 Thread::Thread(
00088     Runnable* runnable, LockObject* lockObject, bool deleteLockObject) :
00089     Runnable(lockObject, deleteLockObject),
00090     threadHandle_(invalidThreadHandle), threadID_(0), isFinished_(false){
00091     runnable_ = runnable;
00092     createThread();
00093 }
00094 //------------------------------------------------------------------------------
00095 // デストラクタ
00096 Thread::~Thread(){
00097     Assert(isFinished_);
00098 }
00099 //------------------------------------------------------------------------------
00100 // スレッドの作成
00101 void Thread::createThread(){
00102     // 同期が取られている場所からしか呼ばれないので同期を取らない
00103     Assert(threadHandle_ == invalidThreadHandle);
00104     Assert(threadID_ == 0);
00105     threadHandle_ = (HANDLE)::_beginthreadex(NULL, getStackSize(),
00106         threadCallback, this, CREATE_SUSPENDED, &threadID_);
00107     if(threadHandle_ == invalidThreadHandle){
00108         ErrorOut("Thread::createThread() _beginthreadex()に失敗しました");
00109     }
00110     isFinished_ = false;
00111 }
00112 //------------------------------------------------------------------------------
00113 // スレッドの操作
00114 //------------------------------------------------------------------------------
00115 // スレッドを開始する
00116 void Thread::start(){
00117     // スレッドに対するロック
00118     SynchronizedBlock synchronizedBlock(this);
00119     // 実行終了後に再度startが呼ばれた場合はスレッドを再作成する
00120     if(isFinished_){ createThread(); }
00121     Assert(getThreadHandle() != invalidThreadHandle);
00122     Assert(getThreadID() != 0);
00123     if(::ResumeThread(getThreadHandle()) == 0xFFFFFFFF){
00124         ErrorOut("Thread::start() ResumeThread()に失敗しました");
00125     }
00126 }
00127 //------------------------------------------------------------------------------
00128 // スレッドをセットアップする
00129 void Thread::setup(){
00130     // スレッドに対するロック
00131     SynchronizedBlock synchronizedBlock(this);
00132     // 実行終了後に再度startが呼ばれた場合はスレッドを再作成する
00133     if(isFinished_){ createThread(); }
00134     Assert(getThreadHandle() != invalidThreadHandle);
00135     Assert(getThreadID() != 0);
00136 }
00137 //------------------------------------------------------------------------------
00138 // スレッドの終了を依頼する
00139 void Thread::requestStop(){
00140     // スレッドに対するロック
00141     SynchronizedBlock synchronizedBlock(this);
00142     if(isFinished()){ return; }
00143     Assert(getThreadHandle() != invalidThreadHandle);
00144     Assert(getThreadID() != 0);
00145     runnable_->setStopRequested(true);
00146 }
00147 //------------------------------------------------------------------------------
00148 // スレッドの終了を依頼し、終了を待つ
00149 bool Thread::stop(u_int milliseconds){
00150     if(isFinished()){ return true; }
00151     requestStop();
00152     return join(milliseconds);
00153 }
00154 //------------------------------------------------------------------------------
00155 // スレッドの終了を待つ
00156 bool Thread::join(u_int milliseconds){
00157     // ロックをかけるとデッドロックになる
00158     if(isFinished()){ return true; }
00159     Assert(getThreadHandle() != invalidThreadHandle);
00160     Assert(getThreadID() != 0);
00161     u_int result = ::WaitForSingleObject(getThreadHandle(), milliseconds);
00162     if(result == WAIT_OBJECT_0){
00163         return true;
00164     }else if(result == WAIT_TIMEOUT){
00165         return false;
00166     }else if(result == WAIT_ABANDONED){
00167         ErrorOut("Thread::join() Mutexを保持したままThreadが終了しました");
00168     }else if(result == WAIT_FAILED){
00169         Assert(false);
00170         return false;
00171 //      DebugOut("%d\n", GetLastError());
00172 //      ErrorOut("Thread::join() WaitForSingleObject()に失敗しました");
00173     }
00174     return true;
00175 }
00176 //------------------------------------------------------------------------------
00177 // プライオリティの設定
00178 void Thread::setPriority(Priority priority){
00179     Assert(getThreadHandle() != invalidThreadHandle);
00180     Assert(getThreadID() != 0);
00181     // スレッドに対するロック
00182     SynchronizedBlock synchronizedBlock(this);
00183     if(SetThreadPriority(getThreadHandle(), priority) == 0){
00184         ErrorOut("Thread::setPriority() SetThreadPriority()に失敗しました");
00185     }
00186 }
00187 //------------------------------------------------------------------------------
00188 // プライオリティの取得
00189 Thread::Priority Thread::getPriority(){
00190     Assert(getThreadHandle() != invalidThreadHandle);
00191     Assert(getThreadID() != 0);
00192     // スレッドに対するロック
00193     SynchronizedBlock synchronizedBlock(this);
00194     int result = GetThreadPriority(getThreadHandle());
00195     if(result == THREAD_PRIORITY_ERROR_RETURN){
00196         ErrorOut("Thread::getPriority() GetThreadPriority()に失敗しました");
00197     }
00198     return (Priority)result;
00199 }
00200 //------------------------------------------------------------------------------
00201 // サスペンド
00202 void Thread::suspend(){
00203     // スレッドに対するロック
00204     SynchronizedBlock synchronizedBlock(this);
00205     if(isFinished()){ return; }
00206     Assert(::GetCurrentThreadId() != getThreadID());
00207     if(::SuspendThread(getThreadHandle()) == 0xFFFFFFFF){
00208         ErrorOut("Thread::suspend() SuspendThread()に失敗しました");
00209     }
00210 }
00211 //------------------------------------------------------------------------------
00212 // レジューム
00213 void Thread::resume(){
00214     // スレッドに対するロック
00215     SynchronizedBlock synchronizedBlock(this);
00216     if(isFinished()){ return; }
00217     if(::ResumeThread(getThreadHandle()) == 0xFFFFFFFF){
00218         ErrorOut("Thread::resume() ResumeThread()に失敗しました");
00219     }
00220 }
00221 //------------------------------------------------------------------------------
00222 // 使用不可
00223 //------------------------------------------------------------------------------
00224 // スレッドの実行ラッパ
00225 u_int Thread::executeWrapper(){
00226     // 開始処理
00227     {
00228         // スレッドに対するロック
00229         SynchronizedBlock synchronizedBlock(this);
00230         runnable_->setStopRequested(false);
00231     }
00232     // 実行
00233     runnable_->run(this);
00234     // 終了処理
00235     {
00236         // スレッドに対するロック
00237         SynchronizedBlock synchronizedBlock(this);
00238         isFinished_ = true;
00239         ::CloseHandle(getThreadHandle());
00240         threadHandle_ = invalidThreadHandle;
00241         threadID_ = 0; 
00242     }
00243     return 0;
00244 }
00245 //------------------------------------------------------------------------------
00246 } // End of namespace Lamp
00247 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:38 2005 for Lamp by doxygen 1.3.2