Russian Qt Forum
Ноябрь 23, 2024, 16:13 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 5   Вниз
  Печать  
Автор Тема: Пример проектирования  (Прочитано 25250 раз)
ufna
Гость
« Ответ #15 : Декабрь 16, 2010, 21:13 »

Смотри gamedev.ru и dtf.ru - уже на сотни раз перетерто с различными вариациями Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Декабрь 16, 2010, 21:54 »

Набросал немного кода, посмотри (компилябельно):
Код
C++ (Qt)
MapCache::iterator it;
for( it = m_cache.begin(); it != m_cache.end(); ++it )
{
if( !it->second.lock() )
m_cache.erase( it );
}
 
Не уверен что это не вылетит, может лучше так
Код
C++ (Qt)
MapCache::iterator it;
for( it = m_cache.begin(); it != m_cache.end(); )
{
if( !it->second.lock() )
m_cache.erase( it++);
               else
                       it++;
}
 
Но не суть, это просто к слову.

За пример конечно спасибо, но Вы предлагаете "общий" способ решения. "Да чего там разбираться с какими-то классами Igors, вот есть прекрасная техника которая отлично работает в сотнях случаев - и в моей практике тоже!".  Улыбающийся  Я ничего не имею против кэширования, но это другая задача. Я хочу реализовать четко reference/dereference баланс. а не кэш. Резоны "почему" у меня есть, но давайте не терять время на их обсуждение, к делу это не относится. Спасибо.


Записан
BRE
Гость
« Ответ #17 : Декабрь 16, 2010, 22:06 »

Не уверен что это не вылетит, может лучше так
А в чем профит?

Я ничего не имею против кэширования, но это другая задача. Я хочу реализовать четко reference/dereference баланс. а не кэш.
А как без кэширования (в том или ином его виде) можно определить: загружен ресурс или нет?  Строит глазки
Кто-то должен за этим следить.

Насчет общего примера... А мне нужно было обязательно реализовать класс Image? Я вообще-то идею пытался показать.
« Последнее редактирование: Декабрь 16, 2010, 22:11 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Декабрь 17, 2010, 10:42 »

Не уверен что это не вылетит, может лучше так
А в чем профит?
У Вас получается что в цикле ++ применяется к итератору после его erase, и это может быть небезопасно

А как без кэширования (в том или ином его виде) можно определить: загружен ресурс или нет?  Строит глазки
Кто-то должен за этим следить.
Ну попробуем упростить - пусть нет окон и машин рисования. Тогда все тривиально - текстуры шерят имеджи. Значит надо как-то учесть машины

Насчет общего примера... А мне нужно было обязательно реализовать класс Image? Я вообще-то идею пытался показать.
Конечно нет, незачем терять время на мелкие брызги/детали. Я имел ввиду что предложенное решение никак не зависит от специфики задачи (оно общее). Ничего плохого в этом нет, но оно и будет работать "в свою силу". Кэш не гарантирует что все будет загружено во время интерактивных операций. Также какие-то картинки могут сидеть в кэше даже если они уже не используются. При размерах 50-100 Mb на картинку это "чревато". Поэтому нет смысла быстро делать первую версию которая создает потенциальные проблемы.
Записан
BRE
Гость
« Ответ #19 : Декабрь 17, 2010, 11:14 »

У Вас получается что в цикле ++ применяется к итератору после его erase, и это может быть небезопасно
Строит глазки
Никакого erase итератора не происходит, удаляется элемент на который указывает итератор.

Ну попробуем упростить - пусть нет окон и машин рисования. Тогда все тривиально - текстуры шерят имеджи. Значит надо как-то учесть машины
Как только появляются машины, сразу встает вопрос о том, что какая-то машина уже загрузила такую картинку, она есть в памяти и грузить ее повторно не нужно.  Смеющийся

Кэш не гарантирует что все будет загружено во время интерактивных операций.
Это как?  Улыбающийся
Кеш вообще не занимается вопросами загрузки.

Также какие-то картинки могут сидеть в кэше даже если они уже не используются.
С чего это?  Улыбающийся

Есть код, он компилируется и запускается. Посмотри.  Подмигивающий
Также, изменение этого кода в несколько строк, позволяет сделать удаление из кэше ссылки на разрушаемый ресурс. Т.е. все будет происходить автоматически и в кэше не будут оставаться ссылки на уже разрушенные данные.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #20 : Декабрь 17, 2010, 14:58 »

Никакого erase итератора не происходит, удаляется элемент на который указывает итератор.
Конечно, но нет гарантий что ++ умеет переходить на следующий элемент "самостоятельно". Он может использовать элемент на который ссылается - а Вы его уже удалили.

Также, изменение этого кода в несколько строк, позволяет сделать удаление из кэше ссылки на разрушаемый ресурс. Т.е. все будет происходить автоматически и в кэше не будут оставаться ссылки на уже разрушенные данные.
Кто и как возьмет на себя ответственность за удаление ресурса? Не вижу unlock() в Вашем коде - значит вытеснение происходит автоматически (емкость кэша). А если нет - то где предел до которого кэш может расти?

Как только появляются машины, сразу встает вопрос о том, что какая-то машина уже загрузила такую картинку, она есть в памяти и грузить ее повторно не нужно. 
Ну а как насчет "выделить сущности", "(глубоко) продумать взаимодействие" и многое др. о чем так много пишут?  Улыбающийся Давайте вместе выделять/продумывать (вместо того чтобы сваливаться в шаблонные решения которые в данном случае не очень подходят).
Записан
BRE
Гость
« Ответ #21 : Декабрь 17, 2010, 15:18 »

Конечно, но нет гарантий что ++ умеет переходить на следующий элемент "самостоятельно". Он может использовать элемент на который ссылается - а Вы его уже удалили.
Для чего эти предположения? Стандарт же.  Улыбающийся

Кто и как возьмет на себя ответственность за удаление ресурса? Не вижу unlock() в Вашем коде - значит вытеснение происходит автоматически (емкость кэша). А если нет - то где предел до которого кэш может расти?
Сколько ресурсов необходимо и используются (находятся в памяти), столько записей и будет в кэше. Как только все кто используют ресурс его освобождают данные ресурса удаляются из памяти, а ссылка на ресурс в кэше становиться невалидной и легко проверяется. А если немного модифицировать код (несколько строк), как я писал выше, то можно добиться того, что при разрушении ресурса ссылка на него удалялась бы и из кэша.

Приведенный мной код у тебя не компилируется? С чем то новым всегда проще разбираться с работающим кодом.

Ну а как насчет "выделить сущности", "(глубоко) продумать взаимодействие" и многое др. о чем так много пишут?  Улыбающийся Давайте вместе выделять/продумывать (вместо того чтобы сваливаться в шаблонные решения которые в данном случае не очень подходят).
Решения подходят.  Улыбающийся И пообсуждать/повыделять можем. Только вначале нужно задачу сформулировать.  Подмигивающий
« Последнее редактирование: Декабрь 17, 2010, 15:26 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Декабрь 17, 2010, 16:01 »

Для чего эти предположения? Стандарт же.  Улыбающийся
Хмм.. вот буквально вчера: итерирую std::set. При итерации вызываю метод который удаляет из того же set. Вылетает.

Сколько ресурсов необходимо и используются (находятся в памяти), столько записей и будет в кэше. Как только все кто используют ресурс его освобождают данные ресурса удаляются из памяти, а ссылка на ресурс в кэше становиться невалидной и легко проверяется.
Кто и как захватывает и освобождает? Простейшая схема:

- попросил менеджера дать ресурс - получил
- попользовался
- освободил

Все хорошо но при этом ресурс грузится/выгружается каждый раз. А если не так то как?
Записан
twp
Гость
« Ответ #23 : Декабрь 17, 2010, 17:22 »

Цитировать
Набросал немного кода, посмотри (компилябельно):
Код
C++ (Qt)
MapCache::iterator it;
for( it = m_cache.begin(); it != m_cache.end(); ++it )
{
if( !it->second.lock() )
m_cache.erase( it );
}
 
Не уверен что это не вылетит, может лучше так
Код
C++ (Qt)
MapCache::iterator it;
for( it = m_cache.begin(); it != m_cache.end(); )
{
if( !it->second.lock() )
m_cache.erase( it++);
else
it++;
}
 
Но не суть, это просто к слову.
не знаю как в std но в Qt в первом отрывке будет гарантированный вылет, я обычно так делаю:
Код
C++ (Qt)
MapCache::iterator it = m_cache.begin();
while (it != m_cache.end()) {
if(!it->second.lock())
it = m_cache.erase(it);
else
++it;
}
 
Записан
BRE
Гость
« Ответ #24 : Декабрь 17, 2010, 18:41 »

Кто и как захватывает и освобождает? Простейшая схема:

- попросил менеджера дать ресурс - получил
- попользовался
- освободил

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

Код
C++ (Qt)
{
Image i1 = ResMan::loadImage( "image1" );
 
// попользовались
}
// Здесь, если нигде больше картинка image1 не используется, то она выгрузиться.
// Если используется, останется в памяти
 

Код
C++ (Qt)
{
Image i1 = ResMan::loadImage( "image1" );
myImages.append( i1 );
}
 
{
Пользуемся картинками из коллекции myImages
Image i1 = myImages[ indexImage1 ];
Image newImage = i1;
}
 
{
myImages.remove( indexImage1 ); // Если эта картинка в локальной колекции не нужна, то удаляем ее.
// Если эта картинка больше нигде не используется, она выгрузиться автоматически
}
 
Записан
BRE
Гость
« Ответ #25 : Декабрь 17, 2010, 18:58 »

У Вас получается что в цикле ++ применяется к итератору после его erase, и это может быть небезопасно
не знаю как в std но в Qt в первом отрывке будет гарантированный вылет...
Признаю, с итератором действительно так лучше не поступать. Могут быть не предсказуемые вещи . Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Декабрь 18, 2010, 12:25 »

Код
C++ (Qt)
{
Image i1 = ResMan::loadImage( "image1" );
 
// попользовались
}
// Здесь, если нигде больше картинка image1 не используется, то она выгрузиться.
// Если используется, останется в памяти
 
Дело в том что нет подходящего места чтобы это воткнуть. Попробуем здесь
Код
C++ (Qt)
void DrawEngine3D::Draw( void )
{
       ...
Image i1 = ResMan::loadImage( "image1" );
       ...
}
 
Машина знает что "image1" должен быть отрисован (она же его и рисует). Но затем она его просто грохнет - ведь больше ссылок (пока) нет. Следующая машина опять загрузит и опять грохнет. Также заметим: если картинка используется 2 и более раз (в течение Draw), то она не выгрузится, но счетчик ссылок на нее будет постоянно расти.

Код
C++ (Qt)
{
Image i1 = ResMan::loadImage( "image1" );
myImages.append( i1 );
}
 
{
Пользуемся картинками из коллекции myImages
 
А в каком месте создать эту коллекцию? Если не в методе Draw - придется повторить все действия машины чтобы определить "а рисуем ли мы этот имедж". И эти мучительные проверки надо выполнять при всех действиях пользователя (вкл/выкл текстуру, открыл/закрыл окно и др.). 
Записан
BRE
Гость
« Ответ #27 : Декабрь 18, 2010, 12:34 »

А разве сейчас ты картинки грузишь прямо в методе draw?

IMHO, вначале нужно подготовить все данные для рендеринга и потом использовать их.
Это можно делать в конструкторе движка или в специальном prepare-методе. Вот там и нужно подготовить коллекцию ресурсов, необходимых для отрисовки, а в Draw их только использовать.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Декабрь 18, 2010, 14:28 »

А разве сейчас ты картинки грузишь прямо в методе draw?
Да (строго говоря не я, а программер чью работу я продолжаю). И я с его решением согласен.

IMHO, вначале нужно подготовить все данные для рендеринга и потом использовать их.
Это можно делать в конструкторе движка или в специальном prepare-методе. Вот там и нужно подготовить коллекцию ресурсов, необходимых для отрисовки, а в Draw их только использовать.
С "движком" как раз все ясно - сначала все зарядил, потом рендер. Но то что мы обсуждаем - совсем не движок, а "редактор" где пользователь готовит все для рендера (подбирает модели, текстуры, анимацию и.т.п). Здесь нет возможности все "перезарядить с нуля" - нужно динамически реагировать на активность пользователя.
Записан
BRE
Гость
« Ответ #29 : Декабрь 18, 2010, 14:39 »

Но то что мы обсуждаем - совсем не движок, а "редактор" где пользователь готовит все для рендера (подбирает модели, текстуры, анимацию и.т.п). Здесь нет возможности все "перезарядить с нуля" - нужно динамически реагировать на активность пользователя.
Ну так значит эту коллекцию ресурсов нужно держать в классе редактора.
Пользователь ткнул меню - загрузили картинку, положили в коллекцию, она осталась в кэше.
Ткнул в другом окне загрузить эту картинку, посмотрели - она есть в кэше, положили в коллекцию.
В двух коллекциях находятся только указатели на сами данные картинки.
Дальше пользователь ткнул выгрузить картинку из первого окна, она удалилась из его коллекции, но осталась в памяти для второго окна. Ткнул пользователь выгрузку этой картинки и из второго окна, она удалилась из коллекции и т.к. ее использовало только это окно - выгрузятся сами данные с вычеркиванием из кеша менеджера ресурсов.
Записан
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.301 секунд. Запросов: 23.