2012-04-11 2 views
2

Bin in der Lage, Zeiger in einem Vektor zu halten, nur damit ich sie verwenden kann, um den Speicher im dtor freizugeben.Zuweisung des Callback-Listener-Objekts in Boost Bind, wenn Notifier/Signal den Gültigkeitsbereich verlässt

Ich habe ein Objekt auf Callbacks (Slots) von den Boost-Signalen zu hören. Diese Objekte mussten einen größeren Umfang als die Methode, in der es erstellt wird, wie es die Boost-Signale hören sollte viel später hören als wo es ist erstellt.So musste ich den Speicher in Heap reservieren und abonniert sofort Boost-Signale mit dieser Instanz.

Nun sollten diese Objekte aus dem Speicher freigegeben werden, wenn die Klasse, um die Signale halten, sind destroyed.Now, was meine Optionen sind,

  • Hat steigern ausplanen alle diese Objekte, wenn Boost-Signal außerhalb des Gültigkeitsbereichs und alle hören geht boost: bind Objekte werden zerstört ??

  • Wird geteilter Zeiger oder intelligenter Zeiger mir dabei helfen?

  • Muss ich einen Vektor aller dieser Zeiger im Signalling Service haben, um in seinem Destruktor die Zuordnung aufzuheben? Gibt es einen besseren Weg?

    void methodA(){ 
    
    CallbackHandler* cbHandler=new CallbackHandler(..); //Allocating in heap as we want to receive boost signals on 
                     //this instance even after this method exits 
    signalingService.subscribeToCertainSignals(signalType,boost::bind(&CallbackHandler::boostSlotListener,cbHandler,_1)); 
    } 
    
    
    // Boost Signal -SignalingService 
    boost::signal<void (const std::string &msg)> signal1; 
    boost::signal<void (const std::string &msg)> signal2; 
    
    void subscribeToCertainSignals(const std::string& signalType,boost::function<void (const std::string& str)> bindObject){ 
         this->signal1.connect(bindObject); 
         this->signal2.connect(bindObject); 
    
    } 
    void sendSignals(A a){ 
        if(check){ 
         this->signal1("somestring1"); 
         }else{ 
         this->signal1("somestring1"); 
         } 
    

    };

+0

Ich bin ein Java-Entwickler nur C++ Programmierung gestartet. Habe angefangen, ein paar gute C++ Bücher zu lesen, aber immer noch versucht, meinen Weg zu finden. Bitte beraten Sie, wenn etwas grundsätzlich falsch ist. – Yeshvanthni

Antwort

1

Eine Möglichkeit, dies tun könnte, würde shared_ptr s an alle Zuhörer in das Objekt hält die Signale und weak_ptr s an die Zuhörer außerhalb zu speichern sein. Wenn das Objekt, das die Signale enthält, zerstört wird, wird der Referenzzähler in jedem der shared_ptr s auf 0 gesetzt und die Listener, auf die gezeigt wird, werden gelöscht. Wenn Sie nun versuchen, die weak_ptr s zu sperren, um von außerhalb des Objekts, das die Signale enthält, auf die Listener zuzugreifen, schlägt die Sperrung fehl, da die Pointees gelöscht wurden. Dies ist leicht zu erkennen, da lock null shared_ptr zurückgibt.

Hier ist ein konkretes Beispiel für Sie (nicht mit Boost.Signals leider nur den Punkt zu veranschaulichen):

#include <iostream> 
#include <memory> 
#include <vector> 

class Listener 
{ 
public: 
    virtual ~Listener() {} 
    virtual void signal() = 0; 
}; 

class Subject 
{ 
private: 
    std::vector<std::shared_ptr<Listener> > m_listeners; 
public: 
    void add_listener(const std::shared_ptr<Listener>& listener) 
    { 
     m_listeners.push_back(listener); 
    } 

    void signal_all() 
    { 
     // Note that you could use "auto it = ..." here in C++11. 
     for(std::vector<std::shared_ptr<Listener> >::iterator it=m_listeners.begin(), iend=m_listeners.end(); it!=iend; ++it) 
     { 
      (*it)->signal(); 
     } 
    } 
}; 

class MyListener : public Listener 
{ 
    void signal() 
    { 
     std::cout << "Signalled!\n"; 
    } 
}; 

int main() 
{ 
    std::vector<std::weak_ptr<Listener> > listeners; 

    { 
     Subject s; 

     std::shared_ptr<Listener> listener(new MyListener); 
     s.add_listener(listener); 
     listeners.push_back(listener); 
     listener.reset(); 

     s.signal_all(); 

     // Locking the listener yields the listener here. 
     std::cout << listeners[0].lock() << '\n'; 
    } 

    // Locking the listener now yields null because s no longer exists. 
    std::cout << listeners[0].lock() << '\n'; 

    return 0; 
} 

Diese Ausgänge:

Signalled! 
<some valid non-null address> 
00000000 
+0

Danke für die Antwort !! Ich dachte auf ähnliche Weise.So würde ich einen Vektor von Zeigern auf Listener haben, die am Destruktor verwendet werden können, um shared_ptr freizugeben oder zu erlauben, seine Arbeit zu machen. Aber ich verstehe den Vektor von weak_ptr nicht. – Yeshvanthni

+0

Das sind nur die Zuhörer außerhalb des Themas - sie müssen nicht in einem Vektor gespeichert werden. Beachten Sie, dass das Subjekt keinen expliziten Destruktor benötigt - wenn seine Instanz den Geltungsbereich verlässt und zerstört wird, tut dies auch der interne Vektor und alle darin enthaltenen shared_ptrs. –

+0

Wenn es sich um weak_ptr handelt, mit dem Sie nicht vertraut sind, siehe hier: http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/weak_ptr.htm –

0

ich besser denken boost scoped_connection zu verwenden. Dieses Objekt wurde für Dinge entworfen, nach denen Sie suchen.

Sie können z. B. bereichsspezifische Verbindungen in einer Liste speichern, und wenn der Besitzer der Liste stirbt, ruft die Liste Destruktoren der Bereichsverbindung auf und einer löst automatisch Ihr Objekt vom Signalsteckplatz.

lesen Details hier:

http://www.boost.org/doc/libs/1_46_1/doc/html/boost/signals2/scoped_connection.html

Verwandte Themen