2016-05-12 78 views
2

根據https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250,GCC 4.9支持原子shared_ptr操作。GCC原子shared_ptr實現

使用GCC 4.9.2,我可以編譯使用原子shared_ptr的程序。 -mcx16標誌是必需的,因爲x86_64上的GCC實現顯然需要cmpxchg16b,這很有意義,因爲我假設shared_ptr上的原子操作需要原子上同時更新指針本身和引用計數。

但是,當我嘗試實際使用使用原子shared_ptr庫時,它的行爲與我預期的不同。所以,要麼我沒有正確使用它,要麼GCC的實現是有缺陷的。大多數時候,我會99%相信我只是做錯了,但由於這是一個相對較新的功能,並且由於行爲看起來很奇怪,所以我只有50%的人相信這是我的錯案件。

下面是一個簡單的程序,創建一個原子shared_ptr,然後執行一系列並行的讀取和對shared_ptr的寫道:

void test() 
{ 
     std::atomic<std::shared_ptr<int>> p(std::shared_ptr<int>(new int(10))); 

     std::cout << "Use count : " << p.load().use_count() << std::endl; 
     std::cout << "Initial value of p : " << *(p.load()) << std::endl; 

     std::vector<std::thread> threads; 
     const std::size_t num_threads = 8; 

     for (std::size_t i = 0; i != num_threads; ++i) 
     { 
       threads.emplace_back([&p, i](){ 

         std::shared_ptr<int> x = p.load(); 
         while (!p.compare_exchange_weak(
           x, 
           std::shared_ptr<int>(new int(i + 5)) 
         )) ; 
       }); 
     } 

     for (auto& t : threads) t.join(); 

     std::cout << "Use count : " << p.load().use_count() << std::endl; 
     std::cout << "Final value of p : " << *(p.load()) << std::endl; 
} 

當我編譯和運行,輸出爲:

~$ g++ test2.cpp -o test2 -std=c++11 -lpthread -mcx16 
~$ ./test2 
Use count : 1 
Initial value of p : 0 
Use count : 0 
Final value of p : 0 

但是這個輸出對我沒有意義。首先,在將原子shared_ptr初始化爲值10後,當我加載它並讀取初始值(在生成任何線程之前)時,我得到0。其次,在所有線程加入後,即使沒有線程可能將其設置爲0,值仍然爲0。最奇怪的是,在線程加入之後,shared_ptr的use_count()0!但原子shared_ptr對象仍在範圍內,因此使用計數應爲1

我敢肯定的GCC實現這裏有缺陷的,但根據我上面貼的鏈接,GCC 4.9擁有一個完整的原子shared_ptr實施,並...

~$ gcc --version 
~$ gcc (Debian 4.9.2-10) 4.9.2 

那麼...到底在這裏?我希望得到某種確認,要麼GCC 4.9.2的實現有缺陷或不完整,要麼我完全錯誤/困惑於如何使用原子shared_ptr

+0

我不確定,但看起來也許是後者?在std :: atomic頁面的參考頁面上,它沒有提及shared_ptr的專門化:http://en.cppreference.com/w/cpp/atomic/atomic。事實上,當我嘗試編譯你的代碼時,我觸發了一個靜態斷言:error:static斷言失敗:std :: atomic需要一個可以複製的類型。所以看起來這是不正確的用法,並且在較舊的編譯器版本中代碼沒有被強化,導致一些奇怪的行爲。 –

+0

這是一個針對* GCC 4.9的bug報告*,在5中修復。 –

+0

您是否在任何可能的情況下將原子與鎖定混淆? – user2296177

回答

6

「原子shared_ptr操作」是指shared_ptr的免費std::atomic_(store|load|exchange|compare_exchange_strong|compare_exchange_weak)(_explicit)?功能模板,記錄爲here。 GCC沒有他們,直到5(有趣的事實:其實施實際上使用的16個互斥引擎蓋下的全球陣列。)

實例化std::atomic超過std::shared_ptr結果不確定的行爲,爲std::atomic需要一個平凡複製的類型。

併發性TS有std::experimental::atomic_shared_ptr