2011-01-17 5 views
1

mit So eine Klasse wie:Wäre eine solche Klasse nur einmal durch mehrere Threads lesbar?

class mySafeData 
{ 
public: 
    mySafeData() : myData(0), changed(false) 
    { 
    } 

    void Set(int i) 
    { 
    boost::mutex::scoped_lock lock(myMutex); 
    myData = i; // set the data 
    changed = true; // mark as changed 
    myCondvar.notify_one(); // notify so a reader can process it 
    } 

    void Get(int& i) 
    { 
    boost::mutex::scoped_lock lock(myMutex); 
    while(!changed) 
    { 
     myCondvar.wait(lock); 
    } 
    i = myData; 
    changed = false; // mark as read 
    myCondvar.notify_one(); // notify so the writer can write if necessary 
    } 
private: 
    int myData; 
    boost::mutex myMutex; 
    boost::condition_variable myCondvar; 
    bool changed; 
}; 

Und ein Thread in Schleife Set aufrufen. Und 3 oder mehr Threads Aufruf Get wie alle Threads aufrufen Get machen, um tatsächlich Daten zu erhalten (jeder Thread soll Get Daten nur einmal Set wurde aufgerufen) (es scheint nur der erste "Leser" wer ruft Get ruft Daten)?

Update wird dies tun ?:

class mySafeData 
{ 
public: 
    mySafeData() : myData(0) 
    { 
    } 

    void Set(int i) 
    { 
    boost::mutex::scoped_lock lock(myMutex); 
    myData = i; // set the data 
    } 

    void Get(int& i) 
    { 
    boost::mutex::scoped_lock lock(myMutex); 
    i = myData; 

    } 
private: 
    int myData; 
    boost::mutex myMutex; 
}; 

Antwort

1

Eigentlich ist es ein seltsamer Ansatz, notify_one() im Leser (Get) aufzurufen! Wenn Sie Ihre Leser wollen warten, bis etwas gesetzt wurde, dann müssen Sie etwas wie folgt aus:

void Set(int i) 
    { 
    boost::mutex::scoped_lock lock(myMutex); 
    myData = i; // set the data 
    ++stateCounter; // some int to track state chages 
    myCondvar.notify_all(); // notify all readers 
    } 

    void Get(int& i) 
    { 
    boost::mutex::scoped_lock lock(myMutex); 
    // copy the current state 
    int cState = stateCounter; 
    // waits for a notification and change of state 
    while (stateCounter == cState) 
     myCondvar.wait(lock); 
    } 

Jetzt ein Aufruf an Get effektiv warten, bis es eine gültige Zustandsänderung ist. Dieser Ansatz (mit Bedingungen) ist jedoch anfällig für Probleme wie falsche Wakeups (die von der Schleife behandelt werden sollten), verlorene Benachrichtigungen usw. Sie müssen ein besseres Modell dafür finden (alles klingt wie ein Fall einer Warteschlange pro Thread)).

3

Ich glaube nicht, dass Sie die Bedingung Variable benötigen; der Mutex sollte genug sein.

Auch die changed Variable hilft Ihnen nicht; Es erlaubt nur einem Thread, die Änderung zu sehen. Entferne das auch.

+0

Ich habe den Post aktualisiert - meinst du, dass das Update, das ich gepostet habe, funktioniert? Mein Hauptpunkt ist, dass die Leser nicht mehr als einmal auf einem Set lesen ... – Rella

+0

Ich könnte mir vorstellen, dass das funktionieren würde (obwohl Sie wahrscheinlich 'myData' als' volatile' deklarieren müssen, um zu verhindern, dass der Compiler unsichere Optimierungen durchführt. Ich bin es nicht sicher, was Sie mit "liest nicht mehr als einmal auf jeden Satz zu lesen." Sicher wollen Sie nur 'get()', um sicher den neuesten Wert jedes Mal, wenn ein Reader Thread ruft es zurück? –

+0

Ich habe versucht, hier http zu erklären: //stackoverflow.com/questions/4713782/boost-mutex-order – Rella

Verwandte Themen