odysset
@odysset
Программист, немного музыкант и bmx'ер

Как изменить значение у всех владельцев shared_ptr?

Пишу рендер, есть класс, который должен хранить шейдеры, что то вроде менеджера шейдеров. Эти шейдеры хранятся как
std::map<std::string, std::shared_ptr<BaseShader>> cache;

BaseShader - это абстрактный класс(имеются виртуальные методы).

Другие классы, хотят владеть шейдерами, и запрашивают их соответственно по имени. То есть у них у каждого хранится копия умного указателя. После изменения нужно шейдеры перезагрузить с диска. Соответственно, делается new и по имени записывается в cache, проблема в том, что клиенты не видят этого изменения. Как сделать так, чтобы не делался reset для умного указателя, а по тому же самому адресу, что он хранит, скопировался обновленный объект?
  • Вопрос задан
  • 301 просмотр
Пригласить эксперта
Ответы на вопрос 1
@menkar3
В принципе, для случая "shared_ptr, который может стать невалидным" и существует std::weak_ptr
Примитивное решение заключается в том, чтобы хранить std::shared_ptr только в кеше (который отвечает за владение объектом), а клиентам выдавать std::weak_ptr на него.
class Base
{
public:
    virtual ~Base() = default;
};

class Derived : public Base {};

int main()
{
    std::map<std::string, std::shared_ptr<Base>> cache;
    cache.insert(std::make_pair<std::string, std::shared_ptr<Base>>
        ("key", std::make_shared<Derived>()));
    std::weak_ptr<Base> ptr(cache["key"]);
    assert(cache["key"].get() == ptr.lock().get());
    // invalidation
    cache["key"].reset(new Derived);
    assert(ptr.expired());
    // check on every access
    if (ptr.expired())
        ptr = cache["key"];
    assert(cache["key"].get() == ptr.lock().get());
    return 0;
}

Проблемы:
  1. Маленькая проблема - перед каждым обращением к объекту нужно проверять expired() (ну, или проверять полученный после lock() shared_ptr на предмет пустоты)
  2. Большая проблема - многопоточность. Как между вызовами expired() и lock() так и при работе с shared_ptr, возвращенным lock() в любой момент может произойти инвалидация кеша. Простого решения сходу не вижу, выбор способа синхронизации остается за вами
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
18 апр. 2024, в 21:56
2000 руб./за проект
18 апр. 2024, в 21:00
150 руб./за проект