/*
	ZConcurrency.hpp
	Author : James Russell, Patrick Baggett

	Purpose :	Provides a number of primitives for building concurrent programs. Each supported
	            platform has a separate implementation.

	Changelog
	1/24/11 - Creation (jcrussell)
	3/17/11 - Major change to support events, mutexes, thread local storage, and semaphores. (ptbaggett)
*/

#pragma once

#ifndef _ZCONCURRENCY_HPP
#define _ZCONCURRENCY_HPP

#include <ZUtil/ZUtilBuild.hpp>
#include <ZUtil/ZSemaphore.hpp>
#include <ZUtil/ZMutex.hpp>
#include <ZUtil/ZEvent.hpp>
#include <ZUtil/ZReadWriteLock.hpp>

//Used to indicate an indefinite wait
#define ZWAIT_INFINITE (~((uint32_t)0))

//Typedef for a thread handle
typedef void* ZThreadHandle;

/*
ZEngine thread data, used as a context for threads. The fields here should not be accessed directly.
*/
struct ZThreadContext
{
	//The handle to this thread
	ZThreadHandle Thread;

	//The id given to this thread. Unique, but may be reused after thread is destroyed
	uint32_t ThreadId;

	//The return status this thread exited with (invalid unless Thread == NULL)
	int ThreadExitStatus;

	//Default Constructor
	ZThreadContext() { Invalidate(); }

	//Returns if it's valid
	bool IsValid() const { return Thread != NULL; }

	//Marks a thread context as invalid
	void Invalidate() { Thread = NULL; ThreadId = 0; ThreadExitStatus = 0; }
};

/*
Namespace used for static access to low-level thread functionality.
*/
namespace ZConcurrency
{
	/*
	ZThreadContext CreateThread()
	
	Creates a thread instance that will begin running the provided function.
	The thread context should be cleaned up with DestroyThread() after the
	thread exits (use WaitThread() to ensure it is exited).

	@param _func - function that the thread will execute.  Should be of return type
		int and take a void* as an argument.
	@param _arg - the argument that is passed to the function.
	
	@return (ZThreadContext) - thread context, used as a handle to the thread
	*/
	ZThreadContext CreateThread(int(*_func)(void*), void *_arg);

	/*
	void DestroyThread()
	
	Frees memory associated with a thread context. This should only be called
	after the thread is known to be dead (e.g. using WaitThread()). As implied
	by the last comment, this does not kill the OS thread if it was already
	running.

	@param _context - Thread context to be cleaned up
	@return (void)
	*/
	void DestroyThread(ZThreadContext& _context);

	/*
	void SleepThread()

	Causes the calling thread to sleep for a minimum of the specified time (in ms).

	@param _ms - the specified time to sleep (in ms)
	@return (void)
	*/
	void SleepThread(uint32_t _ms);

	/*
	int GetThreadId()

	Gets the thread ID of the calling thread.

	@return (uint32_t) -  int that is the thread id of the calling thread
	*/
	uint32_t GetThreadId();
	
	/*
	unsigned int GetTicks()

	Gets the tick count since the last call to GetTicks.

	@return (uint64_t) - the count (in ms) since program start.
	*/
	uint64_t GetTicks();
	
	/*
	int WaitThread()

	Waits for a thread to terminate.  This is the only way to ensure thread resources are
	returned.  The termination code from the thread is stored in the thread context.

	@param _context - the handle returned from CreateThread (the termination code is stored here)
	@return (bool) - true if the thread terminated, false otherwise
	*/
	bool WaitThread(ZThreadContext& _context);

	/*
	void YieldThread()

	Causes the calling thread to yield execution to another thread.

	@return (void)
	*/
	void YieldThread();
}

#endif

