Про нанокри писать особенно нечего, думаю, что пара десятков фоток, которые легко можно найти в инете, дадут полное представление о размахе текущей конференции. Русская ритейловая разработка коллапсирует со скоростью черной дыры, КРИ-шный вакуум заполняется социально-казуально-айфонной аудиторией не так быстро. Хочется все же надеяться, что текущая
(
Read more... )
Возникал вопрос как контролировать последовательность выполнения, в случае сложной логики, да без развесистой иерархии callback'ов.
Придумалось тогда такое: контролировать порядок исполнения на уровне данных.
Предположим что объект Unit1 "принадлежит" первому процессору, а Unit2 - второму. Код, который работает с данными объектами, соответственно, будем запускать на 1 и на 2 процессорах. Если процессор 1 дергает метод Unit2 - он будет ждать пока не получит результат, т.е. блокируется.
И вот появляется магия. Представим что у нас есть микропотоки: очень легковесные конструкции, каждая со своим стеком. Переключение между микропотоками очень быстрое - по сути поменять регистры местами, да указать на его стек.
Вместо того, что бы блокировать и ждать результата от 2го ядра, первый процессор берет следующую задачу, которая висит у него в очереди и выполняет ее - переключается на ожидающий микропоток. Как только появится результат от ожидающего микропотока (и сейчас ничего не выполняется) - продолжит свое управление.
Из положительных моментов:
- Код получается обычный и линейный
Как концепция, оно достаточно красиво, но разбивается о суровую действительность:
- Микропотоки прийдется делать самому, включая шедулер, поддержку разрастающегося стека, etc)
- Простом случае - перехватывать вызовы методов таких вот объектов. Стандартными средствами под С++ такое сделать нельзя. Конечно, можно сделать препроцессором...
- Сложно будет отлаживать все это хозяйство. Callstack, боюсь, будет отсутствовать как класс. Разве что делать какие-то свои тулзы, которые будут анализировать шедулер и показывать кто что сейчас делает и откуда оно пришло.
Ну и вообще - explicit is better than implicit, так что так оно и заглохло.
Reply
По похожей схеме реализовывалась система еще в давних-давних проектах Крейта (типа Недетских Гонок или American Chopper).
По тогдашнему проектированию получается примерно следующая картина:
1. Общее количество классов - в диапазоне 50-200 штук. Это хороший объем, чтобы можно было окинуть картину взглядом, не вникая в детали реализации (еще один бонус к таким схемам).
2. Общее количество подписчиков - до десятков тысяч штук.
3. Обработка событий - достаточно серьезное занятие (например, весь процесс управления NPC машинкой - перемещение, коллижен, выбор дальнейшей траектории движения), которое занимает существенно большее время, чем выборка следующего джоба из Dependency Graph. В пунктах 1-3, кстати, еще кроется предпочтительное агрегирование против наследования.
4. Отдельные экземпляры каждого класса By Default являются независимыми друг от друга. Если существует некоторый процессинг, который требует доступ до всех экземпляров класса сразу, то его лучше оформлять отдельным подписчиком (например, CarNpcCommon after CarNpc).
Reply
- Проектировать все придется так, что бы оно не проводило большую часть времени в шедулере, когда каждый ждет каждого. Ну и наоборот - когда задач мало, делать нечего, ядра друг друга ждут.
Reply
Reply
Leave a comment