2013-07-08 6 views
9

Ich versuche Objekte mit std::shared_ptr und std::weak_ptr zu jonglieren. Das Szenario ist ungefähr so:shared_ptr & weak_ptr Konvertierungen

Ich habe Objekte der Klasse channel, die von einer abstrakten Klasse abstract::channel (mit reinen virtuellen Funktionen) abgeleitet ist. Ich habe einen Container channelContainer (std::vector) mit geteilten Zeigern (std::shared_ptr) zu channel Objekte.

Jetzt habe ich eine deque (std::deque) mit schwachen Zeigern (std::weak_ptr) zu jedem Objekt in der channelContainer. Benennen Sie diese Deque freeChannelQueue.

kann also sagen: ‚Wie eine Referenz auf ein Objekt auf einen schwachen Zeiger konvertieren‘

std::vector<std::shared_ptr<abstract::channel> > channelContainer; 
std::deque<std::weak_ptr<abstract::channel > > freeChannelQueue; 

//Assuming that both the containers are filled appropriately How do I go about implementeing the below functions? 

abstract::channel& get_free_channel() { 
    //This should return a free channel object from 'freeChannelQueue' and pop the queue. 
} 

bool release_channel(abstract::channel& ch) { 
//This should convert 'ch' to a std::weak_ptr (or std::shared_ptr) and push it to 'freeChannelQueue' 
} 

Ich interessiere mich besonders für die

+0

AFAIK Sie können ein 'weak_ptr' nicht direkt von einem Objekt oder einer Objektreferenz initialisieren/konstruieren, da das Objekt, auf das es verweist, im Besitz von' shared_ptr' sein muss. Daher benötigen Sie für die Konstruktion ein 'shared_ptr' oder' weak_ptr'. – Piotr99

Antwort

1

Ist dies Ihr Design? Es gibt jedoch einige schwerwiegende Probleme mit der Kanallebensdauer. Zum Beispiel - wenn der Code get_free_channel() aufruft, gibt Ihre Deklaration ihnen einen Verweis auf ein Objekt zurück, aber sie haben keine Möglichkeit zu garantieren, dass ihre Lebensdauer ihre Verwendung umfasst. Die könnte egal je nachdem, was der Client-Code ist, dass Sie die Funktion aus anrufen, aber Sie wollen wahrscheinlich ein shared_ptr zurückzukehren, wie in:

std::shared_ptr<abstract::channel> get_free_channel() 
{ 
    // return free channel from 'freeChannelQueue' and pop the queue 

    // take a scoped lock on the free queue if necessary 

    while (!freeChannelQueue.empty()) 
    { 
     auto p_channel = freeChannelQueue.back(); 
     freeChannelQueue.pop_back(); 
     std::shared_ptr<abstract::channel> p = p_channel.lock(); 
     if (p) return p; 
    } 

    // freeChannelQueue empty... throw or return nullptr etc.. 
} 

In Bezug auf „Freigabe“ ...

bool release_channel(abstract::channel& ch) { 
//This should convert 'ch' to a std::weak_ptr (or std::shared_ptr) and push it to 'freeChannelQueue' 
} 

Dies ist nur möglich, wenn Sie die channelContainer suchen, um das Objekt zu finden, dann erhalten Sie Ihre schwache_ptr oder shared_ptr von dort. Nochmals - Sie sollten wahrscheinlich den Prototyp so ändern, dass er direkt eine oder weak_ptr empfängt, die freie Warteschlange sperrt und dann den Smartpointer anstößt ...

Alles in allem ist es schwer, Ihnen nützliche Ratschläge zu geben, ohne den Weg zu verstehen Ihre Kanallebensdauer wird verwaltet und verschiedene Threads versuchen möglicherweise, die Objekte und Warteschlangen zu verwenden. Ich hoffe, das obige hilft ein wenig, wenn auch nur um eine genauere Frage zu stellen.

+0

Danke für die Antwort, denn jetzt habe ich die Antwort auf mein Problem. Noch unsicher über das Design, wird die Frage aktualisiert, wenn ich das aktuelle Design für meine Bedürfnisse ungeeignet finde! – user2559933

+0

@ user2559933: sicher ... viel Glück damit. –

+0

Sie können einen unformatierten Zeiger oder eine Referenz in shared_ptr konvertieren, wenn Sie std :: enable_shared_from_this als Basisklasse hinzufügen. Sie können der abstrakten Klasse eine Memberfunktion geben, die ein shared_ptr an sich selbst zurückgibt. – Dennis

3

Sie können nicht

wandeln einen Verweis auf ein Objekt auf einen schwachen Zeiger

Sie einen schwachen Zeiger von einem gemeinsamen Zeiger machen kann, nur Zuordnung mit = z.B.

std::shared_ptr<abstract::channel> get_free_channel(); 

dann

bool release_channel(std::shared_ptr<abstract::channel> ch) 
{ 
    std::weak_ptr<abstract::channel> weak_ch = ch; 
    //... 
} 

für Lebensdauern Watch out - wird die Shared_ptr gehen, bevor die schwachen Zeiger, die auf sie zeigen?

0

Ich verstehe Ihre Frage so: Sie haben einen Container, um alle Ihre Kanalobjekte zu halten, und Sie haben einen zweiten Container, um eine Reihenfolge der Kanäle zu verwalten, die von Ihrer Anwendung verwendet werden können. Sie möchten dann, dass eine Schnittstelle einen Verweis auf den nächsten freien Kanal für Ihren Client zurückgibt, und wenn der Client fertig ist, gibt er den Kanal zurück an den Container.

Um einen Verweis auf einen Kanal zu erhalten, können Sie lock verwenden, um eine shared_ptr von Ihrem weak_ptr zu erstellen und dann deneferenzieren (löschen Sie nicht einfach das zugrunde liegende Objekt!). Ich sehe jedoch keinen vernünftigen Weg, um in die andere Richtung zu gehen. Sie müssten Ihren Kanalcontainer nach dem übereinstimmenden Objekt durchsuchen und einen schwachen Zeiger aus dem passenden shared_ptr erneut erstellen.

Ich würde nicht schwacher_ptr und Referenzen überhaupt verwenden, bleiben Sie einfach mit shared_ptr. Da Sie eine deque verwenden, um zu pflegen, welche Kanäle verfügbar sind, können Sie stattdessen die verfügbaren shared_ptrs dort beibehalten. Wenn Sie froh sind, dass Ihr Client die Kanäle immer freigibt, wenn Sie fertig sind, brauchen Sie vielleicht keinen Container für alle Objekte, nur die Deque für die freien Kanäle - hängt von Ihrem Gesamtdesign ab.

Wie andere bereits gesagt haben, müssen Sie die Lebensdauer Ihrer Kanalobjekte und deren Verwendung durch den Client berücksichtigen.