Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem C++ mutex přes více funkcí

Dobrý den,
Snažím se udělat dvouvláknovou aplikaci v c++, kde jedno vlákno čte střídavě do dvou bufferů znaky ze souboru a druhé vlákno tyto buffery poté zpracovává. Funguje to celé pomocí eventů. které oboum vláknům říkají, kdy začít s Parsováním bufferu, nebo kdy je možné načítat do bufferu. Přístup k bufferům jsem řešil pomocí mutexů..(viz následující kód)

funkce pro zapisování do bufferu:

	void ReadDataFromPath(){
		DWORD waitResult;

		/*
		Pokud je buffer jedna prazdny, pak do nej nahraji data
		pozn:. dodelat cestu z argumentu a novou funkci pro nahravani dat
		*/
		if(bufferOneIsClear == true){
			waitResult = WaitForSingleObject(mutexBuffer1, INFINITE);
			//if pro kontrolu
			cout<<"Plnim buffer 1.."<<endl;
			Sleep(5000);
			cout<<"Buffer 1 naplnen.."<<endl;
			bufferOneIsClear = false;
			SetEvent(eventToParse);
			ReleaseMutex(mutexBuffer1);
		}else if(bufferOneIsClear == false){
			waitResult = WaitForSingleObject(mutexBuffer2, INFINITE);
			//if pro kontrolu
			cout<<"Plnim buffer 2.."<<endl;
			Sleep(5000);
			cout<<"Buffer 2 naplnen.."<<endl;
			bufferOneIsClear = true;
			SetEvent(eventToParse);
			ReleaseMutex(mutexBuffer2);
		}

		//abych mohl pokracovat v plneni bufferu
		waitResult = WaitForSingleObject(eventToBuffering, INFINITE);
	}

funkce pro čtení z bufferu:

	void ParseDataFromBuffer(){
		DWORD waitResult = WaitForSingleObject( eventToParse, INFINITE);

		if(bufferOneIsClear == false){//ctu z bufferu 1
			waitResult = WaitForSingleObject( mutexBuffer1, INFINITE);
			SetEvent(eventToBuffering);
			cout<<"Ctu z bufferu 1.."<<endl;
			Sleep(8000); //nahrazuje zatim zpracovani
			cout<<"Buffer 1 precten.."<<endl;
			ReleaseMutex( mutexBuffer1);
			return;
		}
		if(bufferOneIsClear == true){//ctu z bufferu 2
			waitResult = WaitForSingleObject( mutexBuffer2, INFINITE);
			SetEvent(eventToBuffering);
			cout<<"Ctu z bufferu 2.."<<endl;
			Sleep(7000);
			cout<<"Buffer 2 precten.."<<endl;
			ReleaseMutex(mutexBuffer2);
			return;
		}
	}

Tuto funkci volám ve vláknu jiné třídy:

	void ThreadStartUp(){
		//while
		while(buffers->getContinueProcessing()){
			buffers->ParseDataFromBuffer();
		}
	}

A zde nastává problém, jelikož bych chtěl zpracovávat data ne přímo ve fci getContinueProcessing(), ale v cyklu while, ve kterém je volána. Tím pádem jsem přidal novou funkci na uvolnění mutexu:

	void ParseDataFromBufferEnd(){
		if(bufferOneIsClear == false){
			ReleaseMutex(mutexBuffer1);
			return;
		}
		if(bufferOneIsClear == true){
			ReleaseMutex(mutexBuffer2);
			return;
		}
	}

..a předchozí fci getContinueProcessing() jsem pozměnil:

	void ParseDataFromBuffer(){
		DWORD waitResult = WaitForSingleObject( eventToParse, INFINITE);
		//nejaky if
		/*
		Pokud je naplnen buffer 1 prazdny, pak ctu z bufferu2 a naopak
		Ihned pred zahajenim cteni posilam event pro buffer, aby moh pokracovat
		v plneni dalsiho bufferu
		*/
		if(bufferOneIsClear == false){//ctu z bufferu 1
			waitResult = WaitForSingleObject( mutexBuffer1, INFINITE);
			SetEvent(eventToBuffering);
			cout<<"Ctu z bufferu 1.."<<endl;
			return;
		}
		if(bufferOneIsClear == true){//ctu z bufferu 2
			waitResult = WaitForSingleObject( mutexBuffer2, INFINITE);
			SetEvent(eventToBuffering);
			cout<<"Ctu z bufferu 2.."<<endl;
			return;
		}
	}

To vše volám ve while cyklu:

	void ThreadStartUp(){
		//while
		while(buffers->getContinueProcessing()){
			buffers->ParseDataFromBuffer();
			Sleep(8000);
			buffers->ParseDataFromBufferEnd();
		}
	}

Ačkoliv kód je defacto stejný, jen rozdělený do více funkcí, tak prostě přestal pracovat.. Vlákno na zpracování se prostě už nikdy nezavolá. Chtěl bych se tedy zeptat, jakým způsobem bych to měl rozdělit, nebo co dělám špatně? Nikde na internetu jsem totiž nenašel příklady přío na toto téma.

Děkuji za odpovědi.

Předmět Autor Datum
Urob nejaky prehlad ktory event je kedy jak, ptz mas tam moc eventov a mam pocit ze mas v nich chaos…
MM.. 05.04.2014 16:35
MM..
A dolezite je aj ze jak mas deklarovane kde presne tie mutexy a tie zbytocne stavove premenne, co je…
MM.. 05.04.2014 16:41
MM..
Tvoj problem bude najskor to bufferOneIsClear. Naplnis prvy buffer nastavis to na false, naplnis dru… poslední
MM.. 05.04.2014 17:10
MM..

Urob nejaky prehlad ktory event je kedy jak, ptz mas tam moc eventov a mam pocit ze mas v nich chaos, nie som schopny to ani dekodovat ze ktory event ma znamenat co a preco. Alebo daj sem zazipovany zdrojak ktory ide a ktory nejde, toto co si vlozil sa neda citat ani pochopit (mas tam nejake "bufferOneIsClear" ktore neni thread safe, a navyse cakas na nejaky event ani svaty nevie preco atd)

Take veci sa robia skor pomocou circular bufferu a nepotrebujes potom vobec nic chranit ptz citajuci ma svoj pointer a zapisujuci thread ma svoj pointer. Jedina vec ktora by potom mala byt v critical section je porovnavanie a zvysovanie tych pointrov.

Tvoj problem bude najskor to bufferOneIsClear. Naplnis prvy buffer nastavis to na false, naplnis druhy buffer nastavis to zas na true bez toho aby si vobec vedel ci to uz bolo precitane, a v tom druhom thrade na zaklade toho testujes veci pricom sa ti za jazdy tato premenna moze zmenit. Ziskas mutex1 a potom sa ti zmeni tato premenna za jazdy a neskor na zaklade nej testujes ktory mutex uvolnit??? To je absolutny chaos tak nebezpecny ze az.
Povyhadzuj vsetky stavove premenne uplne vsetko zmaz :-) a zacni robit to co kazdy slusny vyvojar - NAJPRV na papier albeo v hlave logicky navrh datovych struktur a mutexov a premennych tak aby to nebol nebezpecny chaos meniacich sa veci za jazdy, POTOM zacat pisat kod :)

Alebo

if(bufferOneIsClear == false){//ctu z bufferu 1
waitResult = WaitForSingleObject( mutexBuffer1, INFINITE);
SetEvent(eventToBuffering);
cout<<"Ctu z bufferu 1.."<<endl;
return;
}

tu sa ti moze za jazdy zmenit bufferOneIsClear

if(bufferOneIsClear == true){//ctu z bufferu 2

nectes.

Zpět do poradny Odpovědět na původní otázku Nahoru