четверг, 2 июля 2009 г.

[life.humour] Сказано -- сделано

Отличная картинка:

Думаю, что надписи можно свободно заменить на “Начальник/Подчиненный” и “Заказчик/Исполнитель”.

Найдено тут: http://szymon.tumblr.com/

среда, 1 июля 2009 г.

[life] 256Kbps: хвала Белтелекому!

Прихожу сегодня вечером с работы, смотрю на скорость Интернета и закрадываются у меня смутные подозрения, что он работает в два раза быстрее. Неужели, думаю, свершилось? Неужели Белтелеком таки скорость увеличил? С робкой надеждой зашел на сайт byfly.by -- так и есть! С первого июля скорость на тарифах Домосед увеличилась вдвое при той же самой абоненской плате. Так что у меня теперь не 128, а целых 256Kbps!!! Почти полный бубль-гум! PS. Как мало оказывается нужно человеку для счастья... ;)

[comp] Похоже на бесполезно потраченное время

На RSDN появился совершенно загадочный пост Почему монады лучше lvalue (глобальных переменных) (написанное в нем я не понимаю до сих пор, буду признателен, если кто-нибудь его расшифрует). Для того, чтобы понять, о чем же там идет речь, пришлось обратился к первоисточнику: Programming Paradigms for Dummies: What Every Programmer Should Know.

Сегодня с утра я его таки дочитал. И кажется мне, что потраченное на его прочтение время было потрачено зря.

“Научный снобизм”, наверное, не совсем корректная характеристика. Но по ходу чтения я не мог отделаться от мысли, что автор говорит о программировании лишь с точки зрения академического ученого. Отсюда убежденность в непогрешимости функционального подхода. Ну и еще некоторые обобщения. Например, утверждение о том, что записи (record) являются одной из основополагающих концепций и через записи могут быть выведены остальные типы структур, такие как массивы, списки, строки, деревья, hash-таблицы. Или вот это:

Instantiation and genericity, normally associated with object-oriented programming, can be done easily by writing functions that return other functions. In object-oriented programming the first function is called “class” and the second is called an “object”.

Наверное, с точки зрения “высокой научной мысли”, так оно и есть. На практике, однако, удобнее пользоваться массивами и строками, как отдельными понятиями. И не считать, что класс – это функция, которая порождает функции-объекты. Лично мне это напоминает такой апофеоз обобщений, как “очередь с емкостью единица и выталкиванием старого значения при помещении в очередь нового значения” – вот так можно обозвать обычную переменную.

Но больше всего разочаровал пример с демонстрацией того, что наличие named state (т.е. переменных) улучшает модульность. Типа есть модуль, в котором есть функция F. Этим модулем пользуются программисты U1 и U2. Программисту U2 захотелось, чтобы модуль вел подсчет количества обращений к F. Что легко достигается посредством введения в модуль переменной-счетчика. Такое изменение не затрагивает программиста U1, поскольку интерфейс функции F не меняется.

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

Сухой остаток: статья не понравилась, понимания упомянутого выше поста thesz-а не прибавилось. Времени жалко.

вторник, 30 июня 2009 г.

[comp.concurrency] Совсем коротко о SCOOP

SCOOP, или Simple Concurrent Object-Oriented Programming, – это надстройка над языком Eiffel для конкурентного и распределенного программирования. Разговоры о SCOOP идут уже очень давно. В толмуде Бертрана Мейера об Eiffel SCOOP посвящена изрядная часть. Но до реальной эксплуатации SCOOP-а дело, как я понимаю, так и не дошло и в природе существует только его прототип.

Вспомнить о SCOOP меня заставила недавняя статья “SCOOP: Concurrent Programming Made Easy”. В ней дается короткий, но хороший обзор технологии SCOOP. И, самое важное, в ней был описан механизм дуэлей, о котором я раньше не слышал (или пропустил мимо ушей). Ниже следует очень свободный пересказ содержимого упомянутой статьи. Если кто-то заинтересуется подробностями – пожалуйста к первоисточнику :)

Итак, смысл SCOOP сводится к тому, что объекты разрешается распределять по процессам. Процессом может быть другая нить в том же приложении, другой процесс на этой же машине или же другой процесс на другой машине в сети. Для того, чтобы один процесс мог ссылаться на объекты в другом процессе, вводится новый тип ссылок – separate. Например, метод some_feature получает два аргумента: первый нормальный, а второй – ссылку на объект из другого процесса:

some_feature(a: LOCAL_TYPE; b: separate GLOBAL_TYPE) is
...
end

В принципе, ссылка на любой тип может быть объявлена как separate. Хотя не для всех типов это может иметь смысл. Можно так же описывать классы, помеченные как separate – это будет означать, что ссылки на такие классы будут автоматически считаться separate, а все объекты это типа будут т.н. separate object.

А дальше начинается особая SCOOP-овская магия :)

Все обращения к separate-объекту будут ставиться в FIFO-очередь. За этим будет следить среда исполнения Eiffel-SCOOP. Т.е. separate-объекты автоматически получают внутренний монитор (мутекс) и заботиться внутри separate-объекта о защите от многопоточного доступа к его данным не нужно.

Но для того, чтобы пользователь, владеющий ссылкой на separate-объект, мог обращаться к методам этого объекта, необходимо, чтобы это обращение было завернуто в метод, ссылка на separate-объект в который передается как аргумент. Проще всего это показать на примере. Пусть у нас есть некий класс:

class SAMPLE
feature
  -- Вот у нас ссылка на separate-объект.
  mailslot: separate MAILSLOT
  -- А вот в этом методе мы попытаемся обратиться
  -- к separate-объекту.
  produce_messages is
  do
    ...
    -- Это у нас не получится, поскольку mailslot
    -- не является агрументом produce_messages.
    mailslot.store (msg) -- ОШИБКА!
    -- Зато вот так можно.
    store_message (mailslot, msg)
  end
  -- Этот метод может обращаться к mailslot,
  -- поскольку он получает его в качестве аргумента.
  store_message(to: separate MAILSLOT,
    what: MSG) is
  do
    to.store (what)
   end
end

Такая политика связана с механизмом контроля за целостностью объектов в SCOOP. Поскольку SCOOP сам разруливает синхронизацию доступа к объектам, то ему нужно знать, в какой момент нужно захватывать монитор объекта. Таким моментом как раз является вызов метода, в который аргументом передается separate-объект. (Мой склероз может мне изменять, но мне кажется, что таким образом SCOOP может отслеживать вложенные вызовы функций с передачей того же самого объекта – он повторно уже не будет захватываться). Так же такая политика, по мнению разработчиков SCOOP, позволяет избегать тупиковых ситуаций.

Если SCOOP-процессы работают в рамках одного приложения, то обращение к separate-объекту будет происходить просто как вызов метода с необходимыми блокировками. Но если SCOOP-процессы разнесены по разным физическим процессам или даже узлам сети, то SCOOP берет на себя задачу создания proxy-объектов и маршалинг/демаршалинг вызовов.

А дальше начинается самое интересное. Ведь Eiffel – это язык, построенный на использовании Design By Contract. И оказывается, что в SCOOP контракты задействованы достаточно оригинальным образом. В частности, предусловия играют роль condition variable. Т.е. предикаты, которые записываются в секции require делятся на две категории: те, которые можно проверить немедленно и те, которые зависят от внешних условий. Например, приведенный выше метод store_message может быть записан с предусловиями:

store_message(to: separate MAILSLOT,
  what: MSG) is
require
  -- Это условие вычисляется сразу.
  mailslot_specified: to /= Void
  -- А вот это может проверяться неоднократно.
  mailslot_has_free_space: to.free_ceils > 0
do
  to.store (what)
end

Так вот, когда в программе произойдет вызов store_message, то среда исполнения проверит, что возвращает метод free_ceils у separate-объекта. И если это значение равно нулю, то значит предусловия не выполнены и нужно уснуть, пока они не будут выполнены.

Никаких condition variable в SCOOP не видно. Зато на предусловиях их можно имитировать. Не понятно правда, как сделать ожидание, ограниченное по времени (что-то типа cond_timedwait).

Еще одна черта SCOOP – распараллеливание вычислений. Тут, однако, нужно вспомнить про Command Query Separation Principle. Команда должна модифицировать состояние объекта, но не должна возвращать результата. А запрос не должен модифицировать объект, но должен возвращать результат. По сути, запрос должен быть функцией без побочных эффектов.

Итак, допустим, у нас есть ссылка на separate-объект A. Мы можем вызывать несколько команд у него. Это не может быть распараллелено, т.к. все команды будут поставлены в FIFO очередь объекта A. Аналогично и с запросами к объекту A.

Но вот если у нас есть ссылки на разные separate-объекты A, B и C, то обращения к ним могут распараллеливаться. Точкой синхронизации будет первое обращение с запросом к объекту. Например:

some_feature(
  a: separate A;
  b: separate B;
  c: separate C) is
do
  a.do_something
  b.do_something
  c.do_something
  -- Все три задействованные выше команды могут
  -- выполняться параллельно. Зато здесь произойдет
  -- синхронизация действий над объектами a и b.
  if a.result /= Void and b.result /= Void then
    -- До сих пор вычисления для c могли идти независимо.
    -- Но сейчас произойдет синхронизация.
    a.result.attach (c.result)
  end
end

А теперь пара слов о дуэлях (в упомянутой статье им уделено мало внимания, к сожалению). Итак, есть объект, который называется holder. Он владеет неким separate-объектом b, поскольку успел войти в какой-то свой метод r(b) (т.е. b передан в r как аргумент). И тут на арену выходит другой объект, называемый challenger, которому так же нужен объект b. Но объект b сейчас захвачен holder-ом и challenger-у нужно ожидать завершения r. Если же такое ожидание нежелательно, то можно применять дуэли.

Объект holder может использовать два специальных вызова: yeild (который говорит, что holder готов отдать владение объектом challenger-у) и retain (который говорит, что holder не желает отдавать владение). У объекта challenger-а есть набор из трех методов: demand (потребовать немедленное владение объектом), insist (попробовать получить владение объектом) и wait_turn (ожидать хода от holder-а). Поведение holder-а и challenger-а в этих условиях демонстрируется следующей таблицей:

 

wait_turn

demand

insist

retain

challenger ждетИсключение у challenger-аchallenger ждет

yeild

challenger ждетИсключение у holder-аИсключение у holder-а

Т.е., происходить может следующее. Объект holder захватывает какой-то объект и начинает длительную операцию. Где-то на ее середине holder понимает, что критически-важные действия, способные нарушить инварианты объектов, он уже выполнил. Поэтому, если кто-то нуждается в захваченном объекте, то holder может отдать ему владение. Для этого holder вызывает метод yeild. Если после этого challenger вызовет demand или insist, то challenger получит владение над объектом, а у holder-а возникнет исключение.

Если же holder не хочет отдавать владение объектом, то он вызывает retain (или ничего не вызывает, т.к. политика retain используется по умолчанию). И если challenger обращается к demand, то у holder-а ничего не происходит, зато у challenger-а выскакивает исключение. Если же challenger вызывает insist, то challenger засыпает до освобождения объекта.

Как я понимаю, механизм дуэлей нужен для использования SCOOP в real-time проектах. Тогда какой-нибудь низкоприоритетный holder сможет работать с неким важным объектом лишь до тех пор, пока не возникнет более высокоприоритетное событие, обработкой которого занимается challenger. Объект challenger вызывает demand, у holder-а выскакивает исключение, а chellenger получает в свое распоряжение нужный ему объект. Правда, я сомневаюсь, что разработка корректного кода с использованием дуэлей будет простой – уж очень внимательно нужно расставлять в коде retain/yeild и demand/insist. Да и получить в произвольный момент времени исключение, как следствие yeild/demand, хорошего мало, на мой взгляд.

понедельник, 29 июня 2009 г.

[comp; life] Позавидовал

Делать маршрутизацию и рассылку миллионов SMS – это, конечно, интересно. Но я бы с удовольствием попрограммировал бы начинку этих роботов…

воскресенье, 28 июня 2009 г.

[life.cinema] Ангелы и Демоны, Гран Торино и Пятница 13-е

Сегодня впечатления от “громких” фильмов.

Ангелы и Демоны

По ходу просмотра фильма возникали различные вопросы “почему” и “зачем”. Ну, например, почему в CERN-е при проведении серьезнейшего эксперимента оказался католический священник? Он, типа, не только продвинутый священник, но еще и выдающийся ученый? Какой смысл был давать в помощь главному герою женщину? Ведь никакой романтической линии между ними так и не возникло. Какой-нибудь тщедушный физик (типичный такой “ботаник”) в этой роли смотрелся бы, на мой взгляд, более естественно. Еще вопрос – есть ли в природе квантовые биофизики (если я правильно помню, именно такая специализация была у героини)? А то ведь не понятно, откуда она такая вся умная и грамотная – и физик, и медик, и батарейки в контейнере с антиматерией менять умеет, да еще и знает, кто такой Бернини ;)

Но финал всего этого фантастического действа подвела одна фраза. Которая меня лично убила на повал. Итак, почти в конце фильма главный злодей бежит к вертолету, чтобы в последние мгновения перед взрывом вывести взрывоопасный контейнер подальше от Ватикана. Выгоняет пилота вертолета и сам садится за штурвал. Все вокруг шумят, что-то кричат. И вдруг кто-то успокаивающим тоном произносит: “У него есть лицензия!” Мол, все нормально, за штурвал вертолета злодей садиться может и право поднимать машину в воздух имеет.

Ну ёпть, раз лицензия есть, значит может лететь. Иначе бы ему взлететь не позволили, ну никак. То, что остаются десятки секунд до пятикилонного взрыва – это все фигня. Ведь главное, чтобы лицензия пилота была!

В общем, туфта редкая. Но дорогая и качественно снятая. И если правда, что Том Хэнкс получил за эту роль 50 миллионов долларов, то остается только восхититься и сказать: “Ай Хэнкс, ай молодца!”

Гран Торино

Об этом фильме было много сказано на сайте Гоблина (он же и делал перевод этого фильма, но мне попался вариант, в котором текст читал не Гоблин). Еще до просмотра я читал в отзывах зрителей, что у фильма очень неожиданный финал…

В общем, с этим фильмом произошло полное несовпадение ожиданий и реальности. Я думал, что будет боевик, в котором Иствуд будет громить черных бандитов. Оказалось, что не черных, а азиатских. И не громить, а пытаться напугать. Чтобы затем принести себя в жертву и спасти тем самым своих новых друзей-соседей. Такие вот дела, ожидал крутой боевик, получил драму. Поэтому предупреждаю – это не боевик.

С неожиданным финалом так же не срослось. Как сейчас удобно говорить, “фильм был немного предсказуем” :) Где-то к середине фильма стало понятно, что герой Иствуда уже не жилец. И что его роскошный Гран Торино достанется пацану-азиату. Так оно и вышло. Хотя я думал, что героя Иствуда убьют бандиты в перестрелке уже после того, как он успеет замочить парочку-другую отморозков. Оказалось поинтереснее.

По ходу просмотра фильма складывается достаточно однозначное впечатление “Не верю”. Как-то все предсказуемо и стереотипно. Особенно неправдоподобными мне показались азиаты-бандиты. Все из себя такие крутые, а когда старикан их несколько раз обломал, они почему-то ничего с ним не сделали.

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

Пятница 13-е

Реанимированный после многих лет забвения один из самых забойных ужастиков моей молодости. Очень добротно снятое мочилово. Выключаешь мозги и наблюдаешь, насколько за последние 15-20 лет киноиндустрия продвинулась в съемке натуралистических эффектов.

Самое важное – мозги перед просмотром нужно выключать. Это фильм такой, чисто визуальный.

Неприятный осадок оставили последние кадры фильма, когда сброшенный в озеро труп Джейсона вдруг оживает, выскакивает из воды и хватает таки многострадальную главную героиню. Т.е. я понимаю, что авторам нужно было как-то дать себе возможность снять продолжение. Но все таки выключить собственные мозги до такой степени я не могу (в детстве получалось, сейчас нет). Ведь убили же Джейсона, убили. Даже трепанацию черепа дереводробильным станком сделали. А он все равно живее всех живых. Нет чтобы сделать так, чтобы Джейсон всех сам замочил и жив остался для следующих серий без волшебного воскрешения. Редиски, короче. Испортили “удовольствие” от просмотра :)