2012-12-19 124 views
8

我實施使用std::atomic S爲基準計數器(如this)的指針/弱指針機制。對於一個弱指針轉換成一個強大的一個,我需要原子C++增量的std :: atomic_int如果非零

  • 檢查,如果強引用計數器是非零
  • 如果是這樣,增加它
  • 知道的東西是否已經改變。

有沒有辦法做到這一點使用std::atomic_int?我認爲它應該可以使用compare_exchange之一,但我無法弄清楚。

+3

'的std :: shared_ptr'使用原子引用計數器,你知道的。你可以隨時查看源代碼。 – Pubby

+1

「知道是否有變化」部分是什麼意思? – inf

+0

==它是否增加之前是否爲非零。 –

回答

3

給出的定義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將保持前值。請注意,如果失敗,compare_exchange_weak將更新以前的內容。

+0

shouldnt ref_count.load()是否在for循環中?我可能是錯的,因爲我真的很難用原子操作來思考。 :) – NoSenseEtAl

+2

@NoSenseEtAl'compare_exchange_weak'需要'引用和更新它previous',所以沒有必要做另一個'ref_count.load()'。 – ymett

1

這應做到:

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

如果您已經決定不更改該值,似乎沒有必要繼續使用compare_exchange。 – ymett

+0

@ymett我同意你的意見,但我不確定,因爲我會根據我的決定,決定是否增加或不增加'i'的兩個不同狀態。 – inf

+0

您只需要決定一次。一旦你做出了決定(在'if'中),你就完成了。 – ymett