2012-12-19 7 views
8

Wdrażam mechanizm wskaźnika/wskaźnika słabego przy użyciu std::atomic s dla licznika odwołań (np. this). Do konwersji słaby wskaźnik do silnego jednym muszę atomowoC++ inkrementacja std :: atomic_int if niezerowa

  • sprawdzić, czy licznik silne odniesienia jest niezerowe
  • jeśli tak, to przyrost
  • wiem, czy coś się zmieniło.

Czy istnieje sposób, aby to zrobić za pomocą std::atomic_int? Myślę, że to musi być możliwe przy użyciu jednego z compare_exchange, ale nie mogę tego rozgryźć.

+3

'std :: shared_ptr' wykorzystuje atomowe liczniki referencyjnych, wiesz. Zawsze możesz sprawdzić źródło. – Pubby

+1

co znaczy "wiedzieć, czy coś się zmieniło"? – inf

+0

Czy wartość różna od zera przed == czy była zwiększana. –

Odpowiedz

3

Biorąc pod uwagę definicję std::atomic<int> ref_count;

int previous = ref_count.load(); 
for (;;) 
{ 
    if (previous == 0) 
     break; 
    if (ref_count.compare_exchange_weak(previous, previous + 1)) 
     break; 
} 

previous odbędzie poprzednią wartość. Pamiętaj, że compare_exchange_weak zaktualizuje poprzednie, jeśli się nie powiedzie.

+0

shouldnt ref_count.load() być w pętli for? Mogę się mylić, ponieważ naprawdę ciężko myślę w sposób optyki atomowej. :) – NoSenseEtAl

+2

@NoSenseEtAl 'compare_exchange_weak' pobiera' previous' przez odniesienie i aktualizuje go, więc nie ma potrzeby robienia kolejnego 'ref_count.load()'. – ymett

1

ten powinien zrobić:

bool increment_if_non_zero(std::atomic<int>& i) { 
    int expected = i.load(); 
    int to_be_loaded = expected; 

    do { 
     if(expected == 0) { 
      to_be_loaded = expected; 
     } 
     else { 
      to_be_loaded = expected + 1; 
     } 
    } while(!i.compare_exchange_weak(expected, to_be_loaded)); 

    return expected; 
} 
+0

Wydaje się niepotrzebne, aby kontynuować porównywanie, jeśli już zdecydowałeś się nie zmieniać wartości. – ymett

+0

@ymett Zgadzam się z tobą, ale jestem niejasny, ponieważ chciałbym oprzeć moją decyzję, czy zwiększać, czy nie, dwa różne stany "i". – inf

+0

Wystarczy raz zdecydować. Po podjęciu decyzji (w "Jeśli") jesteś gotowy. – ymett