2012-07-25 8 views
5

Beim Versuch, eine threadsichere Containerklasse von Grund auf neu zu erstellen, bin ich auf das Problem der Rückgabe von Werten von Zugriffsmethoden gestoßen. Zum Beispiel unter Windows:Kritische Abschnitte und Rückgabewerte in C++

myNode getSomeData() 
{ 
    EnterCriticalSection(& myCritSec); 
    myNode retobj; 
    // fill retobj with data from structure 
    LeaveCriticalSection(& myCritSec); 
    return retobj; 
} 

Jetzt nehme ich an, dass diese Art von Verfahren ist durchaus nicht Thread-sicher, da, nachdem der Code gibt den kritischen Abschnitt einen anderen Thread, mitzukommen in der Lage ist und sofort retobj vor dem ersten Thread überschreibt kehrt zurück. Also, was ist eine elegante Möglichkeit, retobj an den Aufrufer in einer thread-sicheren Art und Weise zurückzugeben?

+1

Aber retobj auf dem Stapel gespeichert? Wenn es nicht als 'statisch' deklariert ist, sollten Sie keine Probleme mit den überschriebenen Daten haben. –

+0

Wenn nicht etwas Seltsames passiert, sollte 'retobj' auf dem Stack sein, und jeder Thread sollte seinen eigenen Stack haben. Race-Bedingungen dieser Art treten häufiger auf, wenn Sie mit bereits zugewiesenem Speicher arbeiten und den Zugriff sperren müssen, um eine gemeinsame Nutzung zu verhindern. – ssube

+0

@Inface, ok guter Punkt, solange der Rückgabewert auf dem Stack gespeichert ist, bin ich gut. – ThomasMcLeod

Antwort

7

Nein, es ist Thread-sicher, weil jeder Thread seinen eigenen Stack hat, und das ist, wo retobj ist.

Allerdings ist es sicherlich nicht ausnahmesicher. Wenn Sie den kritischen Abschnitt in ein Objekt im RAII-Stil einfügen, würde das helfen. So etwas wie ...

class CriticalLock : boost::noncopyable { 
    CriticalSection &section; 

public: 
    CriticalLock(CriticalSection &cs) : section(cs) 
    { 
    EnterCriticalSection(section); 
    } 

    ~CriticalLock() 
    { 
    LeaveCriticalSection(section); 
    } 
}; 

Verbrauch:

myNode getSomeData() 
{ 
    CriticalLock lock(myCritSec); // automatically released. 
    ... 
} 
2

Dies ist C++, und retobj hat einen automatischen Speichertyp, so dass es auf dem Stapel gespeichert ist.

Jeder Thread hat seinen eigenen Stack, daher kann ein anderer Thread den Wert retobj nicht überschreiben, bevor er zurückgegeben wird.

Verwandte Themen