LINUX.ORG.RU

SFML и менеджмент ресурсов

 ,


0

1

Пишу игру на плюсах и SFML и в процессе написания менеджера ресурсов столкнулся с проблемой. Подробное описание:

  • Есть шаблонный класс ResourceManager, хранит ресурсы в std::unordered_map в виде указателя (std::shared_ptr) и ключа.
  • Ресурсы хранятся внутри zip архива, поэтому я написал класс-наследник от sf::InputStream, благо все классы (Texture, Shader, SoundBuffer, Font, Music) имеют метод loadFromStream.

Проблема заключается в том, что sf::Music и sf::Font при этом не загружают ресурс в память полностью (как все остальное), а продолжают читать из стрима по частям.

Получается, экземляр стрима для них тоже нужно где-то хранить и уничтожать только после вызова деструктора объекта класса, читающего из этого стрима.

Как можно это все элегантно оформить? Пока на ум приходит только засунуть это все в std::pair.

★★★★★

Есть шаблонный класс ResourceManager, хранит ресурсы в std::unordered_map в виде указателя (std::shared_ptr)

А почему не std::uniqe_ptr ?

Проблема заключается в том, что sf::Music и sf::Font при этом не загружают ресурс в память полностью (как все остальное), а продолжают читать из стрима по частям.

Если ResourceManager делает то, чем называется, то он и должен хранить все стримы на ряду с этими вашими музыкальными шрифтами. Более того, только он и должен хранить сильную ссылку на каждый ресурс. А иначе, он не менеджер, а максимум лоадер. А то и вовсе регистри.

robus ★★★★★
()
Ответ на: комментарий от robus

Если ResourceManager делает то, чем называется, то он и должен хранить все стримы на ряду с этими вашими музыкальными шрифтами.

Угу, только где? Я подумывал хранить указатель на std::pair, но это не очень вариант, кмк.

Meyer ★★★★★
() автор топика
Последнее исправление: Meyer (всего исправлений: 2)
Ответ на: комментарий от Meyer

А сделать втупую

struct MusicFromZip {
  ZipStream st;
  Music mus;
};

std::unordered_map<Key, std::unique_ptr<MusicFromZip>> music;

не вариант?

Ну или

std::unordered_map<Key, std::pair<std::unique_ptr<Music>, std::unique_ptr<ZipStream>> > music;
robus ★★★★★
()
Последнее исправление: robus (всего исправлений: 1)

Можно как-то так:

struct FontStruct
{
    sf::InputStream stream;
    sf::Font font;
};

auto s = std::make_shared<FontStruct>();
resources.emplace_back(key, std::shared_ptr(s, &s.font));

См. aliasing constructor.

xaizek ★★★★★
()

поэтому я написал класс-наследник от sf::InputStream

И прибил гвоздями свое поделье, получив вендорлок.

Проблема заключается в том, что sf::Music и sf::Font при этом не загружают ресурс в память полностью (как все остальное), а продолжают читать из стрима по частям.

В этом нет никакой проблемы, это штатное поведение при работе с большими файлами, практически все читается поблочно или постранично или любыми другими мерами кусков.

В зависимости от какой стратегии ты будешь плясать, ты имеешь как минимум несколько вариантов, либо ты будешь получать файловый дескриптор, что ты получаешь сейчас с объектом наследника класса InputStream, который в итоге в виду своей виртуальности просто берет реализацию из FileInputStream вида m_file = std::fopen(filename.c_str(), "rb");, либо ты будешь получать указатель на память с содержимым твоего архива c размером и смещением, за тем как это устроено в реализацию MemoryInputStream, я бы выбрал второй вариант, так скорее всего будет быстрее, и думаю у тебя там не горы ресурсов чтобы нужны были варианты расположения вне памяти или с частичной выгрузкой в память с жд.

Получается, экземляр стрима для них тоже нужно где-то хранить и уничтожать

В этом и есть суть ресурсменеджера, только хранить ничего не надо, хотя можешь и хранить, никто не запрещает. По публичному интерфейсу, при вызове метода из этого публичного интерфейса ресурсменеджера создавать нужный экземпляр потока чтобы иметь возможность достать из архива нужный ресурс.

Короче говоря, ты сам придумываешь какие-то проблемы, проблем в общем-то нет, это у тебя просто паника в селе.

anonymous
()
Ответ на: комментарий от Meyer

так он тебе и предложил то, до чего ты сам дошел, последний пример и есть твоя пара, первый замена пары структурой, но все это лишь частный вариант реализации. Тебе надо продумать саму организацию ресурсменеджера и его внутреннее представление, я честно не вижу смысла вообще в сохранении рядом объекта или указателя или ссылки на поток, все что тебе надо для того чтобы такой поток получить это знать путь до файла с архивом, это инфа по сути константная, никто не тасует от запуска к запуску расположение архива с ресурсами в дереве файлов приложения.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.