/* =============================================================================
 *  scpp_thread.hpp
 *  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
 * =============================================================================
 *
 * スレッドモジュール
 *
 */
#ifndef SCPP_THREAD_HPP
#define SCPP_THREAD_HPP

#include <scpp_os.hpp>
#include <scpp_exception.hpp>

#if (SCPP_IS_WINDOWS)
#include <process.h>
typedef HANDLE           thread_t;
typedef HANDLE	         mutex_t;

#else
#include <pthread.h>
#include <time.h>
typedef pthread_t        thread_t;
typedef pthread_mutex_t  mutex_t;

#endif	// SCPP_IS_WINDOWS

namespace scpp
{



/**
 * スレッドを実行する全てのクラスでは, この Runnable インタフェースを
 * 実装する必要があります. 本インタフェースを実装するクラスは,
 * 引数のない run メソッドを実装する必要があります.
 *
 * 以下にコード例を示す.
 * @code
 * class MyRunnable : public Runnable
 * {
 *   public:
 *     void run()
 *     {
 *	     // スレッドで実行する内容
 *     }
 * }
 *
 * int main(int argc, char* argv[])
 * {
 *   MyRunnable r;
 *   Thread     t(&r);
 *   t.start();        // <- MyRunnable の run が別スレッドで実行される
 *   t.join();         // <- スレッドが終了するまで待つ
 *   return 0;
 * }
 * @endcode
 */
class Runnable
{
	public:
		virtual void run() = 0;
};


/**
 * スレッドに関するエラー発生時に throw される Exception.
 */
class ThreadException : public Exception
{
	public:
		ThreadException() throw();
		ThreadException(const ThreadException& t) throw();
		ThreadException(const std::string& msg) throw();
		virtual ~ThreadException() throw();
};



/**
 * スレッドクラス.
 * 本クラスまたは, Runnable を継承しスレッドを作成することが可能です.
 * @code
 * 使用例)
 *
 * class SampleThread : Thread
 * {
 *   public:
 *     void run()
 *     {
 *       // スレッドで動作させるコード
 *     }
 * };
 *
 * SampleThread thread;
 * thread.start();   // <-- スレッドを起動
 * thread.join();    // <-- スレッドが終了するまで待つ
 *
 * @endcode
 */
class Thread : public Runnable
{
	public:
		Thread();
		Thread(const Thread& t);
		Thread(Runnable* r);
		virtual ~Thread();
		virtual void run();
		void start();
		bool isAlive();
		void join();
		static void sleep(long time);

	protected:
		virtual bool   createThread();

	private:
		Runnable* runnable;
		bool      aliveState;
		thread_t  tid;

#if (SCPP_IS_WINDOWS)
		static unsigned __stdcall executeThread(void* args);
		unsigned int threadId;
#else
		static void* executeThread(void* args);
#endif

};


/**
 * Mutex を扱う.
 */
class Mutex
{
	public:
		Mutex();
		virtual ~Mutex();
		void lock();
		void unlock();
	private:
		mutex_t mutex;


};

}	// namespace scpp

#endif	// SCPP_THREAD_HPP

