XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
Darklight

offline
Опыт: 976
Активность:
Вызов GetHandleId у удалённого объекта
Что будет, если вызвыать функцию GetHandleId(hndl) у переменной, ссылающейся на объект, который был уже удалён (переменной значение null не присваивалось)?
Значение будет отличным от вызова данной функции у неудалённого объекта?
Есть ли какая-нибудь разница, если это ссылка была получена из хештаблицы?
Старый 01.07.2012, 15:37
Lipen

offline
Опыт: 1,550
Активность:
Разве так трудно проверить?
» Тык
        timer t = CreateTimer()
        int h = GetHandleId(t)

        SaveTimerHandle(Hash, h, 123, t)
        timer t2 = LoadTimerHandle(Hash, h, 123)
        int h2 = GetHandleId(t2)

        BJDebugMsg("Start. Handle id : " + I2S(h))
        BJDebugMsg("Hash. Handle id : " + I2S(h2))

        DestroyTimer(t)
        h = GetHandleId(t)
        BJDebugMsg("Destroy. Handld id : " + I2S(h))

        t = null
        h = GetHandleId(t)
        BJDebugMsg("Null. Handle id : " + I2S(h))

        Msg("End")
Старый 01.07.2012, 15:53
DioD

offline
Опыт: 45,134
Активность:
объект высвобождается не мгновенно (иногда), цикл внутреннего GC работает по фазе луны.
Старый 01.07.2012, 18:16
Darklight

offline
Опыт: 976
Активность:
Lipen, Простите, вы, кажется, не поняли суть вопроса. А суть была вот в чём:
  1. Я помещаю в хештаблицу, к примеру, хэндл юнита (ИЛИ таймер, без разницы) по какомуто id
  2. Получаю ID этого хендла (от самого объекта юнита/таймера)
  3. Помещаю по этому ID в хештаблицу ещё что-нибудь (не важно что)
  4. Где-то сохраняю это ID (неважо где)
  5. Через некоторое время юнита убивают и убирают с карты (разрушают таймер)
  6. Ещё через некотороев время (может весьма продолжительное) я получаю хэндл юнита (таймера) по id из хештаблицы.
  7. И получаю i_d этого хэндла
  8. Теперь образаюсь по ID и i_d я однозначно обращусь к одной йчейки хештаблицы? То есть, эти идентификаторы будут совпадать? То есть, удаление юнита (таймера) никак не скажется на его идентификаторе?
Старый 01.07.2012, 18:33
DioD

offline
Опыт: 45,134
Активность:
хештаблица учитывается GC, если ссылка на объект есть в хештаблице объект никогда не освободится.
Старый 01.07.2012, 19:26
Darklight

offline
Опыт: 976
Активность:
DioD, Всё понял, спасибо.
Старый 01.07.2012, 20:19
ScorpioT1000
Работаем
offline
Опыт: отключен
о каком объекте идет речь? destroy уничтожает данные мгновенно, далее объект становится "пустым" - почти все функции работы с ним возвращают фейлд, при этом хендл висит в памяти
Старый 01.07.2012, 20:48
Vadik29
Choice Battle 1.6а
offline
Опыт: 15,845
Активность:
Иногда вызов пустой функции приводит к полной остановке процесса, а в тяжелых случаях бывает десинх или крит.
Старый 01.07.2012, 21:05
Darklight

offline
Опыт: 976
Активность:
ScorpioT1000, Речь шла только про хэндл.
Если я буду помещать в хеш сам объект (юнит или таймер), то спустя некоторое время мне нужно будет к нему обратиться. Так вот, мне нужен будет ID его хэндла и факт того, что объект ещё жив или уничтожен, чтобы выполнить сервисные функции (например, по очистке данных в хештаблицах по этому объекту, в случае его гибели).
Если такой подход не надёжен, придётся вставлять скрипт очистки по смерти воина (хотя это не всегда годится, т.к. некоторые, скажем, способности, ещё некоторое время должны "висеть над трупом" - но это, конечно решается; то же и с разрушаемым объектом), а вот с таймером уже сложнее (нельзя отследить момент его разрушения, правда это можно сделать только программно - значит тоже решается).
А вот, что делать, например, с предметом? Если к нему привязаны данные в хештаблицах, то как корректно определить, что предмета больше нет и данные необходимо очистить? Сохранять ссылку на предмет в связке с числовым ID её хэндла и сверять по периодическому таймеру?
А в хештаблице могу сохраняться и другие объектные типы, что с ними?
Старый 02.07.2012, 19:53
prog

offline
Опыт: 32,865
Активность:
Darklight, советую пересмотреть структуру того что ты делаешь. Что бы там ни говорили, хештаблицы достаточно быстро работают, но все-же не стоит ими злоупотреблять, делая каждый чих с их использованием. Если не можешь проконтролировать жизненный цикл объекта, не используй его хендл как ключ в таблице.
Старый 02.07.2012, 21:22
J64_

offline
Опыт: 4,724
Активность:
как решение можно сделать структуру с хэндлом этого объекта, и использовать в качестве ключа\индекса структуру.
Старый 03.07.2012, 04:51
ScorpioT1000
Работаем
offline
Опыт: отключен
проверять существование юнита так GetUnitTypeId(u) > 0 итема GetItemTypeId(u) > 0
ScorpioT1000 добавил:
+ к этим проверкам добавлять and IsUnitAlive (ну это не точно так, но суть ясна), если мертвые тоже не нужны
Старый 03.07.2012, 13:02
Darklight

offline
Опыт: 976
Активность:
prog, Тогда, прошу дать совет. Сейчас подход такой:
У юнита(ов) обрабатывается какое-либо триггерное заклинание (или аура, или автоприменение/автоподбор целей), действующее во времени - тогда я:
  1. Создаю таймер, циклически отрабатывающий действие заклинания
  2. Помещаю под идентификатором таймера в Хеш таблицу данные, связанные с этим заклинанием (включая ссылку на юнита-владельца данного заклинания)
  3. Для заклинаний, которые имеют эффект управления от своего владельца, помещаю под идентификатором юнита (в связке с идентификатором заклинания в качестве второго ключа) ссылку на таймер этого заклинания.
Тогда - таймер, срабатывая, получает по своему идентификатору все необходимые данные и проверяем "жизнь" юнита-владельца - если он мертв - завершает свою работу и стартует очистку Хеш данных, связанных с таймером и с юнитом.
Когда юнита - производит управление - то по идентификатору юнита и второго ключа (идентификатора заклинания) получается ссылка на таймер - по идентификатору этого таймера получаются данные заклинания из Хеш таблицы и команда управления обрабатывается. По необходимости таймер уничтожается и данные в Хеше по нему очищаются.
Отдельно - можно обработать подписку на смерь юнита - тогда по идентификатору юнита и перечню идентификаторов заклинаний этого юнита в качестве второго ключа получаются ссылки на таймеры, таймеры уничтожаются, по идентификаторам этих таймеров очищаются данные в Хеш таблице. В конце очищаются данные в Хеш таблице по самому юниту.
В принципе, у одного заклинание может быть несколько таймеров - они прописываются под идентификатором юнита в Хеш таблице под разными вторичными ключами.
Итого получается двойная ссылка в Хеш таблице. Под идентификатором таймера лежат данные и ссылка на юнита-владельца. Под идентификатором юнита и идентификатором видов заклинаний (второй ключ) лежат ссылки на таймеры, которые относятся к этим заклинаниям. Нужный источник выбирается в зависимости от обращений - из события таймера или из события юнита.
Естественно для заклинаний, не имеющих управления со стороны юнита с момента своего начала выполнения (люього вида), связь из юнит->таймер не нужна, но лично сейчас у меня все триггерные заклинания получаются с управлением ;)
Всё слишком сложно? Есть более простое решение?
А, ведь, я пока говорил только про заклинания и юнитов/разрушаемые объекты, а ведь с предеметами хуже - там отследить их "гибель" сложнее!
Judycaster64, Что за структуру Вы имеете в виду? Я, в данном проекте, не использую vJass/cJass, да и там, насколько я знаю, структуры - это лишь обёртки над массивами и они не имеют хэндла.
А так, то я, конечно, могу сохранять не только ссылки на таймеры/юнитов но и их идентификаторы. Мой вопрос был как раз в том, стоит ли не стоит так делать. Сначала я дела Хеш таблицы, сохраняя перекрестные ссылки в виде числовых идентификаторов. Потом переделал на объектные ссылки и... задался этим вопросом.
Старый 03.07.2012, 13:29
Hate
конь вакуумный
offline
Опыт: 43,030
Активность:
что то не понятно чего ты добиваешься, есть мнение что ты сам придумал себе сложности.
умер юнит -> очистил все на его ключе
тикает таймер/>условия что юнит умер -> очистил все на его ключе
непонятно что ты там придумал
Старый 03.07.2012, 13:37
Darklight

offline
Опыт: 976
Активность:
Hatsume_Hate, Ок. Привожу пример. Имею заклинаний с нестандартным автоприменением. Поиск цели, для применения заклинания, осуществляется триггерно:
1. Беру, например, базовую абилку “Acrs” (Проклятие).
2. Отлавливаю команду начала автоприменения “curseon” (событие юнита).
3. Проверяю ячейку в Хеш таблице по идентификатору юнита (первый ключ) и идентификатором заклинания (второй ключ: StringHash(“My super ability autousing timer”)) на наличие значения через функцию HaveSavedHandle.
4. Если значение есть – значит таймер уже запущен – ничего делать не нужно.
5. Если значения нет - запускаю таймер заклинания, который ищет подходящие цели и, когда находит отдаёт юниту-владельцу приказ “curse” на найденную цель (далее отрабатывает триггер данного приказа и к делу это уже не относится). Таймер помещаю в Хеш таблицу под идентификатором созданного таймера.
6. В ячейку этого идентификатора помещаю ссылку на юнита-владельца (чтобы получить того, кому нужно будет отдать приказ для применение заклинания на цель).
7. Под идентификатором юнита (первый ключ) и идентификатором заклинания (второй ключ: StringHash(“My super ability autousing timer”)) помещаю ссылку на таймер.
8. Событие таймера. Таймер на каждой своей итерации получает из Хеш таблицы юнита-владельца (по идентификатору таймера) - caster .
9. Проверяю полученного юнита на то, что он уже мёртв (GetWidgetLife(caster)<0.405)
10. Если мёртв, то останавливаю таймер, очищаю в Хештаблице данные по идентификатору таймера и удаляю значение в ячейке под идентификатором юнита (первый ключ) и идентификатором заклинания (второй ключ: 0StringHash(“My super ability autousing timer”)) через RemoveSavedHandle, уничтожаю таймер.
11. Если юнит жив, то ищу цель (target) в области нахождения этого юнита, и когда её нахожу, выполняю команду IssueTargetOrder(caster, “curse”, target)**.
12. Отлавливаю команду окончания автоприменения “curseoff” (событие юнита).
13. По идентификатору юнита (первый ключ) и идентификатору заклинания (второй ключ: StringHash(“My super ability autousing timer”)) получаю ссылку на таймер.
14. Останавливаю и уничтожаю таймер.
15. Очищаю в Хештаблице данные по идентификатору таймера и удаляю значение в ячейке под идентификатором юнита (первый ключ) и идентификатором заклинания (второй ключ: StringHash(“My super ability autousing timer”)) через RemoveSavedHandle.
16. Отлавливаю команду окончания автоприменения “curse” (событие юнита).
17. Обрабатываю необходимые действия – применяю заклинание на цель.
18. НЕОБЯЗАТЕЛЬНО. Отлавливаю событие “Unit die” (событие юнита).
19. Проверяю ячейку в Хеш таблице по идентификатору юнита (первый ключ) и идентификатором заклинания (второй ключ: StringHash(“My super ability autousing timer”)) на наличие значения через функцию HaveSavedHandle.
20. Если значения нет – значит таймер не запущен (автоприменение не включено) – ничего делать не нужно.
21. Если значение есть – то, по идентификатору юнита (первый ключ) и идентификатору заклинания (второй ключ: StringHash(“My super ability autousing timer”)) получаю ссылку на таймер.
22. Останавливаю и уничтожаю таймер.
23. Очищаю в Хеш таблице данные по идентификатору таймера и удаляю значение в ячейке под идентификатором юнита (первый ключ) и идентификатором заклинания (второй ключ: StringHash(“My super ability autousing timer”)) через RemoveSavedHandle.
Как-то вот так получается. Простой алгоритм обработки автоприменения заклинания. В данном случае целевого заклинания, но это не важно.
Я в чём-то не прав?
Darklight добавил:
ScorpioT1000:
проверять существование юнита так GetUnitTypeId(u) > 0 итема GetItemTypeId(u) > 0
Вот это и была суть вопроса:
  1. С одной стороны имеем то, что ссылки в хештаблице не дают удалить объект - т.е. если у меня в таблице будет именно ссылка, то по ней я всегда получую ID хэндла > 0 и я вполне могу операться на эти ссылки и идентификаторы как на ключи
  2. С другой стороны, тогда через функции GetUnitTypeId и GetItemTypeId (а проще через GetHandleId) нельзя проверить, что юнит/предмет уже не существуют (т.к. пока ссылка на них есть в хештаблице - они не будут уничтожены в памяти).
Старый 03.07.2012, 14:56
ScorpioT1000
Работаем
offline
Опыт: отключен
пока ссылка на них есть в хештаблице - они не будут уничтожены в памяти
Откуда такая информация?
Старый 03.07.2012, 15:09
Darklight

offline
Опыт: 976
Активность:
ScorpioT1000:
пока ссылка на них есть в хештаблице - они не будут уничтожены в памяти
Откуда такая информация?
отсюда (пост выше)
DioD:
хештаблица учитывается GC, если ссылка на объект есть в хештаблице объект никогда не освободится.
что - не так?
Старый 03.07.2012, 15:30
Hate
конь вакуумный
offline
Опыт: 43,030
Активность:
FlushChildHashtable( hash, key)
Старый 03.07.2012, 15:46
ScorpioT1000
Работаем
offline
Опыт: отключен
о каком объекте идет речь? destroy уничтожает данные мгновенно, далее объект становится "пустым" - почти все функции работы с ним возвращают фейлд, при этом хендл висит в памяти
кароче попробуй сохранить в хт, убить юнита, заремувить его и проверить через время GetUnitTypeId
при этом время разложение дб равно нулю, иначе он действительно будет висеть целиком
Старый 03.07.2012, 16:18
Darklight

offline
Опыт: 976
Активность:
Hatsume_Hate:
FlushChildHashtable( hash, key)
Это к чему было сказано?
Старый 03.07.2012, 17:51
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 00:38.