[C++] Thread safe

@deep

Bei setVal sollte das Beispiel threadsicher sein, da keine return Anweisung vorhanden ist. Das Beispiel ist equivalent mit:
C++:
boost::mutex locker;
int Val;
 
void setVal(int v)
{
   locker.lock():
   Val = v;
   locker.unlock();
}

Aber bei den getMethoden, generell bei Schreibzugriff habe ich Return-Anweisung und da hast du Recht, der Destruktor wird davor aufgerufen.

@Cromon Es geht mir nicht um threadsicherheit im Destruktor, die Beispiele habe ich verwendet weil ich aktuell boost::mutex::lock_guard(..) benutze in Memberfunktionen.

Das mit dem möglicherweise veralteten Wert meine ich so: Ich habe die get und set Funktion (siehe oben)
Code:
Thread1: getVal - temp. Variable angelegt
Thread1: getVal - mutex locked
Thread1: getVal - Zuweisung der temp. Variable
Thread1: getVal - mutex unlocked
Thread2: setVal - locked, schreibe Wert auf Val, unlocked
Thread1: getVal - return temp. Var // hier ist nun ein veralteter Wert
// Thread1 könnte auch mitten in der return-Anweisung unterbrochen werden

mfg
 
Zuletzt bearbeitet:
Das Objekt lock_guard ist einfach nur eine Abkürzung für lock und unlock...
Es macht kein Sinn diese Klasse global zu haben dann würde er den Mutex erst wieder im Destruktor freigeben...

So danke ersma an alle, denke das hat sich erledigt. Falls noch einer ein Tip hat wie er/sie das machen würde dann scheut euch nicht ;-]
 
Das Objekt lock_guard ist einfach nur eine Abkürzung für lock und unlock...
Es macht kein Sinn diese Klasse global zu haben dann würde er den Mutex erst wieder im Destruktor freigeben...
Du hast es immer noch nicht verstanden.

Ich kenne Boost.Thread.

Es war nicht mein Vorschlag ein globales Objekt anzulegen. Es ist allerdings notwendig eine Variable innerhalb der Funktion zu definieren, denn ansonsten darf der Compiler das temp. Objekt welches du erzeugt hast, direkt wieder wegräumen (da es nicht mehr verwendet werden kann), was dann dazu führen würde, dass der Mutex wieder freigegeben wird...

Gruß
 
Ich will das Objekt auch nicht verwenden. Ich habe dich jetzt verstanden, du meinst es gibt einen Unterschied zwischen:
C++:
int getVal()
{
   boost::lock_guard(locker);
   return Val;
}
und
C++:
int getVal()
{
   boost::lock_guard foo(locker);
   return Val;
}
Meine Testklasse oben spuckt das gleiche Ergebnis aus. Wärst du so freundlich und erklärst mir den Unterschied außer das ich das temp. Objekt nicht mehr ansprechen kann ? Meinst du der Compiler löscht es dann gleich wieder ? (dürfte) Im Falle von lock_guard() macht es nämlich keinen Sinn davon eine Variable anzulegen da es nur einen Konstruktor und Destruktor besitzt wie du ja weist.

Mir ist noch was eingefallen, was ist wenn ich eine Referenz oder Pointer zurückgeben möchte ?
C++:
// aktueller code der nicht threadsicher ist !?
// Alternative hier nich einsetzbar da ich keine Kopie habe will
Weight* Interface::getWeight()
{
    locker.lock();
    return &weighting;
    // locker.unlock() // wird wohl niemals aufgerufen
}

Danke für eure Mühe.
 
Zuletzt bearbeitet:
Meinst du der Compiler löscht es dann gleich wieder ?
Ja, genau das ist das Problem. Der Compiler darf temp. Objekte zerstören sobald diese nicht mehr zugreifbar sind.

Siehe http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=198
Im Falle von lock_guard() macht es nämlich keinen Sinn davon eine Variable anzulegen da es nur einen Konstruktor und Destruktor besitzt wie du ja weist.
Doch, es macht ziemlich viel Sinn. Damit erreicht man, das das Objekt auch bis zum Ende des Skopus überlebt...

Gruß
 
Alles klar, wieder was gelernt. :)
Hat noch wer Tips wie ich Referenzen sicher zurückgeben kann ? siehe Bsp. auf der 1. Seite
 
Alles klar, wieder was gelernt. :)
Hat noch wer Tips wie ich Referenzen sicher zurückgeben kann ? siehe Bsp. auf der 1. Seite
Du könntest z.B. die Methoden des zurückgegebenen Objektes threadsicher machen.

Du könntest auch eine Art Smartpointer verwenden. Sowas in der Art:
C++:
template <typename T>
class Pointer {
  boost::mutex m;
  T* obj;
public:
  class Locker : public boost::non_copyable {
    T* obj;
    boost::lock_guard guard;
  public:
     Locker(T* o, boost::mutex& m) :obj(o), guard(m) {}

      T* operator->() const {
        return obj;
      }
  }

public:
  Pointer(T* o) : obj(o) {}
  Locker operator->() {
    return Locker(o, m);
  }
};

typedef std::pair<int, int> tp;
tp aPair(3, 5);
Pointer<tp> p(&aPair);

p->first;
p->second;
Gruß
 
Zuletzt bearbeitet:
Zurück