私は、マルチスレッドアプリケーションのどこからでもアクセスできる設定クラスをいくつか書いています。これらの設定は非常に頻繁に読み込まれるため(読み込みアクセスは高速にする必要があります)、あまり頻繁には書き込まれません。それはboost::atomic
のように見えるプリミティブデータ型のスレッドセーフな設定
は私が必要なものを提供していますので、私はこのような何かを思い付いた:
class UInt16Setting
{
private:
boost::atomic<uint16_t> _Value;
public:
uint16_t getValue() const { return _Value.load(boost::memory_order_relaxed); }
void setValue(uint16_t value) { _Value.store(value, boost::memory_order_relaxed); }
};
質問1:メモリ順序についてイムわかりません。私のアプリケーションでは、メモリの順序付けにはまったく関心がありません(私はそうですか?)。 getValue()
が常に破損していない値(古いものか新しいものか)を返すことを確認したいだけです。私のメモリの注文設定は正しいですか?
質問2:このアプローチでは、この種の同期にはboost::atomic
をお勧めしますか?または、より良い読み込みパフォーマンスを提供する他の構造体がありますか?
私のアプリケーションには、std::string
などのより複雑な設定タイプ、またはたとえばboost::asio::ip::tcp::endpoint
のリストが必要です。これらの設定値はすべて不変であると考えています。ですから、setValue()
を使用して値を設定すると、値自体(std::string
またはエンドポイント自体のリスト)はもう変更されません。だからもう一度、私は古い値か新しい値のどちらかを取得するが、何らかの破損した状態を取得しないようにしたい。
質問3:このアプローチはboost::atomic<std::string>
で動作しますか?そうでない場合は、何が選択肢ですか?
質問4:エンドポイントのリストのようなより複雑な設定タイプはどうですか? boost::atomic<boost::shared_ptr<std::vector<boost::asio::ip::tcp::endpoint>>>
のようなものをお勧めしますか?そうでない場合、何が良いでしょうか?
必要に応じて、複数のスレッドがこれらの設定を読み書きできるようにする必要性を再確認します。スレッドがgetBlahSetting()を呼び出して1つの結果を取得するのは意味があります。同じ関数で、後でもう一度呼び出すと、別の結果_が得られますか?私はあなたがハード同期ポイントで設計することをお勧めします。 – David
設定はユーザーのために変更する必要があります。ユーザーは複数のことを同時に行うことはほとんどありません。それでも、作家は二人以上ではいけません。したがって、私は頻繁に起こるので、何の同期もせずにconfigにアクセス(=読み込み)します。設定が変更されるというまれなケースのために、変更スレッドから詳細なコピーを作成します(これは再び同期化する必要はありません)。次に、誰もが使用する設定オブジェクトへのポインタへの 'seq_cst'ストアを1つだけ行います(これは高価ですが、まれにしか起こらないので余裕があります)。それは... – Damon
...他のスレッドが変更を受け取る前に瞬間が、それは通常問題ではありません。彼らは、結局、そうなるだろう。 *が問題*の場合は、ロック(おそらくリーダーライターロック)を使用する以外に選択肢はありません。その場合、パフォーマンスが悪くなります。あるいは、スレッドは、コンフィグステートのローカルコピーを保持する(または、再カウントされたコピーを共有する)ことができ、明確に定義された時刻に、タスクキューを介してコンフィグレーションを更新するように_explicitly_通知されます。それは可能なレースを排除します。 – Damon