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 //------------------------------------------------------------------------------