Я реализовал простой ResourceManager — все было хорошо, пока я не попытался реализовать его деструктор для (экстренной) очистки (например, в случае фатального исключения). Я не смог найти ни одного способа сделать это:
template<typename T>
class ResourceManager
{
public:
std::unordered_map<std::string, std::weak_ptr<T> > resource_map;
std::shared_ptr<T> getResource(std::string name)
{
std::shared_ptr<T> res = resource_map[name].lock();
if(!res)
{
res = std::shared_ptr<T>(new T(this, name));
resource_map[name] = res;
}
return std::move(res);
}
void Release(std::string name)
{
resource_map.erase(name);
};
~ResourceManager(void) { /* ???? */}
};
class Texture
{
private:
ResourceManager<Texture> * manager_;
std::string name_;
public:
Texture(ResourceManager<Texture> * manager, std::string& name)
: manager_(manager), name_(name) { }
~Texture(void){
manager_->Release(name_);
}
};
Очевидно, что мне приходится перебирать все активные ресурсы … но как я могу их освободить, если ResourceManager не является технически (единственным) владельцем ресурсов? Это может быть недостатком дизайна, если это так, пожалуйста, предложите альтернативу.
РЕДАКТИРОВАТЬ: в ответ на ответы для определения «менеджера ресурсов» я представляю себе авторитетный кеш — хранилище для ссылок на ресурсы, которые могут искать ресурсы (= не дублировать) и управлять их состоянием в памяти (в памяти, только для описания (= путь + тип) ) и освобожден), все вышеизложенное максимально автоматизировано. (должны быть отдельные ResourceLoaders, но это не сильно изменится для этого вопроса)
Итак, ваш код не делает много для освещения вашего общего дизайна, здесь, но…
При реализации ваш менеджер ресурсов, кажется, имеет только слабые указатели на ресурсы. Это указывает на то, что он не отвечает за время жизни самих реальных ресурсов и, следовательно, не должен очищать эти ресурсы в своем деструкторе.
если ты хочу Менеджер ресурсов, чтобы быть официальным владельцем данных ресурса, вы захотите изменить его дизайн / реализацию. Например, вы можете иметь его в магазине shared_ptr
S к самим ресурсам, и только потерять сознание weak_ptr
с клиентами. Или просто хранить unique_ptr
s и раздать голые указатели на код клиента.
Но, как написано, вам не нужно (и не можете) ничего сделать, чтобы очистить ресурсы в ~ResourceManager()
,
Чтобы предложить альтернативы, нам нужно знать, для чего предназначается ваш менеджер ресурсов.
Помни что shared_ptr
s в C ++ не работают как GC. То есть если вы уничтожите / сбросить последний shared_ptr
объекту этот объект будет удален немедленно, даже если есть weak_ptr
с этим.
Таким образом, подходы (1) и (2) могут иметь много смысла. (3) однако, то, что у вас есть в настоящее время, имеет смысл только очень редко (если вообще имеет смысл).