Closed manabinohibi closed 2 years ago
すっかり忘れてましたが,std::atomicはコピー・ムーブコンストラクトが不可(=deleteで定義されている)でした^1.一方で,std::array
を使うときは中に入れる型T
がコピーコンストラクト可能であることが要求されます(fill
関数などの実行にインスタンスのコピーが必要なため).そのエラーメッセージはその点を警告している文章で,解決策としてはCの配列を使ってfill
関数の代わりにforループで初期化すればたぶん通ると思います.
どうもありがとうございます!無事にビルドできました.
とりあえず空いている記述子を取得するところまでかけた(つもり)なのですが,この場合どのようなテストをすべきなのでしょうか…?
Descriptor poolの機能としては,
という感じなのでテストとしては,
の3つくらいかなと思います.3のテストが割りと難しいのと,3の機能(descriptorの未割当状態への遷移)は別のクラスを用意してあげないと実現できない気がちょっとしています.
たぶん,以下のようなクラスElementHolder
を用意して,これをthread_local
で保持してあげる必要がある気がします.このクラスはデストラクタでis_reserved
をfalse
にするので,スレッド終了時に自動的に保持していたPoolElement
の所有フラグを消せます.
struct PoolElement {
public:
/// a flag for indicating this element is reserved.
std::atomic_bool is_reserved{false};
/// a target instance.
PMwCASDescriptor desc{};
}
class ElementHolder
{
public:
/*####################################################################################
* Public constructors and assignment operators
*##################################################################################*/
explicit ElementHolder(PoolElement *element) : element_{element} {}
ElementHolder(const ElementHolder &) = delete;
ElementHolder(ElementHolder &&) = delete;
auto operator=(const ElementHolder &) -> ElementHolder & = delete;
auto operator=(ElementHolder &&) -> ElementHolder & = delete;
/*####################################################################################
* Public destructors
*##################################################################################*/
~ElementHolder
{
element_->is_reserved.store(false, std::memory_order_relaxed);
}
/*####################################################################################
* Public getters
*##################################################################################*/
constexpr auto
GetHoldDescriptor() const //
-> PMwCASDescriptor *
{
return &(element_->desc);
}
private:
/*####################################################################################
* Internal member variables
*##################################################################################*/
/// an address of an actual element.
PoolElement *element_{};
}
たいへん詳しくありがとうございます! とりあえず簡単そうな1からやってみたいと思います.
@baycedar とりあえず以下の2つのテストを書いてみたので,少し見ていただきたいです.
テストこそ通りましたが,正しいテストがかけているのか,きちんとマルチスレッドで動いているのか等怪しさたくさんです.
よろしくお願いいたします.
と,思ったらPRでのテストは失敗してました. 明日確認します.
修正しました!
一旦レビューを外しておくので,テストを書いてチェックして欲しくなったら再度割当をお願いします.
@baycedar
の2つです.
結局std::future
らを使っていないので,なにか間違っている気がします.
あと少し困った(解決策についてなにも検討していない)のは,
Poolの容量分のスレッドでdescriptorを取得した(i.e., poolに空きなしの)状態でメインプロセスでdescriptorの取得を要求し,何も返ってこない(i.e., descriptorの重複割当がない)ことを確認.
しようと思ったときに,今の実装だと空きができるまでループするので,無限ループになってしまう気がします. 実際使う分には,いつかは空きができると思いますが…
ありがとうございます! 全体的にリファクタリングした後3つ目のテストを書いてみます!
一度クローズします…
記述子のプールを定義したクラスをなんとなくで書いてみました. が, 現状
[build] /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_algobase.h:760:11: error: object of type 'std::pair<std::atomic<bool>, dbgroup::atomic::pmwcas::PMwCASDescriptor>' cannot be assigned because its copy assignment operator is implicitly deleted [clang-diagnostic-error]
といったエラーが出ます. 調べてもよくわからずお手上げ状態なので,ご教授いただければ幸いです.なお,
pmwcas_descriptor.hpp
の場所はとりあえずそのままにしてます.ややこしくなりそうなので.