最近私は狡猾な計画(tm:P)を考えました 私のプログラムで設定の構造を更新しなければなりません。設定構造体は複数の関数によって使用され、それらの関数はすべて複数のスレッドによって呼び出されます。 古い設定の構造体を解放するのがいつ安全であるかを知るために、参照カウンタが必要です。 これは正しい方法ですか? コードを慎重に読んでいない場合は、共有ポインターに関してはこのような悪用を行うと間違いを犯すのは簡単です(信頼してください)。 編集:重要な部分については言及しません。私はこの実装がrefSetを0に落とさないようにしていると思います。なぜなら、私はupdateSettings()で初期化し、再度呼び出されるまで落とされないからです(そして、myFucntionはメモリの2つの設定のうちのもう1つを使います)。(Ab)shared_ptrを参照カウンタとして使用
#include<memory>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
struct STNGS
{
int i;
vector<double> v;
};
static int CUR_STNG=0;
shared_ptr<STNGS> stngsArray[2];
int myFunction() //called by multiple threads
{
shared_ptr<STNGS> pStngs=stngsArray[CUR_STNG];
STNGS& stngs=*pStngs;
//do some stuff using stngs
}
void updateSettings()
{
auto newIndex=(CUR_STNG+1)%2;
stngsArray[newIndex].reset(new STNGS);
CUR_STNG=newIndex;
}
void initialize()
{
auto newIndex=CUR_STNG;
stngsArray[newIndex].reset(new STNGS);
CUR_STNG=newIndex;
}
int main()
{
initialize();
//launch bunch of threads that are calling myFunction
while(true)
{
//call updateSettings every 15 seconds
}
}
編集:私は、コードを更新し、コメントからのフィードバックを使用して:
#include<memory>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
static const int N_STNG_SP=4;
static int CUR_STNG=0;
struct STNGS
{
int i;
vector<double> v;
STNGS()
{
for (int i=0;i<10;++i)
v.push_back(42);
}
};
shared_ptr<STNGS> stngs[N_STNG_SP];
int myFunction() //called by multiple threads
{
shared_ptr<STNGS> pStngs=stngs[CUR_STNG];
STNGS& stngs=*pStngs;
//do some stuff using stngs
}
void updateSettings()
{
auto pStng=new STNGS;
//fill *pStng
int newVer=(CUR_STNG+1)%N_STNG_SP;
stngs[newVer].reset(pStng);
CUR_STNG=newVer;
}
void initialize()
{
auto pStng=new STNGS;
//fill *pStng
int newVer=(CUR_STNG+1)%N_STNG_SP;
stngs[newVer].reset(pStng);
CUR_STNG=newVer;
}
int main()
{
initialize();
//launch bunch of threads that are calling myFunction
while(true)
{
//call updateSettings every 15 seconds
updateSettings();
}
}
ああ、もう一度答えは消えました...しかし、もう一度聞いてください。なぜatomic_loadが必要ですか?私は、アトミックストアが必要であることを理解していますが、atomic_loadはatomic_loadを保証していませんか?つまり、変数はロックされていますか?そして、私は他の機能は設定を読み込むように言った。それが愚かなQなら私にいくつかのリンクを教えてください。愚かなQといえば、生のポインタがコンストラクタの引数として使用されている場合、共有されたptrが値をコピーしないことがわかりました。それは新しい(:P)私にはまだ、私はまだwheatherについての議論を持っていないこれは、標準によって良い考えであるかどうかです。 – NoSenseEtAl
アトミック命令は、指示された操作(実際にはどのようにブーストの実装がそれを行うか)を包み込んだミューテックス以上のものであると考えてください。各shared_ptrは、参照カウントを更新するだけでなく、一貫して読み書きが必要な2つのポインタで構成されています。 shared_ptrを設定しているスレッドが、同じshared_ptrを読み込む前に設定されているポインタのうちの1つだけを取得すると、問題が発生します。したがって、リーダーとライターの両方が互いに同期しなければなりません。 atomic_loadは、読み込み中にライターが設定しないように、フードの下にあるmutexをロックします。 –
OK、わかりました。あなたは私の "共有ポインタの円形配列"解決策にいくつかの問題を見ますか?私はそれが単に変更されている1つのインデックスであり、それは "かなり原子的"でなければならないので、どのように失敗するかはわかりません。 Ofc関数は長い時間がかかる可能性があり、まだ使用されている間に円形配列(キュー)のメンバーを更新し始めますが、キューのサイズを大きくするとうまくいくはずです。 – NoSenseEtAl