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

using namespace std;

// zmienna globalna
double liczba;

// tworzymy sekcje krytyczna do wypisywania i zmian liczby
CRITICAL_SECTION wyp;
CRITICAL_SECTION change;

DWORD WINAPI Wypisz(PVOID pvParam)
{
   int nr=*(int*)pvParam;
   // czekamy na wejscie do sekcji krytycznej
   while (TryEnterCriticalSection(&wyp)==FALSE)
   {
      //cout<<"\n(czekam_"<<nr<<")"<<endl;
      Sleep(5);
   }
   // weszlismy do sekcji krytycznej
   cout<<"\nJestem w sekcji krytycznej "<<nr<<", wartosc liczby to: "<<liczba<<endl;
   Sleep(5);
   // opuszczamy sekcje krytyczna
   LeaveCriticalSection(&wyp);
   //cout<<"\nWwyszedlem z sekcji krytycznej "<<nr<<endl;

   return 0;
}

DWORD WINAPI Zmien(PVOID pvParam)
{
   for(;;)
   {
      srand(time(NULL)*1000);
      int los1=rand()%1000;
      int los2;
      int op=rand()&4;
      while(TryEnterCriticalSection(&change)==FALSE)
      {
         los2=rand()%100; // w oczekiwaniu losujemy co rozn nowa liczbe
      }
      // weszlismy do sekcji krytycznej
      switch(op)
      {
         case 0:
            liczba+=los1-los2;
            break;
         case 1:
            liczba+=los1*los2-los1;
            break;
         case 2:
            liczba+=los2+(los1*los2%20)/los2+los1-5*los2;
            break;
         case 3:
            liczba-=los1-los2+(los1/los2);
            break;
      }
      // opuszczamy sekcje krytyczna
      LeaveCriticalSection(&change);
   }
   return 0;
}

int main()
{

   // tworzymy tablicę wątkow
   HANDLE TArW[6];
   HANDLE TArCh[6];
   DWORD IdAr[12];
   int nr[6]={1,2,3,4,5,6};

   // inicjalizujemy sekcje krytyczne
   InitializeCriticalSection(&wyp);
   InitializeCriticalSection(&change);

   // uruchamiamy watki
   TArCh[0]=CreateThread(NULL, 0,Zmien,0, 0, &IdAr[1]);
   TArCh[1]=CreateThread(NULL, 0,Zmien,0, 0, &IdAr[2]);
   TArW[0]=CreateThread(NULL, 0,Wypisz,&nr[0], 0, &(IdAr[0]));
   TArW[1]=CreateThread(NULL, 0,Wypisz,&nr[1], 0, &IdAr[3]);
   TArCh[2]=CreateThread(NULL, 0,Zmien,0, 0, &IdAr[4]);
   TArW[2]=CreateThread(NULL, 0,Wypisz,&nr[2], 0, &IdAr[5]);
   TArCh[3]=CreateThread(NULL, 0,Zmien,0, 0, &IdAr[6]);
   TArCh[4]=CreateThread(NULL, 0,Zmien,0, 0, &IdAr[7]);
   TArW[3]=CreateThread(NULL, 0,Wypisz,&nr[3], 0, &IdAr[8]);
   TArCh[5]=CreateThread(NULL, 0,Zmien,0, 0, &IdAr[9]);
   TArW[4]=CreateThread(NULL, 0,Wypisz,&nr[4], 0, &IdAr[10]);
   TArW[5]=CreateThread(NULL, 0,Wypisz,&nr[5], 0, &IdAr[11]);

   // czekamy na zakonczenie watkow wypisywania
   WaitForMultipleObjects(6,TArW,TRUE,INFINITE);

   // zamykamy watki zmieniajace
   for (int i=0; i<6; i++)
   {
      CloseHandle(TArCh[i]);
   }

   system("PAUSE");
   return 0;
}
//---------------------------------------------------------------------------
 