2016-06-29 27 views
3

Ich muss einige Werte in einer Klasse zurücksetzen, nachdem X Sekunden vergangen sind. Ich bin mit so etwas, aber ich weiß nicht, welche Probleme es haben könnte:In C++ wie Variablen nach X Sekunden in einer Klasse zurückgesetzt werden?

class Points 
{ 
    public: 
     Points(); 
     ~Points(); 
     void reset(); 
     ... 
    private: 
     int number; 
     static void resetAfter5seconds(Points* points); 
}; 

Im Innern des contructor ich einen freistehenden Thread initialisieren:

Points::Points(){ 
    thread start(resetAfter5seconds, this); 
    start.detach(); 
} 

void Points::resetAfter5seconds(Points* points){ 

    while(true){ 
    std::this_thread::sleep_for((std::chrono::seconds(5))); 
    points->reset(); 
    } 

} 

Dies funktioniert, aber ich weiß nicht, ob es ist der richtige Ansatz. Hat es Speicherprobleme? Was sind die Alternativen?

+3

nick-picking: Vielleicht möchten Sie einen Mutex um alles setzen, was Sie in einem anderen Thread zurücksetzen möchten. – lorro

+0

Sie benötigen keine "statische" Thread-Funktion, verwenden Sie einfach eine normale Member-Funktion. –

+1

Wenn dieses Points-Objekt jemals gelöscht wird, versucht der Reset-Thread weiterhin, darauf zuzugreifen und eine Zugriffsverletzung zu verursachen. Um dies zu beheben, müssen Sie den Destruktor verwenden, um dem zurückgesetzten Thread mitzuteilen, dass es Zeit ist, die Schleife zu beenden. Warten Sie auf das Schließen des Threads, bevor Sie vom Destruktor zurückkehren. – tsandy

Antwort

5

Ihr Code ist nicht threadsicher, und es ist wahrscheinlich zu viel, um es threadsicher zu machen, wenn der Rest des Codes single threaded ist. Vielleicht könntest du ein einfacheres Muster haben, das keine Threading-Funktion benötigt, wie zum Beispiel das Überprüfen, ob die Zeit von 5 Sekunden seit der Erstellung verstrichen ist, etwa so;

class Points 
{ 
public: 
    Points() {creationtime = time(0); /* do the rest of init */ } 
    ~Points(); 
    void method1() { test_and_reset(); /* do the rest of logic...*/ } 
    void method2() { test_and_reset(); /* do the rest of logic...*/ } 

     ... 
private: 
    time_t creationtime; 
    void test_and_reset() { 
      time_t now = time(0); 
      if (now > creationtime + 5) { /*reset*/ } 
    } 
}; 

Die obige einfache Implementierung auch bedeuten, dass Sie das Problem des Fadens ungültigen Speicherzugriff nicht haben, wenn das Objekt gelöscht wird, und Sie werden nicht haben, um herauszufinden, wie die Lauffläche zu töten.

+0

Es ist unmöglich festzustellen, ob der OP-Code Thread-sicher ist, da er nicht die Implementierung von' Point' zeigt - solange 'reset' und alle anderen Member-Funktionen von' Point' die notwendigen Mutexe oder atomaren Zugriffe enthalten, es könnte gut sein. –

+0

@ChrisDodd - wahr, aber nach den Kommentaren und Antworten zu urteilen, ist es nicht threadsicher – Soren

+0

Es ist nicht genau das, was ich gerade brauche, aber das ist eine gute Alternative für eine andere Klasse, die ich habe. Hat es irgendwelche Nachteile? – Anxious

5

Tun Sie es träge. Keine Notwendigkeit für Threads hier. Füge Getter hinzu (privat oder öffentlich) und greife nur über den Getter (und den entsprechenden Setter, wahrscheinlich) auf die Variable zu.

Im Getter überprüfen, ob die Rücksetzzeit aktiv ist (einfaches boolesches Flag, um den Overhead zu minimieren) und dann prüfen, ob genug Zeit vergangen ist, und dann den Wert zurücksetzen. Schließlich geben Sie den Wert wie in einem einfachen Getter zurück.


Oder, wenn Ihre Anwendung Ereignisschleife und ereignisgesteuerte Architektur (wahrscheinlich nicht, nur das Hinzufügen von hier der Vollständigkeit halber), Timer-Ereignis fügen Sie den Wert zurücksetzen. Immer noch keine Notwendigkeit für Fäden, um die Schläger zu komplizieren.

+0

Ja, ereignisgesteuert ist der richtige Weg. – ravenspoint