Интересные технические заметки по геймдеву
Кто-то знает где лучше искать качественный сабж?
Пример - DOOM 3 BFG Technical Note
http://fabiensanglard.net/doom3_documentation/index.php
Кто-то знает где лучше искать качественный сабж?
Пример - DOOM 3 BFG Technical Note
http://fabiensanglard.net/doom3_documentation/index.php
В дополнение к предыдущему посту о сферах применимости С++ и шедевральному посту об ооп (в данный момент продолжающегося обсуждением топологии Скотта).
(credits: гугля материалы о лиспе, случайно наткнулся на вот такой пост в ЖЖ, откуда я невозбранно изъял множество текста для написания этого сообщения.)
Итак, виновник торжества, этот пдф: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf
Автор С++, преподобный Страуструп, и команда отчаянных друзей-борщевиков пишут новую библиотеку для диспетчеризации по типам с помощью внешней интроспекции. Это либа, написанная на шаблонах С++x11, и называется Mach7 (почти как вот эти няшные автомобильчики)
Вот, собственно, что так хочет видеть в крестах сам преподобный Бьорн:
int eval (const Expr& e)
{
Match(e)
Case(const Value& x) return x.value;
Case(const Plus& x) return eval (x.e1)+eval(x.e2);
Case(const Minus& x) return eval(x.e1)−eval(x.e2);
Case(const Times& x) return eval(x.e1)∗eval(x.e2);
Case(const Divide& x) return eval(x.e1)/eval (x.e2);
EndMatch
}
В объектно-ориентированном языке без прямой поддержки алгебраических типов данных, тип, представляющий дерево выражения какого-то языка, обычно будет написан как абстрактный класс, с производными классами, реализующими более конкретные варианты.
struct Expr { virtual int eval () = 0; };
struct Value : Expr { ⋯ int eval (); int value ; };
struct Plus : Expr { ⋯ Expr& e1; Expr& e2; };
но более открытый (читай: расширяемый) дизайн заключается в другом:
По-настоящему открытые подходы опираются на дорогой тест на принадлежность к классу, комбинирующийся с деревьями решений.
Ну, то есть, хотим-то мы, наверное, как раз открытый подход, который подсмотрели из функционального программирования с его сопоставлением с образцом, но он слишком дорог с точки зрения CPU, если делать в лоб. Поэтому сделали Mach7, вот эту самую библиотеку на шаблонах, которая реализует открытый подход, но при этом не страдает по производительности, как если бы использовался тест на принадлежность к классу.
Насколько быстро теперь работает? Говорят, примерно как OCaml или Haskell:
Библиотека реализована как стандартный C++11 код с шаблонным мета-программированием и несколькими макросами. Оно работает примерно также быстро, как эквиваленты на OCaml или Haskell, и даже иногда приближается по быстродействию или даже становится быстрее написанного руками C++ кода, который использует Visitor дизайн-паттерн.
Ну это хорошо, что так быстро, как OCaml или Haskell. Вопрос, зачем при таком раскладе использовать C++, замнём для ясности.
Но дальше вообще прелесть идёт: критика паттерна Visitor!
Библиотека Mach7 и идеи в ней были мотивирована нашим неудовлетворительным опытом работы с различными C++-ными фронт-эндами и фреймворками для анализа программ. Проблема была не с самими фреймворками, но с фактом, что мы должны были использовать шаблон проектирования Visitor для того, чтобы смотреть, обходить и обогощать абстрактные синтаксические деревья целевых языков. Мы нашли Visitor-шаблоны неподходящими для прямого выражения логики приложения, удивительно сложными для обучения студентов, и часто более медленными, чем решения для обхода, написанные вручную. Вместо них, пользователи опирались на динамические приведения типов во многих местах, часто многоуровневые, таким образом предпочитая более короткий, более ясный, и более прямой код, нежели чем Visitor'ы. Соответствующий проигрыш в производительности был обычно незамечаем до более поздних стадий кодирования, когда уже было поздно что-то менять.
Ну можно поздравить C++, теперь можно на нём отдельные вещи писать почти так же коротко, ясно и почти так же быстро, как на OCaml.
В пдф по ссылке присутствуют графики сравнения перфоманса Хацкеля и Крестов, начертанные самим преподобным Бьорном, очень рекомендованные к просмотру для тех, кто еще не готов отречься от старых убеждений и перейти на новые.
Заметим, что не только Страуструп раскаялся в прошлом. Кармак с энтузиазмом рассказывает, как с головой погрузился в Haskell и Scheme, объясняет, почему хаскель невероятно крут и почему сегодня он бы, вероятно, сделал QuakeScheme вместо QuakeC. Он пишет на хаскеле порт wolf3D. (видео на ютубе — Quakecon 2013, обсуждение в толксах)
Пора задуматься о жизни, господа и дамы крестопоклонники.
Пичал я тут на днях токенайзел для C++-кода, но всё это меня добило я решил поделится.
Проблема - мне надо было вычислять сложные значения для таблицы в компилтайме, да можно на сишке сделать через жопу(енумы) и макросы, но мне стало лень. Да можно сгинерить, но мне тоже лень.
Шблонную магию плюсов я не люблю, ибо она ущербна чуть более, чем полностью и тут я вспомнил, что оказывается в плюсах хотели ввести компилтайм функции, аля constexpr и подумалось мне - во, плюсы затащат и как всегда я в очередной раз убедился в ущербности плюсов и так и не понял логики тех, кто это запилил.
Чтобы не быть голословным пишем что-то типа
constexpr uint64_t f(uint64_t a, uint64_t b) {
return a + b;
}
uint64_t m[] = {0, 1, 2, 3, 4};
constexpr uint64_t f(uint64_t a, uint64_t b) {
return m[a] + m[b];
}
Бида( или это моё неосиляторство плюсов?), дак зачем они запилили эту фичу, если она может лишь галимую примитивщину? Шаблоны ещё ущербней. В чем приемущество? Зачем?
А теперь у меня вопрос к вам, уважаемы батьки и отцы - что мне делать? Я хочу запонять массивы написав генератор, причем и в компилтайме тоже. Я хочу юзать libc, я хочу всё, а у меня нет ничего, почему?
Т.е. я не хочу каких-то макропроцессоров и скриптовых языков - я хочу, чтобы, если я написал constexpr - оно должно до последнего пытаться собрать то, что я написал и уже только тогда, когда оно реально это не сможет - отвалиться.
У меня есть 3 пути: терпеть, пилить свой язык и конпелятор самому( что долго и нудно) и ваш совет.
Подскажите какую книгу лучше прочитать дабы лучше понять язык C и устройство ЭВМ. Как работает компилятор, что делает препроцессор, что такое связывание, раннее, позднее, динамическое, символы. Как в ЭВМ происходит выделение памяти, что происходит при вызове функции.
Пытаюсь прояснить для себя работу динамических библиотек.
Сейчас мучаюсь над результатами следующего мысленного эксперемента.
Стартует приложение, слинкованное с so-библиотеками общим объемом 2 Гб. На машине есть хардварно 512 Мб ОЗУ и бесконечно большой swap (но он нам в конкретно этой задаче все равно не понадобится).
Код и const-данные из библиотек могут быть практически моментально выдавленны из физической ОЗУ в «swap». Т.к. они уже и так есть на диске в so-файлах, на самом деле в swap они помещаться не будут, страницы физической ОЗУ просто будут помечанны как свободные, а при необходимости код и данные из so-файла буду снова загружены в физическое ОЗУ. (или я тут где-то ошибаюсь?)
А теперь внимание, вопрос:
ОС (пусть для конкретики это будет linux) будет прогонять все эти код/данные через физическое ОЗУ -> «swap» или просто определит для себя, в каких страницах виртуальной памяти будет находится тот или иной код/данные и загрузит его в физическое ОЗУ при необходимости что-либо с этими код/даннные сделать?
В идеале ответ можно подкрепить ссылками на документацию или код загрузчика динамических библиотек.
При помощи технологии OpenGL и библиотеки GLUT вы можете ускорить процесс обработки изображений, используя всю мощь видеоадаптера вашей системы.
>>> Подробности
Как в программе на С++ перехватить исключение типа segmentation fault? Возможно ли это?
Всем спасибо.
//И если не в С++, то где возможно?
//ОС, конечно же, Linux.
Пытаюсь отладить приложение, которое падает до входа в main.
Приложение линкуется с кучей библиотек, которые были написаны разными людьми в разное время. Некоторые библиотеки слинкованы между собой.
Есть подозрение, что все это дело падает на инициализации какой-то static переменной класса, т.к. подобную ошибку когда-то в этих библиотеках уже находили.
В общем жду советов, как все это безобразие можно отладить или хотя бы детектировать ошибку. Желательно, чтобы способ ограничивался использованием gdb и утилит из стандартного набора GNU.
Update: Библиотеку в которой происходит падение вычислили. Теперь необходимо понять, где именно в этой библиотеке происходит падение.
Все (приложение и библиотеки) собрано с отладочной информацией.
Всем доброго времени суток! Решился попробовать что такое ассемблер но сталкнулся с такой проблемой что все книги которые находи заточены под MASM/TASM и под ОС MS-DOS И Windows. Существует ли адекватная русская литература по ассемблеру либо заточенная под пользователей linux ? или все таки стоит ставить на в виртуалку винду и штудировать на винде ассемблер ?
boost::filesystem::path::replace_extension не хочется городить.
по многопоточному программированию. Семафоры, барьеры, мутексы и пр. Кнута не предлагать. никогда раньше не писал многопоточных приложений, хочется введения в курс дела(с примерами). Желательно на великом и могучем, но не обязательно. Языки - кресты или питон.
Раз уже пятница то сабж. Вопрос не совсем праздный. сталкивался со сбоями оперативы когда проги на ровном месте сегфолтились, а вот после vm.drop_caches=3 всё работало нормально. Хочу запилить чексум и периодически его сверять. От порчи данных не поможет, да. Как и от 100500 других хардварных багов.
Наверно тут свои проблемы внесёт PIC, я в этом не силён. Но хотя бы после запуска проги содержимое кода меняться не должно, верно? При условии что линкер уже всё подгрузил.
Перемещено Dimez из talks
Можно из функции - члена класса в С++ вернуть итератор так чтобы сокрыть подробности внутренней реализации коллекции. Т.е. чтобы клиент не знал std::map там или std::vector?
Стало интересно, как принято оформлять группы функции, объединенные одной «тематикой». Что для этого больше подходит namespace или класс со статическими методами.
Следует учесть, что у функций есть несколько связанных с ними констант, как публичных, так и приватных.
Я пробовал оба способа, но так и не понял, что удобнее.
Может быть +/- этих подходов уже где-нибудь обсуждались?
Мне нужен класс таймера (будильника?) который срабатывает каждые N секунд. В описании ASIO я нашёл таймеры, которые разово срабатывают через указанный промежуток времени.
Можно, конечно, просто передёргивать их каждый раз, но тогда промежуток времени получиться чуточку больше. Мне, конечно, это некритично, просто хочу увидеть менее костыльное решение. Таймеры из Gtk+ и Qt, будэ таковые имеются, не подходят, потому что тянут за собой Gtk+ и Qt, нужно что-то более компактное.
Может я вообще не те слова ищу в описании? Может это по-английски не timer называется, а как-то по-другому?
Зачем нужны классы?
Глянул я исходники flare. Везде одни классы, да классы. Вот у меня в рогалике на данный момент нет ни одно класса. Везде обхожусь методами.
Может я чего то не понимаю? Зачем они нужны, если всегда вместо них можно обойтись методами? Да и в си их нету.
И использовать её в другом phoenix-выражении, передав в неё некие аргументы.
Этот вариант не компилируется.
#include <iostream>
#include <algorithm>
#include <boost/spirit/include/phoenix.hpp>
namespace ph = boost::phoenix;
namespace var = boost::phoenix::local_names;
namespace arg = boost::phoenix::arg_names;
template <typename T>
void foo (const T &t){
int i = 0;
int a[] = {1, 2, 3, 4};
std::for_each (a, a+4, ph::bind(&t, ph::ref(i), arg::arg1));
}
int main(){
foo (ph::ref(std::cout) << arg::arg1 << "\n");
}
Этот выводит 1 2 3 4 вместо ожидаемых нулей.
#include <iostream>
#include <algorithm>
#include <boost/spirit/include/phoenix.hpp>
namespace ph = boost::phoenix;
namespace var = boost::phoenix::local_names;
namespace arg = boost::phoenix::arg_names;
template <typename T>
void foo (const T &t){
int i = 0;
int a[] = {1, 2, 3, 4};
std::for_each (a, a+4, ph::lambda[t](ph::ref(i), arg::arg1));
}
int main(){
foo (ph::ref(std::cout) << arg::arg1 << "\n");
}
Все примеры игрушечные, но есть код, в котором это нужно.
Обнаружил тут, что если взять указатель на элемент std::vector, а потом сделать скажем push_back, то указатель начинает указывать на чушь.
Когда я с этим столкнулся, то понял из-за чего (скорее всего realloc какой-нибудь), вопрос не в этом. Вопрос в том: как ведут себя другие такие контейнеры (мапы, списки, очереди)? Платформозависимо ли это, или оговоренно в стандарте? Если второе, то прошу ткнуть носом. Спасибо.
В отдельном хидере определены 2 константы:
#ifndef STRINGS_H
#define STRINGS_H
const char * Started = "started";
const char * Stopped = "stopped";
#endif//STRINGS_H
#ifndef START_H
#define START_H
#include <cstdio>
#include "strings.hh"
void start()
{
puts( Started );
}
#endif
#ifndef STOP_H
#define STOP_H
#include <cstdio>
#include "strings.hh"
void stop()
{
puts( Stopped );
}
#endif
all:
g++ start.cc stop.cc 12.hh act.cc one.cc task1.cc two.cc Worker.cc act.hh Cat.hh Dog.hh Egg.hh Pet.hh start.hh stop.hh strings.hh Worker.hh Zoo.hh -o task1
Похоже на ситуацию, когда не ставишь проверку в начале хидера, и он включается несколько раз, но здесь это есть. М.б. надо сделать сборку объектов отдельно, потом уже из них общий бинарник? Или проблему следует искать всё-таки в коде?
PS: ошибка идет при включении хидеров со стартом и стопом. Задачу решить надо всё-таки мне, поэтому полностью использование приводить не буду. Но пока тупик, не понимаю даже в какой области ошибка
Понадобилось собрать пару плюсовых библиотек под андроид.
Скачал android-ndk-r7-crystax-5.beta2, ибо официальный NDK С++0х не умеет, а мне оно нужно.
Из проекта OpenCV спер android.toolchain.cmake
При попытке собрать пример из NDK все работает, но там исходники только на С, а мне нужен С++.
При компиляции срр получаю сообщение - «fatal error: thread: No such file or directory»
Чего оно хочет как-бы понятно. Проблема в том, что в ключах компилера только:
-isystem /opt/android-ndk-r7-crystax-5.beta2/platforms/android-8/arch-arm/usr/include
-isystem /opt/android-ndk-r7-crystax-5.beta2/sources/cxx-stl/gnu-libstdc++/include
Ну ясно дело, попробовал подокидывать путей для не найденых хидеров. Да что-то их сильно много. То c++config.h не находит, то wchar.h...
Может кто в курсе как оно вообще в gcc плюсовые библиотеки по каталогам раскиданы? Ну или какие пути захаркоджены в gcc для сборки на хосте?
следующие → |