#include <windows.h>
#include <iostream>

using namespace std;

int i;

DWORD WINAPI TFunc1(PVOID pvParam)
{
   int licznik=0;
   // otwieramy u siebie mutexa
   HANDLE hMutex = *(HANDLE*)pvParam;
   // czekamy na zwolnienie sie mutexa
   while (licznik<10)  // jesli 10 razy nie ikrementowalismy
   {
      WaitForSingleObject(hMutex, INFINITE);
         //teraz jestesmy w sekcji krytyczne
         cout<<"Jestem watek 1, wykonuje i++\n";
         i++;
         // opuszczam sekcje krytyczna
      ReleaseMutex(hMutex);
      licznik++;
   }
   return 0;

}

DWORD WINAPI TFunc2(PVOID pvParam)
{
   int licznik=0;
   // otwieramy u siebie mutexa
   HANDLE hMutex = *(HANDLE*)pvParam;
   // czekamy na zwolnienie sie mutexa
   while (licznik<10)  // jesli 10 razy nie ikrementowalismy
   {
      WaitForSingleObject(hMutex, INFINITE);
         //teraz jestesmy w sekcji krytyczne
         cout<<"Jestem watek 2, wykonuje i--\n";
         i--;
         // opuszczam sekcje krytyczna
      ReleaseMutex(hMutex);
      licznik++;
   }
   return 0;

}

DWORD WINAPI TFunc3(PVOID pvParam)
{
   int licznik=0;
   // otwieramy u sibie mutexa
   HANDLE hMutex = *(HANDLE*)pvParam;
   // czekamy na zwolnienie sie mutexa
   while (licznik<10)  // jesli 10 razy nie ikrementowalismy
   {
      WaitForSingleObject(hMutex, INFINITE);
         //teraz jestesmy w sekcji krytyczne
         cout<<"Jestem watek 3, wykonuje i++\n";
         i++;
         // opuszczam sekcje krytyczna
      ReleaseMutex(hMutex);
      licznik++;
   }
   return 0;
}

int main()
{
   HANDLE hThread[3];
   DWORD Thread1ID,Thread2ID,Thread3ID;

   // tworzymy mutex
   HANDLE hMutex=CreateMutex(NULL,TRUE,"Teraz Twoja kolej!");

   //tworzymy 3 watki
   // w parametrze przekazujemy adres mutexa
   hThread[0]=CreateThread(NULL,0,TFunc1,&hMutex,0,&Thread1ID);
   hThread[1]=CreateThread(NULL,0,TFunc2,&hMutex,0,&Thread2ID);
   hThread[2]=CreateThread(NULL,0,TFunc3,&hMutex,0,&Thread3ID);

   cout<<"Jestem watek glowny, zaraz oddam mutexa!\n\n";
   // posiadaczem mutexa jest teraz watek ktory go stworzyl

   // oddajemy teraz mutexa do dyspozycji innym watkom
   ReleaseMutex(hMutex);

   // czekamy az wszystkie inne watki skoncza dzialanie
   WaitForMultipleObjects(3, hThread, TRUE, INFINITE);

   cout<<endl<<"Jestem watek glowny, witam z powrotem, wartosc zmiennej globalnej i to: "<<i<<endl;
   CloseHandle(hMutex);

   system("PAUSE");

   return 0;
}
//---------------------------------------------------------------------------
