Торжество высоких технологий

Мои предыдущие два поста были бы невозможны без скриншотов с телевизора.

Скриншоты я делаю так. Захожу на свой телевизор по ssh. И делаю следующее

export DISPLAY=:0.0
import -window root screen01.jpg

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

Что Вебер имеет сказать

Сразу после вчерашней аварии Вебер сделал заявление

Оказывается, высшим пилотажем ему заниматься не впервой. В 1999 году он умудрился дважды ухайдохать свой Мерс в Ле Мане. Требуйте на ю-тюбах вашего города

РедБул окрыляет!

Вебер сегодня в этом убедился

(more…)

Все совпадения случайны!

Вот тут сфотакл на днях:

Знаю, что цвета ненатуральные и горизонт завален, а шо делать?

Я видел, как Гендальф танцует!

Вчера ходили в Оперу. В Sydney Opera House на пьесу “Waiting for Godot”.

В роли Эстрагона – Ian McKellen, в миру известный как Гендальф, а среди любителей комиксов как Магнето.

Постановка просто отличная, игра актеров – восхитительная. Сказать, что понравилось – ничего не сказать. Боялись моргнуть и чего-нибудть пропустить. Пребываем в полнейшем восторге.

Представление, билеты на которые были, мягко говоря, нифига не дешевыми, стоит того до последнего цента. И даже больше.

P.S. А Годо так и не пришел.

Паттерн “observer” на tr1::function или почти настоящие делегаты

Про C++ делегаты на основе boost::function (tr1::function) я уже писал. В отличие от стандартного варианта обсервера для C++, который подразумевает фиксированный контракт (интерфейс) для подписчиков, вариант с функциональными объектами обладает определенными весомыми преимуществами (все они перечислены в посте по ссылке).

Но за удобство приходится платить. В данном случае расплачиваться приходится невозможностью реализовать отписку. И причина тому банально проста. Вот простейший пример

class Subject
{
   public:
       typedef std::tr1::function<void (const MyData&)> typeDelegate;

       void Subscribe(typeDelegate);
       void Unsubscribe(typeDelegate);
}

Реализация метода Subscribe() вопросов не вызывает. А вот с отпиской возникает проблема. В случае с классическим обсервером в оба метода передается голый указатель на интерфейс подписчика. А указатели можно сравнивать без хитростей, поэтому отписка превращается в банальное удаление элемента из контейнера.

Function сравнивать нельзя. В tr1 этот класс не определяет операторы сравнения, да и сама идея сравнивать функции в общем виде выглядит несколько нелепо. Идея подобного функционального объекта состоит в том, чтобы единожды его создав, скрыть его внутренности от всех остальных, при этом предоставив возможность создавать копии и выполнять как функцию с предопределенной сигнатурой. Эта идея не подразумевает возможности сравнивать, так как непонятно, что тут вообще можно сравнить. В бусте вроде пытались сделать оператор равенства для функций, но ничего хорошего из этого не вышло.

Отсутствие возможности сравнивать ставит жиирный такой знак вопроса на самой возможности отписки. Конечно, можно усложнить интерфейс субъектов и обязать подписчиков передавать какой-нибудь уникальный идентификатор при подписке и отписке. Таким идентификатором, например, может быть и указатель на подписчика, совсем как в классическом обсервере.

Делать так можно. Только это кривовато сразу по нескольким статьям. Поэтому нам нужно пойти другим путем.

Вышеозначенный делегат можно создавать динамически и заворачивать в умный указатель. А умные указатели уже можно сравнивать! Значит, получим

class Subject
{
   public:
       typedef std::tr1::function<void (const MyData&)> typeDelegate;
       typedef std::tr1::shared_ptr<typeDelegate> typeDelegatePtr;

       void Subscribe(typeDelegatePtr);
       void Unsubscribe(typeDelegatePtr);
}

Теперь, чтобы подписаться на события субъекта, подписчик должен сначала динамически создать объект типа typeDelegate, завернуть его в shared_ptr, а затем уже этот умный указатель использовать для подписки и отписки:

// Somewhere in subscriber's constructor, for example
Subject::typeDelegatePtr m_Delegate(
    new Subject::typeDelegate(bind(&Subscriber::Process, this, _1))
    );
//...
//   Subscribe for events on _pSubject
_pSubject->Subscribe(m_Delegate);
//
//
//   Unsubscribe from _pSubject
_pSubject->Unsubscribe(m_Delegate);

При этом реализация методов подписки и отписки субъекта становится очевидной, поэтому о них больше ни слова.

Как видно, если у объекта есть необходимость отписки, он должен сохранять оригинал делегата для этих целей. Если отписка не требуется (а такое бывает часто), локальная копия m_Delegate не нужна – временный экземпляр его можно будет создать при вызове Subscribe().

Можно еще сделать следующий финт ушами – слегка изменить интерфейсы и в субъект передавать не shared_ptr, а weak_ptr, образованный от оригинального умного указателя на делегат, который является членом класса-подписчика. При этом бесплатно решается проблема курицы и яйца: иногда требуется обеспечить, чтобы объект-подписчик автоматически отписывался при удалении, но никакой гарантии, что субъект еще жив, нет и быть не может. Достаточно лишь обеспечить, чтобы субъект проверял, не протухли ли “слабые” указатели (или делал им lock()) перед вызовом делегата, а подписчик владел оригинальным shared_ptr<typeDelegate>. При этом удаление подписчика будет вызывать инвалидацию всех инстанций weak_ptr, образованных от этого указателя, тем самым делая невозможным вызов убитого объекта через делегат, что и даст нам такую вожделенную возможность подписчика замести все свои следы даже без информации о том, на события каких объектов он подписан и живы ли они еще.

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

Политика, иттить

Все уже отписались, и я отпишусь.

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

Теперь у нас новый премьер-министр. Точнее, новая премьер-министр.

Вот такой вот разоруженный переворот.

Йандекс жжот

Почему-то с тындекса на мой уйутный бложек выходят в основном по запросу “шкаф гидропоника”.

Что бы это все значило?

Fuck the standards!

TR1 уже давно вышел. Это хорошо. Студия 2008 и 2010 уже включают его по умолчанию. Это просто отлично.

Стандарт (а TR1 – это де-факто уже стандарт) – это всегда хорошо. Больше нельзя называться C++ программистом и закатывать истерики при виде безобидного bind. Теперь нужно либо напрячь мозги и таки освоить основы функциональщины, либо идти заниматься гуевой мышевозней.

А еще стандарты – это плохо. Потому что любое, даже самое разумное и оправданное изменение стандарта превращается в процесс перемещения и горы и Магомета к единому стандартизированному месту встречи. И стандартно занимает до чертиков времени, да и других восполнимых и не очень ресурсов тоже дофига требует.

Вот включили они bind в стандарт. И чо (что, шо, So what, нужное подчеркнуть)? А перегруженные операторы не включили! Бо не было их еще в бусте на момент подачи черновиков в стандарт. В итоге в TR1 вот так вот не сделать:

vector<Person> myVector;
//
// Some stuff here
//
vector<Person>::iterator iter = find_if(
myVector.begin(),
myVector.end(),
bind(&Person::GetLastName, _1) == "Pupkin");

А все из-за того, что тот bind, что в TR1, не перегружает оператор “==”, сцуко такой! В итоге, чтобы сделать то же самое, что на куске кода вверху, нужно городить двухуровневый bind с equal_to посередине, от вида которого даже у привычных к boost пассажиров может случится истерика:

vector<Person>::iterator iter = find_if(
myVector.begin(),
myVector.end(),
bind(equal_to<string>, "Pupkin", bind(&Person::GetLastName, _1)));

Еще можно по-старинке взять и нарисовать функтор. На каждый подобный чих. В итоге от обилия их изжога начнется уже у меня.

Нинавижу.

А следующего стандарта еще 10 лет ждать.

Музыкальноэ

А Роджер-то наш Тейлор, оказывается, альбом выпускать надумал. Ждем “Unblinking eye (Everything is broken)”.

Старички жгут. И еще, в Англии явно что-то в воздух добавляют – музыка и прочий креатив оттудова так и прут.

11 visitors online now
11 guests, 0 members
Max visitors today: 15 at 09:10 am MST
This month: 23 at 05-03-2012 08:23 am MST
This year: 29 at 01-23-2012 02:50 am MST
All time: 45 at 02-23-2011 09:11 am MST