2016-05-12 12 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を使用するプログラムをコンパイルできます。 shared_ptrのアトミック操作では、ポインタ自体と参照カウントの両方を同時に更新する必要があると想定しているため、x86_64のGCC実装では明らかにcmpxchg16bが必要なため、-mcx16フラグが必要です。

しかし、私が実際にを使用しようとすると、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が返されます。第2に、すべてのスレッドが結合した後でも、値が0に設定されていても、値はまだ0です。そして、最も奇妙なことに、スレッドが参加した後、shared_ptrのuse_count()0です!しかし、原子番号shared_ptrオブジェクトは依然として有効範囲にあり、使用カウントは1でなければなりません。

私はGCCの実装は、ここで欠陥があるかなり確信しているが、私は上記の投稿のリンクによると、GCC 4.9は

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

そう...何を完了し、原子shared_ptr実装を持っている、と...正確にここにいるのですか?私はGCC 4.9.2の実装に欠陥があるか不完全であるという何らかの確認をしたいと思います。あるいは、原子の使用方法について完全に間違っている/混乱しています。shared_ptr

+0

わかりませんが、後者のようですか? std :: atomicページのリファレンスページでは、shared_ptrの特殊化については言及していません。http://en.cppreference.com/w/cpp/atomic/atomic確かに、あなたのコードをコンパイルしようとすると、私は静的なアサートを引き起こします:エラー:静的なアサーションが失敗しました:std :: atomicは、簡単にコピー可能な型を必要とします。だから、これは誤った使用法であり、古いコンパイラのバージョンではコードが強化されておらず、奇妙な動作につながっているようです。 –

+0

これは、GCC 4.9に対するバグ報告* 5で修正されました。 –

+0

万が一原子をロックフリーと混同していますか? – user2296177

答えて

6

「原子shared_ptr操作」とはのフリーstd::atomic_(store|load|exchange|compare_exchange_strong|compare_exchange_weak)(_explicit)?ファンクションテンプレートを指し、hereと記載されています。 GCCは5までそれらを持っていません(楽しい事実:。その実装は、実際にボンネットの下に16のミューテックスのグローバル配列を使用しています)

std::atomicは自明コピー可能タイプを必要とするため、未定義の動作でstd::atomicstd::shared_ptr以上の結果をインスタンス化。

並行性TSはstd::experimental::atomic_shared_ptrです。

関連する問題