2012-12-19 12 views
8

Sto implementando un meccanismo di puntatore/indicatore debole utilizzando std::atomic s per il contatore di riferimento (come this). Per la conversione di un puntatore debole per uno forte ho bisogno di atomicamenteC++ incremento std :: atomic_int se diverso da zero

  • controllo se il contatore di riferimento forte è diverso da zero
  • in caso affermativo, incrementarlo
  • so se qualcosa è cambiato.

C'è un modo per farlo utilizzando std::atomic_int? Penso che sia possibile utilizzare uno degli compare_exchange, ma non riesco a capirlo.

+3

'std :: shared_ptr' utilizza i contatori di riferimento atomiche, si sa. Puoi sempre controllare la fonte. – Pubby

+1

cosa significa la parte "sapere se qualcosa è cambiato"? – inf

+0

Se era diverso da zero prima == se è stato incrementato. –

risposta

3

data la definizione 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 conterrà il valore precedente. Si noti che compare_exchange_weak verrà aggiornato in caso di errore.

+0

non dovrebbe ref_count.load() essere nel ciclo for? Potrei sbagliarmi, dal momento che ho davvero difficoltà a pensare in modo atomico. :) – NoSenseEtAl

+2

@NoSenseEtAl 'compare_exchange_weak' prende' previous' per riferimento e lo aggiorna, quindi non c'è bisogno di fare un altro 'ref_count.load()'. – ymett

1

Questo dovrebbe farlo:

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

Sembra inutile andare avanti con il confronto_exchange se hai già deciso di non modificare il valore. – ymett

+0

@ymett Sono d'accordo con te, ma sono in qualche modo insicuro, dato che altrimenti deciderò se incrementare o meno i due diversi stati di 'i'. – inf

+0

Devi solo decidere una volta. Una volta presa la decisione (in 'if') hai finito. – ymett