2010-03-08 15 views
13

Ze względów historycznych muszę używać natrętnych wskaźników, ponieważ potrzebuję możliwości zamiany surowych wskaźników na inteligentne wskaźniki.Czy jest doładowanie :: weak_intrusive_pointer?

Zauważyłem jednak, że nie ma słabego, natrętnego wskaźnika dla wzmocnienia. Znalazłem o tym rozmowę na liście wątków doładowania, jednak nic konkretnego.

Czy ktoś wie o implementacji wątku bezpieczne słabe intruzyjnych wskaźnik?

Dzięki Rich

Odpowiedz

10

To nie ma żadnego sensu.

Aby rozwinąć: weak_ptr wskazuje na to samo wystąpienie obiektu counter, który wykonuje shared_ptr. Gdy shared_ptr wykracza poza zakres, instancja modelu counter pozostaje (z liczbą skutecznie przy 0), co pozwala instancjom weak_ptr na sprawdzenie, czy skutecznie wskazują na uwolniony obiekt.

Przy liczeniu introspekcyjnym licznik jest zintegrowany z obiektem. Kiedy liczba osiągnie 0, obiekt jest zwykle albo poddawany recyklingowi, albo kasowany ... ale punktem jest, że licznik nie jest już dostępny. Uzasadnieniem jest to, że pozwala to na bardziej wydajne przechowywanie (1 pojedynczy fragment) i większą szybkość (lokalizacja pamięci podręcznej).

Jeśli potrzebujesz słabego liczenia referencji i nie zależy Ci na korzyściach z inwazyjnego liczenia, możesz użyć kombinacji shared_ptr i weak_ptr.

Pomysł polega na odłączeniu licznika od obiektów.

class Counted 
{ 
    // bla 
private: 
    boost::shared_ptr<int> mCounter; 
}; 

Teraz można powrócić słabe uchwyty:

class WeakHandle 
{ 
public: 
    explicit WeakHandle(Counted& c): mCounter(c.mCounter), mObject(&c) {} 

    bool expired() const { return mCounter.expired(); } 

private: 
    boost::weak_ptr<int> mCounter; 
    Counted* mObject; 
}; 

Tutaj deassociate żywotność licznika z życia obiektu, tak, że będzie przetrwać zniszczenie przedmiotu ... częściowo. W ten sposób efektywne staje się weak_ptr.

I oczywiście, używając shared_ptr i weak_ptr to jest bezpieczeństwo wątków;)

+0

Mój pomysł polega na osadzeniu współdzielonego obiektu używanego przez współdzielony ptr i słaby ptr wewnątrz obiektu hosta i intrusive_weak_ptr (jeśli istniał) użyłby go w taki sam sposób, jak robi to weak_ptr. Nadal potrzebuję funkcji usuwania obiektu, gdy nie ma już żadnych odniesień. Ponadto muszę wziąć słabe referencje. – Rich

+0

Myślę, że nie zrozumiałeś mojego punktu widzenia: dokładnie to proponuję. Obiekt "Counted" jest "inwazyjnie" zliczany, właśnie zmieniłem licznik ze zwykłej liczby całkowitej na wskaźnik na liczbę całkowitą. Jeśli chodzi o twoją 'intrusive_weak_ptr', to właśnie nazwałem' WeakHandle'. –

+0

Ah Myślę, że jestem z tobą. Więc użyłbym inwazyjnego wskaźnika jako normalnego, jednak gdy wywoływana jest metoda intrusive_ptr_add_ref, odwołuję się do int ze współużytkowanego wskaźnika jako liczby. Kiedy trafi zero, obiekt zostaje zwolniony, jednak wszelkie słabe referencje utrzymują wskaźnik na int. Czy to jest poprawne? – Rich

4

Bieżąca realizacja natrętne wskaźnik korzysta licznik odniesienia. Usunięcie obiektu powoduje również usunięcie licznika, więc weak_intrusive_pointer nigdy nie będzie wiedział, że obiekt został usunięty.

Jeśli chcesz uzyskać weak_ptr z this, prawdopodobnie przeszukujesz boost::enable_shared_from_this<T>.

3

I naprawdę nie jak jeden z poprzednich odpowiedzi tak:

Nie, nie wiem od implementacji, ale myślę, że to możliwe. Standardowa implementacja shared_ptr zawiera dwie liczniki referencji, jedną dla "silnego" i jedną dla "słabych" referencji, a także wskaźnik do referencji. W implementacji intrusive_ptr silna liczba musi być częścią obiektu, ale słabe nie może być. Wygląda na to, że możesz stworzyć "słabe" intrusive_ptr.

Definiowanie słaby wskaźnik pomocnika:

template<class X> 
class intrusive_ptr_weak_helper { 
    long weak_ref_count; 
    X *target_instance; 
}; 

następnie nagrać że do obiektu obok liczby odniesienia:

struct X { 
    ... 
    intrusive_ptr_weak_helper *ref_weak_helper; 
    ... 
    long ref_count; 
    ... 
}; 

przy konstruowaniu X:

ref_count = 0; 
ref_weak_helper = NULL; 

W "mocny" wskaźnik, intrusive_strong_ptr, jest identyczny z intrusive_ptr, dopóki nie nastąpi usunięcie. Gdy silny Ilość ref wychodzi na zero (zanim nastąpi skreślenie):

if (ref_weak_helper != NULL) { 
    if (ref_weak_helper->weak_ref_count == 0) 
     delete ref_weak_helper; 
    else 
     ref_weak_helper->target_instance = NULL; 
} 

W „słaby” wersja, intrusive_weak_ptr, zapisuje wskaźnik do słabego pomocnika, manipulując tego licznika odwołań, a dostęp do obiektu docelowego poprzez target_instance wskaźnik. Gdy weak_ref_count zmniejsza się do zera, status parametru target_instance określa, czy helper został usunięty, czy nie.

Brakuje wielu szczegółów (na przykład dotyczy współbieżności), ale jest to mieszanie shared_ptr i intrusive_ptr. Utrzymuje podstawowe zalety intrusive_ptr (optymalizacja pamięci podręcznej, ponowne użycie intruzyjnego (silnego) licznika referencji, silne i słabe wskaźniki stand-in są wielkościami wskaźnika), przy jednoczesnym dodaniu dodatkowej pracy głównie w słabej ścieżce referencyjnej.