2 дек. 2010 г.

Машграфы


Тетрис – финал

Тетрис – поиск стиля

Грибной лес – почти финал

Грибной лес – второй вечер работ

Финал Леса:


Ежели кому по-нраву и охота поиграться самим пишите в комменты с указанием ОС.
Как кончиться курс машграфа есть вероятность что подчищу сорцы от говна и выложу на гитхабе.

Второго нет, потому что только самый обычный успел.
Четвертый – рейтрейсер. Дали в этот понедельник. Еще не брался.

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

Таймлайн вида: "Тетрис, большой перерыв, Распознование людишек, перенос срока 2 раза, небольшой перерыв, Лес с грибами, почти отсутствие перерыва, Рейтрейсер" какбы намекает на некоторую недодуманность дедлайнов/заданий. Стандартный срок 2 недели. Надо либо задания проще (в том году были проще), либо сроки изначально лучше продумать.

На время грибочков прям таки на неделю из жизни выпал, правда с шейдерами никто ковыряться не просил, да и опечатки за которыми я гонялся 1,5 дня с valgrind'ом исключительно мой fail.

16 нояб. 2010 г.

Псевдо-литературный высер

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

25 июл. 2010 г.

LastCover alpha

Как я и обещал – я боле-менее допилил LastCover (потом лучше допилю) и выложил сорцы.
При этом я убил двух зайцев: я не просто выложил сорцы, я наконец заюзал github и собственно git. Тащем-то сугойно :)

15 июл. 2010 г.

Textual defecation

Что-то давненько я не ходил в бложик по-большому :)

Итак: на кафедру АЯ – попал, притом на желанный семинар, на отличные концерты (DSO и Xandria) сходил (кому интересно – в интернетах полно отчетов и фото), сессию закрыл (как ни странно чем меньше парюсь, тем лучше сдаю), на работу устроился (пограммистом под iOS, чсх – выцепили меня в контактике – вот уж от чего пользы не ожидал).

Заимел в пользование MacBookPro 13" (рабочий, охуительный девайс) и бас Ibanez ^_^ (от знакомых, видимо куплю с зарплаты).

Ощущения от MacOS X – вцелом все удобно и хорошо, но не без проблем. Действительно почти идеальная ось для повседневных задач, большая часть неудобств была связанна с непривычностью, теперь комфортно.
Самый шикарный охуец: нету никакой галки чтобы ноут не засыпал при закрытии крышки (но если подключить моник – не засыпает). Решинем стала InsomniaX, несчастная софтина устнанавливает модуль ядра, что какбы намекает на степень костльности решения.
Guake мне заменил Visor. Отдельно отмечу Better Touch Tool, которая позволяет по-настоящему утилизовать возможности тачпэда. Quicksilver какой-то глючный, да и спотлайт его почти заменяет. Доставляет остутствие Cmd-X в Finder от того, что это противоречит философским воззрениям Ябла :)
Не хватет полноценного менеджера пакетов, впрочем есть сторонние решения.

iTunes тема отдельная, ибо количество анальных гвоздей зашкаливает, особенно в момент подключения я-планшетки. Попробовал переползти на Songbird, тот оказался тормозным и глючным (xulrunner жеж), но оч классно интегрировался с last.fm и прочими около музыкальными интернетами (xulrunner жеж). Хныкая уполз обратно к Тунцу. И тут меня поджидал ещё один охуец - вместо плагнов и скриптов большинство обвесов являет собой отдельные софтинки висящие в системе и взаимодействующие с тунцом через его pubic API (кстати очень многоие приложения для мака могут управляться Apple Script'ом как раз через подобный API). Некоторые умеют запускаться и убиваться вместе с тунцом, что приятно.
Нашел маленький, уютный скробблер, который так же умеет выводить нотификации. Нашел ещё кучу всякого прикольного, но бесполезного для меня.
А вот со стягиванием обложек все как-то очень грустно – из всех что я нашел – только один платный умеет стягивать с ласта обложки для моей (видимо слишком экзотической для стягивалок с амазона) коллекции, но он платный и перегруженый. Потому взялся вечерами пилить свой. Через час полностью заработал, но пока управляется правками кода, а допиливать некогда, как только доведу до адекватного состояния - выложу на гуглокод.

Да, с инструменатами для разработки проблем не обнаружено, многое уже есть в пакетике для девелоперов, чего нет – нетрудно доставить, unix жеж.

Из того, чем духовно обогатился могу посоветовать: Caprice, Carnival in Coal, The Vision Bleak, Mr. Nobody, Star Trek TOS, Первые книги про Ведьмака (Анжей Сапковский), Игра про ведьмака (The Witcher)

5 июн. 2010 г.

Как нам обустроить Россию

by Костарев Иван aka ChaoX

Считается, что социальное неравенство по финансовому признаку является одной из причин бед в обществе. Как известно, попытки добиться всеобщего равенства путём отмены денег успехом не увенчались.
Однако, это ни в коем случае не значит, что надо опускать руки! Буквально утром мне в голову пришло настолько простое решение проблемы, что удивительно, что до сих пор никто ещё до него не додумался!
Всё, что требуется - это переход к измерению количества денег в комплексных числах!
Действительно, множество комплексных чисел нельзя упорядочить, а значит финансовая дифференциация общества потеряет всякий смысл - и вот оно, идеальное всеобщее равенство!

29 мая 2010 г.

Ебанариум

Меня и одну подругу конкретно так накрыло:

- Между прочим чебурашка 2жды винни-пух и посему чернослив

- а как же его еврейские и немного норвежские корни? заблудились в ушах?

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

- О_О чудеса... и как он так расчебуранился скрипно? совсем забыл сопесть? почему же ему под пятку ничего не нашептали? нужно же правовое регулирование! и кто его теперь съест? чего ради он гольфы носит на ушах?

- Да что уж теперь-то уж? Разве чтож под нож! По капельке скальпелюшечке да на стол писаный маслом между прочим по холсту. "Ах какая страсть-то" - взвизгивали молодые, ещё не вполне княжны глядя на ту вполне искусную работу мастера века этак цатого.

- а какая судьба у этих дамочек? они таки стали княжнами?) или их тоже... расписали..?

- Расписали конечно, да распилили между собой, по-тихому. Как мужечёк елочку, да под новый год. А все потому что власти вертикаль уж вертикальная больно, вот и мрак на горизонте!

- так и во мраке ведь есть что-то.. не видно просто.. о_О может, там моржинки прячутся?

- Вот и я о чем: холод мороженый и мрак лупоглазый!

З.Ы. Никаих наркотиков, только матан и чего-то-что-учат-на-юрфаке

13 мая 2010 г.

Power of Differential Equations Elixir

Эликсир Мощь Диффуров: кровь Хайлова, моск личинки Хайлова(аспиранта), горелая страница Филлипова, слезы неcдавшей первокурсницы. Гарантирует сдачу диффуров.

Что характерно - я сегодняшние (до)сдал. Кто не был на первой контрольной - можно ещё в следующий четверг, но уже не в "наставнике"

6 апр. 2010 г.

Как сломать vim шаблонной магией

Симптомы:
Пишу в vim'е  objname. в момент написания точки vim, консолька а потом и весь гуй повисают.
Жму Ctrl+Alt+F1 через ~минуту вижу черноту текстовой консоли. Логинюсь. Отстает даже ввод текста в текстовом терминале. Таки умудряюсь глянуть top, узреть что все сожрал именно vim. Снимаю его. Переключаюсь обратно в графику. Наступаю снова на те же грабли. Снова привожу все в порядок. Догадываюсь наконец что происходит. Добиваюсь своего :)

Что происходило:
Vim у меня настроен таким образом, что если сгенерированы теги, он пытается провернуть code completion. Точка после слова в cpp файле - один из триггеров. В коде шаманский рекурсивно определенный класс-шаблон вида:

tempate <class T>
class A: public A<T> {
 ...
};

template <>
class A<NullT> { 
};

Означенный объект как раз этого чудо-класса. Vim, пытаясь предложить возможные варианты уходит все глубже и глубже в это наследование, которое несчастному редактору кажется вечным, ведь в его обязанности не входит разбираться со специализациями. Хотя разрабы могли бы хоть ограничение на поиск воткнуть. Быть может соберусь с силами и починю vim :)
Такие дела.

5 апр. 2010 г.

Свежие альбомы Pagan'цев

Итак по порядку. Все ниже написанное ИМХО.

Butterfly Temple - Земля
Альбом хорош, если не сказать больше. Присутствуют "цепляющие" треки. "Смерть" вообще шедевр. 4,5 из 5.














Невидь - Янтарное сердце Арктиды
У меня очень противоречивые чувства относительно этого альбома. С одной стороны звучание стало другим, присутствуют довольно интересные моменты. А с другой - слишком тяжело, нету ничего похожего на "Ярым оком" или "Мокоши прядь храню". Нет даже лютого и бешеного драйва как в "Тени от сейдов" и "Зов новой гипербореи". (Совершенно непонятно почему). Звучание стало намного тяжелее, но нету драйва. Даже скучновато как-то, все наверно потому, что драйва мало. :)
Хотя есть и забавные моменты, только благодаря им и дослушал альбом до конца.

P.S.: Особо доставил следующий текст:

"Постой, не уходи, подруга!
В петлях не болтались мы,
В озорных объятиях друг друга
Не смотрели с мертвой высоты…

Птицы не клевали наши лица,
Ветер не раскачивал тела.
Это ж надо было умудриться-
Не узнать, как вянет голова!

Я и так уже давно без блеска,
Что играл в моих сухих глазах.
Нету в этой жизни интереса,
Кроме нежных слов в твоих устах…

Остальное все туман, пустое,
Головокружение в бреду…
Если счастье есть, оно простое -
Быть в петле с тобою на ветру…" 




Путь Солнца - Победитель всегда остается один
Отдельно хочется сказать, что обложка говно. И куда подевалось относительно вменяемое лого группы? 
Звук записан весьма годно. Но вокал звучит как-то "приклеено" и совсем не так яростно. Местами вокал блевотен. Вокал на "Эффекте бабочки" мне нравился куда больше. На концерте они забавнее чем в записи. =)

4 апр. 2010 г.

Template Magic Applied

Вот интересно что лучше: скрипт на Ruby, который генерирует:
    1 #ifndef __ENCODING__
    2 #define __ENCODING__
    3 
    4 template <typename T>
    5 struct encode_type {
    6     static const char code = '?';
    7 };
    8 
    9 template <typename T>
   10 struct encode_type<T *> {
   11     static const char code = '*';
   12 };
   13 
   14 template <>
   15 struct encode_type<char> {
   16     static const char code = 'c';
   17 };
   18 
   19 template <>
   20 struct encode_type<int> {
   21     static const char code = 'i';
   22 };
   23 
...

Или шаблонная магия:

    1 #include <cstdlib>
    2 #include <cstdio>
    3 #include <iostream>
    4 
    5 using namespace std;
    6 
    7 namespace Encodings {
    8  template <typename H, typename T>
    9  struct EL {
   10   typedef H Head;
   11   typedef T Tail;
   12  };
   13 
   14  template <typename T, char c>
   15  struct EP {
   16   typedef T Type;
   17   static const char code = c;
   18  };
   19 
   20  struct NullType;
   21 
   22  typedef EL<EP<int, 'i'>, EL<EP<char, 'c'>, EL<EP<float, 'f'>, EL<EP<double, 'd'>, EL<EP<bool, 'b'>, NullType> > > > > Encodings;
   23 
   24  template <typename List, typename T>
   25  struct EncFor {
   26   static const char result = 0;
   27  };
   28 
   29  template <typename T>
   30  struct EncFor<NullType, T> {
   31   static const char result = 0;
   32  };
   33 
   34  template <typename T, typename Tail, char c>
   35  struct EncFor<EL<EP<T, c>, Tail>, T> {
   36   static const char result = EP<T, c>::code;
   37  };
   38 
   39  template <typename T, typename Wrong, typename Tail, char c>
   40  struct EncFor<EL<EP<Wrong, c>, Tail>, T> {
   41   static const char result = EncFor<Tail, T>::result;
   42  };
   43 
   44  template <typename T>
   45  char encode_type(void) {
   46   return EncFor<Encodings, T>::result;
   47  }
   48 
   49  template <typename T>
   50  char encode_var_type(T t) {
   51   return encode_type<T>();
   52  }
   53 }
   54 
   55 int main(int argc, char **argv) {
   56  cout << Encodings::encode_type<int>() << endl;
   57 
   58  return EXIT_SUCCESS;
   59 }

Первое - проще осознать, проще дописать потом ещё тип, быстрее компилируется.
Второе - наркоманство, чтобы дописать ещё тип, надо осознать, долго компилируется. НО проще переделать все encoding'и, и нет внешнего генератора.
Мне больше нравится первый вариант, но отдельные личности против генерации кода внешней тулзой :( Интересно какой из вариантов попадет в release :)

30 мар. 2010 г.

one-liner

Template-Meta-Wizard! Исполняет ваш самый сокровенный код в момент компиляции! xD И, что характерно, без побочных эффектов.

26 мар. 2010 г.

Людишки-муравьишки

Если кинуть муравьям печенье, то оно вначале немного повернется а потом "поедет" к муравейнику. Почему так? Ученые не сразу осознали.
Все оказывается нехитро: каждый тянет на себя, в итоге "побеждает" та сторона печеньки, где оказалось больше муравьев.

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

Убей людишку, выпей людишкну кровь... (Thief 3' Pagans)

28 февр. 2010 г.

Полнота по Коши

Предлагаю, по аналогии с полнотой по Тьюригну, языки полные матана (Haskell) называть полными по Коши :)

8 февр. 2010 г.

Ruby & Co

Во-первых решил запилить на Ruby обработку медиатеки. Успешно написал стягивание обложек с ласта. Дальше чего-то забил.

Во-вторых по случаю поднял дома сервак из ешки (apache + passenger -> redmine) и сделал внешний IP.
Выводы: redmine рулит. Не ставте passenger из репозитариев ubuntu =) Не пользуйте горком =)

С++ с конкурентностью и акторами (подобием оных)

Далее будет мой концепт на тему. Разрабатываю главным образом в рамках этого
Заренее прошу прощения за поехваший код. Я хз как его заставить нормально отображаться :(

Ниже я изложу некоторое количество мыслей на тему in-game объектов, сервисов, поддвижков и того, как это параллелить. Излагать буду в следующем порядке:
1) Абстрактно в отрыве от всего, о модели взаимодействия.
2) Как описанное в предшествующем пункте ложится на нашу задачу, как это пользовать и как мешать с plain С++ кодом. В отрыве от реализации.
3) Как это будет реализовано.

1) Абстрактное
Давайте на время забудем про нашу задачу, про наш С++ и про всё остальноё, отхлебнём хорошего чая и погрузимся в сабж.
Итак мы хотим (просто хотим, срочно забыли про задачу!) чтобы в конкурентном, возможно распределённом, окружении существовали и взаимодействовали какие-то артефакты, и чтобы было быстро. Обременив себя такими желанием мы непременно изобретём Erlang и Actor-model. Немного приспустившись на бренную землю (вот тут можно вспомнить, что мы делаем игру и что мы не Naughty Dog) нам захочется во-первых чего-то более знакомого и императивного, потому, что надо писать игру, а не учиться ФП (оно жутко полезно, но не в проекте с приходящими и уходящими кадрами); во-вторых нам захочется чего-нибудь менее асинхронного. Рассуждая, в таком ключе я пришёл к некоторой компромиссной модели.
Вот теперь вновь пришло время позабыть про то, что мы делаем, в противном случае в голове вашей будут роится мысли о том, оно как на мою модель ложится, которые, возможно, будут мешать воспринимать саму модель. Вначале обратимся к конкурентности, и введём понятие процесса (process), способного к выполнению полезной работы (О том как красавца трудоустроить мы поговорим немного позже). Процессы на реальные потоки ложатся как-то, нас это пока не волнует, нам сейчас важно, знать что они могут выполняться одновременно. Ну а "какие-то артефакты" назовём объектами (objects), типизированы объекты... странно они типизированы =) А строго-говоря не типизированы вовсе. Чтобы как-то различать поганцев будем помечать каждый тегами (tag), прямо как сообщения в вашем блоге. По тегу можно выбирать коллекции объектов, и производить с ними операции. Для коммуникации воспользуемся телеграфом^W сообщениями (message). Сообщение можно послать как кому-то так и широковещательно. На сообщение можно ответить банально вернув результат. Для взаимодействия один объект посылает сообщение другому (это близко к вызову метода, но не совсем), где-то за кулисами что-то происходит (а может и не происходит), и вот сообщение доставлено, вызывается реализация (implementation). А вернее реализации, на каждое сообщение можно навесить сколько душе угодно реализаций, они все будут вызваны, в недетерминированном порядке (в т.ч. параллельно). Если реализация не определена, то ничего не произойдёт (но можно ловить warnig'и при отладке), а в качестве результата вернётся гордый 0 (NULL/nil/...).
Но пока объекты сами по себе чертовски глупы (единственно обучены ссылки считать, впрочем это уже детали), учить их уму (ма)разуму вестимо задача программиста. Для этого придумаем расширения (extension). Расширением называется комбинация из данных (datum) и реализаций, сопоставленных паре {tag, process}. В момент регистрации расширения (она может произойти и в run-time) все объекты, отмеченные тегом, к которому привязывается расширение, обучаются обработке сообщений, реализации которых определены в расширении (либо реализации добавляются к уже существующим). Как не трудно догадаться, когда объекту приходит сообщение, реализации исполняются в соответствующих процессах. Сообщения обрабатываемые одним процессом никогда не обрабатываются одновременно. Ни между тегами, ни между процессами данные не разделяются вообще, синхронизация получается за счёт нескольких обработчиков одного сообщения. Избавившись от разделяемого ресурса, мы избавляем себя и от необходимости контроля доступа (mutex'ы и прочее), идея эта не нова и за годы себя зарекомендовала.
Важно отметить, что при выборках вместо идентификаторов tag и process может быть передано "ничего", что будет синонимично "выбору всех" или "для любого". То есть при регистрации расширения для {0, process1} вы добавите всем объектам обрабатываемое в process1 расширение, а при {tag1, 0} всем помеченным как tag1 расширение, обрабатываемое в параллельно с чем угодно, при этом вы берёте на себя ответственность за синхронизацию.

2) Использование
Будем считать что описанное в предыдущей части усвоено и душа требует примеров использования. Несмотря на моё желание о реализации поговорить позже, кое-что всё таки придётся оговорить. Раз языком реализации выбран С++, то давайте его просто надстроим где-нужно. Для начала изобретём синтаксис.
Посылка сообщения: @object->messageName(p1, p2); или @select(tag1, tag2, ..., tagN)->messageName(p1, p2); (параметров сколько нужно). Первый вариант - посылка целевому объекту, второй - всем объектам, одновременно помеченных перечисленными тегами. Возможно будет посылка сообщения произвольному списку объектов. Возможно будет @map. Теги добавляются так: @object += tagName; убираются: @object -= tagName; Можно вместо одного тега указывать список тегов: @object [+/-]= (tag1, tag2) Все вышеприведённые конструкции возвращают значение, какое именно, опишу в деталях реализации.

Расширение описывается так:

@extension(tagname, processname) {
//тут как обычная C++ структура
// в частности можно сделать конструктор и деструктор =)
};

@property instanceVariableName; // сгенерирует set/getInstanceVariableName
@receive T messageName(p1_t p1, p2_t p2) {
// implementation
@this->message1(p1); // куда же без self =)s
} // от определения функции отличается только словом @receive, и тем, что идентификатор - это произвольная строка до первой открывающей скобки.
...
@end(GlobalData) //@extesion(...)
/* GlobalData - указатель на void, через который можно передать нечто, доступное ( DataType *gd = (DataType *)@global; *gd->field; ) внутри любого экземпляра расширения.
Если ничего передавать не надо - можно писать просто @end*/

Приведённое транслируется в человекопонятный С++, точнее в обращения к системе сообщений и хэши с комментариями ( <большая страшная чиселка>/*original text*/ ). Всё абсолютно можно будет делать/звать и ручками. Каждое расширение может быть определено не более одного раза. Если в run-time нужно добавить функцию (например при импорте оной из скрипта), то сделать можно будет только обращением к системе сообщений. Расширения объявляются прямо в .cpp, .h не нужен, ибо для компилятора имена сообщений это просто хэши. Объекты плавают где-то в эфире, а мы оперируем лишь ссылками на них, в отместку они считают ссылки. В С++ вероятно умными указателями, при обращении из скрипта вероятно привязками, в самом низу - функциями системы. Будет интроспекция средствами вызовов соотв. подсистемы.
Поскольку оно лишь надстройка, то вполне допустимо писать С++ код рядом или совсем вперемешку. Есть 3 способа использования надстройки: 1) только как обёртку вокруг чего-то завершенного на С++, 2) писать всё, что уровнем выше только в таком стиле и 3) разумненько смешивать в примерно равных пропорциях. Ожидаете рекомендацию? - Её не будет! =)
Пожалуй пришло время какого-нибудь примера =)

@extension(mouse, logic) {
int x, y;
};
@property x;
@property y;
@property x,y; // так тоже можно =) но сгенерирует только set-функцию
@end

...

// где-то:
int x, y;

getMousePos(&x, &y);
@select(mouse)->setXY(x, y);

...
Object cursor; // это всего лишь ссылка на объект
@cursor += (mouse, renderable, mainCursor);
@cursor->setRenderType(SPRITE);
@cursor->setTexture("justCursor");
@cursor->setSizeXY(10, 10); // возможно будет синтаксис для посылки сразу многих сообщений
// Всё, мы сделали курсор.
...
// где-то ещё
Object cursor = @select(mainCursor).first;
@cursor += physicalObject;
@cursor->setMass(10);
@cursor->setShape(@physics->shapeBuilder().sphere(10)); // shapeBuilder() сообщение, которое возвращает обычный С++ объект, а так же типичный пример сообщения, которое не привязано к процессу
// После 4х строчек кода курсор становится способен к интеракции с игровым миром.



Ещё благодаря интроспекции оно замечательно экспортируется в скрипт, и замечательно сериализуется.

Теперь немного об идиомах которые я (кое где Илья поучаствовал) успел придумать. Во-первых в приведённом выше примере, можно было видеть присвоение уникального тега для однозначной идентификации, вместо того, чтобы как-то явно передавать ссылку на объект. Во-вторых у нас могут быть несколько ситуаций доступа к большим данным:
1) Данные большие, но нужны только в одном расширении. Очевидно не требует никаких доп. усилий
2) Данные нужны разным тегам/процессам/расширениям, но маленькими частями - сделать объект контролирующий данные.
3) Данные нужны всем и целиком - взять ответственность за синхронизацию на себя и добавить сообщение для прямого доступа.
В-третьих сервис теперь делается до невероятного просто:

@extension(cookieBringer, cookies) {
unsigned cookiesRemains;
@datum_constructor(): cookiesRemains(100) {}
};
@receive Cookie bringTheCookie!(void) {
return cookiesRemains > 0 ? --cookieRemains, Cookie() : NotfreshCookie();
}
@end
...
Object cookieBringer;
@cookieBringer += (cookieBringer, service);
...
@select(cookieBringer, service).first->bringTheCookie!();


Недораскрытой осталась тема использования для нашей задачи. Тут всё вроде бы просто. Система добавляет системные расширения и сервисы. Потом грузит поддвижки, которые просто С++ классы, те, в свою очередь, регистрируют необходимые расширения и создают свои сервисы. И понеслась. Про экспорт в скрипты и импорт оттуда я уже писал. Про потенциально возможные "толстые" данные тоже.

На данный момент вроде бы всё.

Реализация
Реализация состоит из нескольких частей: 1) microthreading framework, 2) object communication system, 3) syntatic sugar. Всех борцов с кодогеном прошу обратить внимание, на то, что собственно кодоген только в пункте 3) и это лишь сахар. Рассмотрим всё по порядку.
MTF вещица заслуживающая отдельного рассмотрения. Потому её здесь опишу лишь вкраце. Есть фиксированное количество потоков (пул потоков). У каждого потока один "вход" и один "выход". На вход подаётся очередное задание (одно). На выходе - очередь заданий, запрошенных потоком на выполнение. Задания помечены. Задания с одинаковой пометкой одновременно не выполняются. Есть "почтальон", он забирает из очереди каждого потока задания и передаёт дальше. А дальше система фильтров, в которую можно добавлять кастомные. Таким образом можно вмешаться в процесс диспетчеризации. Отфильтрованные задачи раздаёт освободившимся потокам планировщик. Как можно видеть, у каждой упомянутой очереди только один читатель и один писатель. Что позволяет реализовывать вставку при многих потоках с константной сложностью (если предварительно выделить память).
Поверх MTF выстраивается система взаимодействия объектов. Примерно так:

// Datatypes
typedef int32_t Idn;
typedef Idn Tag;
typedef Idn Process;
typedef Idn Object;
typedef Idn Message
typedef void * Data;
typedef ??? List; // list of Idns

typedef (void *) (*IMPL)(Object this, Data data, ...);
// Message sending
void *sendMessage(Object, Message, ...); // сложность примерно константа, если никто в момент вызова не регистрирует новый тип сообщения.

// могут пригодится при ручной оптимизации, так как, они будут просто возвращать скаляр, при условии если обработчик возвращает скаляр. Иначе падают по ассерту.
long sendMessage_l(/* ... */);
long long sendMessage_ll(/* ... */);
double sendMessage_d(/* ... */);
long double sendMessage_ld(/* ... */);

void sendMessage_(Object, Message, ...); // если нам глубоко плевать на результат. Самая быстрая в семействе =)
void sendMessage_list(List, Message, ...); // не возвращает ничего. Так всё таки будет сильно проще.

// Object manipulation
Object newObject(void);
void retainObject(Object);
void releaseObject(Object);

void addTag(Object, Tag);
void removeTag(Object, Tag);
void addTags(Object, List);
void removeTags(Object, List);

List selectObjects(Tag, ...) // list of tags must be null-terminated. If first param is 0, then return all objects.

// Extensions
int bindFunctionToExtension(Tag, Process, Message, IMPL, const char *argtypes); // argtypes - строка описывающая типы в сигнатуре
int bindDataToExtension(Tag, Process, void * data, size_t);

// Introspection
const char *getNameByIdn(Idn);
Idn getIdnByName(const char *name);
List getObjectTags(Object);
List getObjectMessages(Object);

Под капотом таблица тегов, таблица сообщений, таблица объектов. Таблицы при чтении не блокируются, если никто не пишет. Пищут только bind* фунции. Потому при ручной регистрации надо думать, когда её звать. Для С++ Object ещё сверху оборачивается в умные указатели, которые за нас ссылки посчитают. Где GlobalData? фтопку её, ибо можно через структуру передать.

Вот мы и подобрались к самому щекотливому вопросу =) Кодогенерация нужна для двух вещей - чтобы строить хэши (Idn) по строке в compile-time (не представляю как это можно на шаблонах, они со строками вроде совсем никак) и чтобы не мучить себя ручной регистрацией всего. Прописывать полный синтаксис до утверждения мне как-то страшно =) Ничего, чего бы я не показал в примерах из 2й части не будет.

@object->messageName(p1, p2);
sendMessage(object->value, /*messageName*/ p1, p2); // Выбор происходить будет только из 2 вариантов void *, void. На основе положения в тексте. Т.е. void будет выбран если ничего слева кроме табуляци нет, а предыдущая строка кончается ';' или '{' (+ ещё немножко случаев =) )

@select(tag1, tag2)->messageName(p1, p2);
sendMessage(selectObjects(/*tag1*/, /*tag2*/), /*messageName*/ p1, p2);

@object [+-]= ...
// Думаю очевидно =)

@extension(tag, process) {
// just structure defenition
@data_constructor(..)...
@data_destructor(..)...
}
@receive Type messageName(P1 p1, P1 p2) {
// ...
}
@end

struct STRUCT__tag__process {
// just structure defenition
STRUCT__tag__process(..)...
~STRUCT__tag__process(..)...
};

Type messageName_impl_tag_process(Object _thisobj, STRUCT__tag__process *data, P1 p1, P2 p1) {
// ...
}

@this
CppObject(_thisobj)
@data
data

// Да, типы переменных надо будет подсмотреть в структуре. Но фича не обязательная.
// Но как можно видеть экономит время
@property x;
@receive void setX(int aX) {
@data->x = aX;
}
@receive int getX(void) {
return @data->x;
}

@property y, z;
@receive void setYZ(int aY, int aZ) {
@data->y = aY;
@data->z = aZ;
}

Ещё тривиально генерируется отдельный .cpp файл, с вызовами функций регистрации, который потом надо будет просто инклуднуть.
Вроде бы даже всё =)

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

3) Резюме
Итак мы имеем масштабируемую систему (как на 2-8 так и на 20-80 ядер). Имеем удобную модель для описания взаимодействия внутриигровых сущностей. Имеем возможность быстро писать хорошо абстрагированный быстрый код и возможность незаметно интегрировать его с ещё более быстро написанным, хорошо абстрагированным, но менее быстрым кодом.
Из минусов лично я вижу только относительную небезопасность прямых вызовов руками. Но это издержки C/С++ Как раз это решается (если очень надо) обвешиванием шаблонами.

Маленькие Открытия

Музыка
Благодаря Last.fm нашел и подсел:

  1. Diablo Swing Orchestra
  2. Akphaezya
  3. Unexpect
Это всё авангардные металлы.

Посмотрел

  1. Зелёная Миля - отличненько.
  2. Avatar 3D - сюжет банален, но потрясающе сделанный мир. Оно того стоит.
  3. Досмотрел таки второй сезон Code Geass. No comments ;)
  4. Aoi Bungaku Series - аниме-экранизация японской классики. Очень хорошо. А на фоне, того шлака рядом с которым оно вышло, просто гениально =)
  5. Мой сосед тотторо - Миядзаки, этим всё сказано
  6. Какое-то блядски тупое гаремное онеме  про Красную ночь, человеокв - кусков и парня с золотым убер-глазом-стохастическим-анализатором. Пожалел потраченнное время.
  7. Человек Дождя - ох не зря оно в топе на кинопоиске.
  8. Властелин колец реж.версия. - круто, но вконец затянуто.
  9. Все умрут, а я останусь - быдло такое быдло. хуже треша лучше нет. шикарно.
  10. Школолололололо - посмотрел несколько серий. Примечательно то, что все до одного герои не вызывают ничего кроме отвращения, неподдельного. Камера а-ля "снмало школие на мобилу" решение сомнительное. Вначале казалось, что смотреть можно, потом осознал, что нельзя. Плохо, что во многом показанное правда (не во всех школах разумеется) .
  11. Черная летающая хуйня  - черная летающая хуйня. Русский спидер-мен бессмысленный и беспощадный.
 Играл

  1. Dead space - забавно поначалу, не осилил до конца, бо наскучило
  2. Overlord 2 - поначалу гениально (в первую часть не играл), потом заскучал.
  3. Thief 3 - запоем за 3-4 суток.
  4. Mass Effect - запоем за двое суток. Наверное хотел бы ещё разок. Подумываю о второй части.
    Что, характерно, там есть солнечная система, в которой всё названо в честь славянских богов
Софт
  1. Kupfer - аналог quicksilver. Много удобнее обычного окна выскакивающего по alt-f2
  2. Google Chrome - очень быстрый, годый броузер от сами знаете кого. Правда пока есть глюки. Но огнелис опасносте. 
  3. Redmine - вкусненький СУПчик