PDA

Prikaži potpunu verziju : Deljene i lokalne promenljive, C++, WinAPI


Lucic Nemanja
11.1.2014, 13:39
Dakle, trenutno radim na implementaciji fajl sistema za projekat na fakultetu i potrebno je da se implementira pristup fajlu po principu multiple readers - single writer i to bez izgladnjivanja bilo koga. Shodno tome našao sam ovaj (http://en.wikipedia.org/wiki/Readers-writers_problem) wiki članak koji govori o rešenjima za dati problem i opredelio sam se za treći pošto on ne izgladnjuje ni čitaoce ni pisce. Sve je to ok, algoritam mi je jasan u potpunosti, ali imam tehničkih problema.
Prilično sam noob što se tiče višenitnog programiranja i ne znam još kako funkcionišu stvari u tom domenu.
Želeo bih da napravim klasu koja će da enkapsulira svu logiku pritupa po datom principu. Gruba definicija klase bi izgledala ovako:

class RWMonitor
{
private:
int nreaders; // shared
int prev, current; // local
HANDLE waitMutex, accessMutex, cntMutex;

public:
void beginReading();
void endReading();

void beginWriting();
void endWriting();
};


Posle bih sve pozive za samu logiku čitanja i pisanja omotavao ovim metodama.

Moje pitanje je, kako se prave deljene promenljive, a kako lokalne? Ideja mi je da svaki objekat otvorenog fajla ima po jednu instancu ove klase koja bi upravljala pristupom svom fajlu.

Ne znam da li je relevantno, ali koristi se win api za višenitne funkcionalnosti.

Ivan452
11.1.2014, 14:25
Pogleda ovo, mislim da ce ti pomoci:
http://www.glennslayden.com/code/win32/reader-writer-lock

A ovde imas resenje koriscenjem semafora:
http://www.codeproject.com/Articles/3023/A-solution-to-the-Readers-Writers-Problem-using-se

Da bi delio promenljive najbolje je da ti budu static tipa.
Ali, mislim da ti to nije potrebno. Jer je ideja da imas jedan objekat (strukturu) koji ce da upravlja citanjem i pisanjem objekata koji to zele da urade.

Lucic Nemanja
11.1.2014, 17:28
Nisu mi ovi linkovi bili od mnogo pomoći pošto u ovim rešenjma postoji problem izgladnjivanja, ali hvala u svakom slučaju. Uspeo sam da smislim neko rešenje mada ga nisam još istestirao. Ako ikog zanima ili mu bude potrebno evo staviću ga ovde :).



#ifndef _RWMONITOR_H_
#define _RWMONITOR_H_

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

class RWMonitor
{
private:
unsigned int n_readers;
std::map<DWORD, unsigned int> prev;
std::map<DWORD, unsigned int> current;

HANDLE waitingMutex, accessingMutex, cntMutex;

public:
RWMonitor();
~RWMonitor();

void beginReading();
void endReading();

void beginWriting();
void endWriting();
};

#endif




#include "RWMonitor.h"

RWMonitor::RWMonitor()
{
this->accessingMutex = CreateMutexA(0, true, 0);
this->accessingMutex = CreateMutexA(0, true, 0);
this->accessingMutex = CreateMutexA(0, true, 0);

this->n_readers = 0;
}

RWMonitor::~RWMonitor()
{
::CloseHandle(this->accessingMutex);
::CloseHandle(this->waitingMutex);
::CloseHandle(this->cntMutex);
}

void RWMonitor::beginWriting()
{
::WaitForSingleObject(this->waitingMutex, INFINITE);
::WaitForSingleObject(this->accessingMutex, INFINITE);
::ReleaseMutex(this->waitingMutex);
}

void RWMonitor::endWriting()
{
::ReleaseMutex(this->accessingMutex);
}

void RWMonitor::beginReading()
{
::WaitForSingleObject(this->waitingMutex, INFINITE);

::WaitForSingleObject(this->cntMutex, INFINITE);
this->prev[::GetCurrentThreadId()] = this->n_readers;
this->n_readers++;
::ReleaseMutex(this->cntMutex);

if (this->prev[::GetCurrentThreadId()] == 0)
::WaitForSingleObject(this->accessingMutex, INFINITE);

::ReleaseMutex(this->waitingMutex);
}

void RWMonitor::endReading()
{
::WaitForSingleObject(this->cntMutex, INFINITE);
this->n_readers--;
this->current[::GetCurrentThreadId()] = n_readers;
::ReleaseMutex(this->cntMutex);

if (this->current[::GetCurrentThreadId()] == 0)
::ReleaseMutex(this->accessingMutex);

this->prev.erase(::GetCurrentThreadId());
this->current.erase(::GetCurrentThreadId());
}



Problem lokalnih promenljivih sam rešio tako što sam napravio mapu gde sam za svaku nit alocirao promenljivu. Pošto postoji samo jedan objekat klase RWMonitor, n_readers promenljiva je svakako deljena između svih niti koje konkrišu za pristup datom fajlu.