Я бы не стал доверять этому коду. Я считаю, что ему не хватает надлежащих барьеров памяти для всей памяти, используемой разными потоками, за исключением двух подсчетов ссылок.
Для меня это выглядит как хорошее приложение для shared_mutex .
Edit:
20.7.2.2 [util.smartptr.shared] / p4 говорит:
В целях определения
наличие данных гонки, член
функции должны иметь доступ и изменять только
объекты shared_ptr и weak_ptr
сами по себе, а не объекты, которые они ссылаются
к.
Однако вместо использования shared_mutex другим вариантом может быть использование API в 20.7.2.5 атомном доступе shared_ptr [util.smartptr.shared.atomic]:
Параллельный доступ к shared_ptr
объект из нескольких потоков не
ввести гонку данных, если доступ
сделано исключительно через функции в
этот раздел и экземпляр
в качестве первого аргумента.
template<class T>
bool atomic_is_lock_free(const shared_ptr<T>* p);
template<class T>
shared_ptr<T> atomic_load(const shared_ptr<T>* p);
template<class T>
shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);
template<class T>
void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);
template<class T>
void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
template<class T>
shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);
template<class T>
shared_ptr<T>
atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
template<class T>
bool
atomic_compare_exchange_weak(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T>
bool
atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T>
bool
atomic_compare_exchange_weak_explicit(shared_ptr<T>* p, shared_ptr<T>* v,
shared_ptr<T> w, memory_order success,
memory_order failure);
template<class T>
bool
atomic_compare_exchange_strong_explicit(shared_ptr<T>* p, shared_ptr<T>* v,
shared_ptr<T> w, memory_order success,
memory_order failure);
shared_mutex будет легче понять правильно. Но API atomic shared_ptr может дать решение с более высокой производительностью.
Обновление:
Вот непроверенный код для решения shared_mutex (обратите внимание, что shared_mutex - это не std, а сторонняя библиотека):
struct STNGS
{
int i;
vector<double> v;
ting::shared_mutex m;
};
STNGS stngs;
int myFunction() //called by multiple threads
{
shared_lock<shared_mutex> _(stngs.m);
//do some stuff using stngs
return 0;
}
void updateSettings()
{
unique_lock<shared_mutex> _(stngs.m);
//fill stngs
}
void initialize()
{
//fill stngs
}
Вот непроверенный код, который использует атомарные функции загрузки / сохранения для shared_ptr:
struct STNGS
{
int i;
vector<double> v;
};
shared_ptr<STNGS> pStng;
int myFunction() //called by multiple threads
{
shared_ptr<STNGS> stngs = atomic_load(&pStng);
//do some stuff using *stngs
return 0;
}
void updateSettings()
{
shared_ptr<STNGS> newStng(new STNGS);
//fill *newStng
atomic_store(&pStng, newStng);
}
void initialize()
{
pStng.reset(new STNGS);
//fill *pStng
}