/* ============================================================================= * scpp_thread.cpp * Copyright (c) 2003 - 2011 Nomura Kei * LICENSE : * LGPL (GNU Lesser General General Public License - Version 3,29 June 2007) * http://www.gnu.org/copyleft/lesser.html * ============================================================================= * * ライブラリの動的ロードを行うモジュール * */ #include <scpp_os.hpp> #include <scpp_thread.hpp> namespace { } // namespace 無名名前空間 namespace scpp { //////////////////////////////////////////////////////////////////////////////// // // ThreadException // /** * 最後に発生した errno に対するメッセージをもつ Exception を構築します. * エラーメッセージを取得できない場合, 空文字がメッセージに設定されます. */ ThreadException::ThreadException() throw() : Exception() { } /** * コピーコンストラクタ. * * @param t コピー元 */ ThreadException::ThreadException(const ThreadException& t) throw() : Exception(t) { } /** * 指定されたメッセージをもつ ThreadException を構築します. * * @param msg メッセージ */ ThreadException::ThreadException(const std::string& msg) throw() : Exception(msg) { } /** * デストラクタ. */ ThreadException::~ThreadException() throw() { } //////////////////////////////////////////////////////////////////////////////// // // Thread // /** * スレッドを構築します. */ Thread::Thread() : runnable(0), aliveState(false) { // NOP } /** * スレッドを構築(コピー)します. * * @param t コピー元 */ Thread::Thread(const Thread& t) : runnable(t.runnable), aliveState(t.aliveState) { // NOP } /** * 指定された Runnable を実行するスレッドを構築します. * * @param r スレッドで実行する Runnable */ Thread::Thread(Runnable* r) : runnable(r), aliveState(false) { // NOP } /** * スレッドを破棄します. */ Thread::~Thread() { // NOP } /** * スレッドが生きているか否かを返します. * * @return ture/false (スレッドが生存している/していない) */ bool Thread::isAlive() { return aliveState; } /** * スレッドで実行される関数. */ void Thread::run() { if (runnable != 0) { runnable->run(); } } /** * スレッドを開始します. */ void Thread::start() { if (aliveState) { throw ThreadException("already running"); } aliveState = true; bool ret = createThread(); if (!ret) { aliveState = false; throw ThreadException(); } } /** * スレッドが終了するのを待機します. */ void Thread::join() { #if (SCPP_IS_WINDOWS) WaitForSingleObject(tid, INFINITE); CloseHandle(tid); #else pthread_join(tid, 0); #endif } /** * 指定された ms 間スリープします。 * * @param time スリープする時間(ms) */ void Thread::sleep(long time) { #if (SCPP_IS_WINDOWS) Sleep(time); #else struct timespec req; long sec = time / 1000; long msec = time - (sec * 1000); req.tv_sec = sec; req.tv_nsec = msec * 1000000; nanosleep(&req, 0); #endif } /** * スレッドを生成します. * * @return スレッドのハンドル */ bool Thread::createThread() { #if (SCPP_IS_WINDOWS) threadId = 0; tid = (thread_t) _beginthreadex( 0, 0, &Thread::executeThread, this, 0, &threadId); return (tid != 0); #else int ret = pthread_create(&tid, 0, &Thread::executeThread, this); return (ret == 0); #endif } /** * スレッド実行用関数 * 本関数は, Thread::start メソッドからのみ実行されます. * * @param args Thread ポインタ */ #if (SCPP_IS_WINDOWS) unsigned __stdcall Thread::executeThread(void* args) { scpp::Thread* thread = reinterpret_cast<scpp::Thread*>(args); thread->run(); thread->aliveState = false; // _endthreadex は自動で呼び出されるので省略. // _endthreadex(0); return 0; } #else void* Thread::executeThread(void* args) { scpp::Thread* thread = reinterpret_cast<scpp::Thread*>(args); thread->run(); thread->aliveState = false; // pthread_exit(0); return 0; } #endif //////////////////////////////////////////////////////////////////////////////// // // Mutex // /** * Mutex を構築します. */ Mutex::Mutex() { #if (SCPP_IS_WINDOWS) mutex = CreateMutex(0, false, 0); #else pthread_mutex_init(&mutex, 0); #endif } /** * Mutex を破棄します. */ Mutex::~Mutex() { #if (SCPP_IS_WINDOWS) CloseHandle(mutex); #else pthread_mutex_destroy(&mutex); #endif } /** * ロックします. */ void Mutex::lock() { #if (SCPP_IS_WINDOWS) WaitForSingleObject(mutex, INFINITE); #else pthread_mutex_lock(&mutex); #endif } /** * ロックを解除します. */ void Mutex::unlock() { #if (SCPP_IS_WINDOWS) ReleaseMutex(mutex); #else pthread_mutex_unlock(&mutex); #endif } } // namespace scpp