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
わかりませんが、後者のようですか? std :: atomicページのリファレンスページでは、shared_ptrの特殊化については言及していません。http://en.cppreference.com/w/cpp/atomic/atomic確かに、あなたのコードをコンパイルしようとすると、私は静的なアサートを引き起こします:エラー:静的なアサーションが失敗しました:std :: atomicは、簡単にコピー可能な型を必要とします。だから、これは誤った使用法であり、古いコンパイラのバージョンではコードが強化されておらず、奇妙な動作につながっているようです。 –
これは、GCC 4.9に対するバグ報告* 5で修正されました。 –
万が一原子をロックフリーと混同していますか? – user2296177