	
#ifndef THREADS_H
#define THREADS_H

#include "common.h"

#include <winsock2.h>
#include <windows.h>
#include <exception>

namespace threads
{
	/// forward declaration
	class thread;

	// ################################################################################################

	/// runnable interface 
	class runnable 
	{
	public:
		virtual void operator()(thread* thd) = 0;
	};

	// ################################################################################################

	/// thread class
	class thread 
	{
	public:
		/** Vytvori novy objekt vlakna */
		thread(runnable* runObj, bool suspended);
		/** Nastartuje vlakno, pokud bylo vytvoreno jako suspendovane 
		*/
		void start(void);

		/** Ceka na ukonceni cinnosti vlakna a pak uklidi jeho datove struktury 
		*/
		void join(void);
		/** Ceka na ukonceni cinnosti vlakna po dobu miliseconds a pak uklidi jeho datove struktury 
		  * @return True, pokud bylo vlakno uspesne ukonceno a uvolneno, false jinak. */
		bool join(DWORD miliseconds);

		/** Spusti vlakno, radeji nepouzivat! 
		*/
		void resume(void);
		/** Stopne vlakno, radeji nepouzivat! 
		*/
		void suspend(void);

		/** Zjisti, zda vlakno je spustene. 
		 * @retval True, pokud je spustene, false jinak. 
		 */
		bool isAlive(void);
	private:
		HANDLE threadHandle_;
	};

	// ################################################################################################

	/// Mutex class
	class mutex 
	{
	private:
		HANDLE mutexHandle_;
	public:
		mutex();
		~mutex();
		void lock(void);
		bool lock(DWORD miliseconds);
		void unlock(void);
	};

	// ################################################################################################

	/// Semaphore class
	class semaphore
	{
	private:
		HANDLE semaphoreHandle_;
	public:
		semaphore(int initcnt, int maxcnt);
		~semaphore();
		void up(void);
		void down(void);
		bool down(DWORD miliseconds);
	};

	// ################################################################################################

	void sleepCurrentThread(DWORD miliseconds);
}

#endif 