#include <Windows.h>

DWORD WINAPI MyThreadProc(LPVOID lpParam)
{
	for (int i = 0; i < 10000; i++)
	{
		printf(".");
	}

	printf("\n");
	return 0;
}

int main()
{
	DWORD dwThreadId = 0;
	HANDLE hThread = CreateThread(NULL, 0, &MyThreadProc, NULL, 0, &dwThreadId);
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);
    return 0;
}

#include <stdio.h>
#include <process.h>
#include <Windows.h>

void MyThreadProc3(void* pArguments)
{
	for (int i = 0; i < 10000; i++)
	{
		printf(".");
	}

	printf("\n");
}

int main()
{
	unsigned int threadID = 0;
	HANDLE hThread3 = (HANDLE)_beginthread(&MyThreadProc3, 0, NULL);
	WaitForSingleObject(hThread3, INFINITE);
	CloseHandle(hThread3);

	return 0;
}

unsigned int threadID = 0;
HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, &MyThreadProc2, NULL, 0, &threadID);
WaitForSingleObject(hThread2, INFINITE);
CloseHandle(hThread2);

DWORD WINAPI MyThreadProc(LPVOID lpParam)
{
	for (int i = 0; i < 100; i++)
	{
		printf(".");
		Sleep(50);
	}

	printf("\n");
	return 0;
}

long _x = 0;
long _y = 0;
CRITICAL_SECTION _cs1;

DWORD WINAPI MyThreadP1(LPVOID lpParam)
{
	InitializeCriticalSection(&_cs1);

	for (int i = 0; i < 10000; i++)
	{
		EnterCriticalSection(&_cs1);
		_x++;
		_y++;
		printf("%d/%d.", _x, _y);
		LeaveCriticalSection(&_cs1);
	}

	printf("\n");
	return 0;
}

int main()
{
	DWORD dwThreadId1 = 0;
	HANDLE hThread1 = CreateThread(NULL, 0, &MyThreadP1, NULL, 0, &dwThreadId1);
	DWORD dwThreadId2 = 0;
	HANDLE hThread2 = CreateThread(NULL, 0, &MyThreadP1, NULL, 0, &dwThreadId2);
	DWORD dwThreadId3 = 0;
	HANDLE hThread3 = CreateThread(NULL, 0, &MyThreadP1, NULL, 0, &dwThreadId3);
	HANDLE hTab[3] = { hThread1, hThread2, hThread3 };
	WaitForMultipleObjects(3, hTab, TRUE, INFINITE);
	CloseHandle(hThread1);
	CloseHandle(hThread2);
	CloseHandle(hThread3);

	return 0;
}

void DoSimpleTask(void)
{
	Logger::LogDebug("Enter DoSimpleTask...");
	wait(1000);
	Logger::LogDebug("Leave DoSimpleTask...");
}

void Call_Task_Group_Run()
{
	// Déclaration du Task Group
	task_group g;
	// Avec une déclaration explicite de task_handle et de prototype
	task_handle<void (*)(void)> t1 = make_task(&DoSimpleTask);
	// Avec auto
	auto t2 = make_task(&DoSimpleTask);
	// Avec std::tr1::function
	std::function<void (void)> f3 = &DoSimpleTask;
	auto t3 = make_task(f3);
	// Création des tâches
	g.run(t1);
	g.run(t2);
	g.run(t3);
	g.run( &DoSimpleTask );
	g.wait();
}

 
int DoSimpleTask_Random()
{
	Logger::LogDebug("Enter DoSimpleTask_Random...");
	wait(1000);
	// Génération d'un nombre aléatoire de 1..1000
	unsigned int r = 0;
	srand(1); rand_s(&r);
	r = (unsigned int) ((double)r / ((double) UINT_MAX + 1 ) * 1000.0) + 1;
	Logger::LogDebug("Leave DoSimpleTask_Random...");
	return r;
}

void Call_Task_Group_Run_Extras()
{
	std::function<int (void)> f1 = &DoSimpleTask_Random;
	task<int> t1(f1);
	t1.wait();
	int ret = t1.get();
	printf("Tasks t1 returns %d\n", ret);

	std::function<void (void)> f2 = &DoSimpleTask;
	task<void> t2(f2);
	t2.wait();
}

void Call_Task_Group_Run_Extras_WithOperator()
{
	std::function<int (void)> f1 = &DoSimpleTask_Random;
	task<int> t1(f1);
	std::function<int (void)> f2 = &DoSimpleTask_Random;
	task<int> t2(f2);
	(t1 && t2).wait();
	printf("Tasks t1 returns %d\n", t1.get());
	printf("Tasks t2 returns %d\n", t2.get());
}

void Call_Task_Group_Run_Extras_WithOperator2()
{
	std::function<void (void)> f1 = &DoSimpleTask;
	task<void> t1(f1);
	std::function<void (void)> f2 = &DoSimpleTask;
	task<void> t2(f2);
	std::tr1::function<void (void)> f3 = &DoSimpleTask;
	auto t3 = (t1 && t2).then(f3);
	t3.wait();
}