суббота, 30 октября 2010 г.

[life.cinema] Очередной кинообзор (2010/10)

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

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

Большое дело. Мне понравилось. Легкая и добрая криминальная комедия. Хотя я могу быть необъективным, поскольку смотрел этот фильм находясь в легком подпитии :)

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

Уолл Стрит: Деньги не спят. Обычная мелодрама. Да и финал какой-то слишком слащавый. Привлекает внимание только тем, что является продолжением отличного фильма Уолл-Стрит и темой недавнего глобального кризиса.

Не оглядывайся. Вроде бы сильная драма. И актрисы в главных ролях замечательные. Но в конце с перевоплощениями авторы явно переборщили и испортили все впечатление.

РЭД. В принципе, хороший комедийный боевик. Впечатление портит только возлюбленная главного героя. Ее играет 46-летняя актриса, поэтому не смотря на все усилия гримеров и операторов видно, что ей далеко за 30. Но исполняет при этом роль какой-то малолетней сентиментальной дурочки и весь фильм задаешься вопросом: "И что он в ней нашел?"

Генерал. Фильм 1998 года, но я посмотрел его впервые (и меня не покидает мысль, что на эту же тему я раньше смотрел фильм с Кевином Спейси – Обыкновенный преступник). В картине делается попытка показать известного ирладского преступника Мартина Кэхилла обычным человеком, который любит, страдает, боится, переживает. Что мне и не понравилось. Лучше бы показали человеческую сторону жертв его преступлений.

Обитель зла 4. Вполне себе ничего фильм – в духе предыдущих серий. Хотя я не в восторге. Мне больше понравились первая и третья части.

Американец. Снятая в духе соцреализма неспешная, скучная и малопонятная драма о суровых буднях обычного наемного киллера. Однако, фильм хорош тем, что в отличии от РЭД-у и Неудержимых показывает постоянное напряжение и страх у обычных наемников, а не у супергероев из комиксов.

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

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

пятница, 29 октября 2010 г.

[prog.thoughts] Подумалось о программировании для нового китайского суперкомпьютера…

В последние два дня идут разговоры о новом суперкомпьютере из Китая. Вчера услышал об этом в новостях по НТВ, а сегодня чуть более подробно прочитал на opennet.ru.

Впечатляет, конечно: 7168 графических процессоров NVIDIA Tesla M2050 и 14336 процессоров Intel Xeon. Вся эта байда потребляет 4.04 мегаватта (тогда тогда как предыдущий рекордсмен, Cray XT5 Jaguar потреблял порядка семи мегаватт).

Можно было бы, конечно, потрындеть о том, до чего дошел Китай… Но меня другое вставило – представил я, что это мне предстоит для него программы писать. Какой-нибудь расчет движения воздушных масс над Тихим Океаном, который будет идти часиков эдак пять-шесть, напрягая все имеющиеся в наличии 20K+ процессоров и потребляя по 4.04 мегаватта в час. Чтобы затем выяснить, что где-то в программе затесалась ошибка.

Представил я это себе… И не захотелось мне заниматься разработкой программ для таких суперкомпьютеров :)

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

[prog] Разработчики ACE заинтриговали – хотят выпустить ACE 6.0

Сегодня из рассылки ace-announce пришло письмо, в котором говорится, что ACE 5.0 вышла 31 июля 1999, и что спустя 11 лет самое время выпустить ACE 6.0. Что, собственно, разработчики ACE и собираются сделать в течении месяца.

Других подробностей пока нет, поэтому новость получается интригующей. Означает ли это, что в ACE 6.0 грядут какие-то серьезные изменения (например, более серьезное использование C++ных возможностей, в частности, исключений)? Или же это будет тот же самый ACE 5.8.*, но уже под новым именем?

Лично я уже довольно долго придерживаюсь мнения, что мажорный номер версии проекта нужно менять только при его кардинальной переделке. Т.е. когда новая реализация практически не совместима со старой. Поэтому такое громкое обещание несколько меня тревожит. Однако, кажется мне, что не будет в ACE 6.0 ничего революционного.

В общем, будем посмотреть. Но пока заинтриговали :)

четверг, 28 октября 2010 г.

[prog] Вышла версия 5.8.3 библиотеки ACE

Вышла очередная версия библиотеки ACE – 5.8.3. Из основных изменений:

  • в класс ACE_Pipe добавлены методы close_read() и close_write(), чтобы закрывать только один из каналов;
  • на платформах, где есть poll() теперь семейство функций ACE::handle_ready() теперь использует poll() вместо select(). Раньше такая штука включалась посредством макроса ACE_HAS_LIMITED_SELECT, но теперь этого макроса нет, а использование poll() происходит при наличии ACE_HAS_POLL;
  • добавлена простая вспомогательная функция ACE::is_equal(), которая выполняет сравнение двух объектов без использования operator==();
  • из ACE удалены методы, аргументы, классы, функции, макросы, файлы, которые в течении длительного времени были помечены как deprecated;
  • удалена поддержка платформ Irix/Tru64/SCO/Uniware/Cray;
  • удален класс ACE_Pair, теперь должен использоваться стандартный std::pair;
  • плюс еще ряд багфиксов.

Заявлено, что это последний релиз ACE, который работает с GCC версий до 3.0.0. В следующих версиях ACE поддержки столь древних версий GCC уже не будет.

В общем, какой-то серьезный релиз.

Скачать эту версию можно отсюда: http://download.dre.vanderbilt.edu/previous_versions/

среда, 27 октября 2010 г.

[prog.flame] Java под Mac OS X is deprecated: еще один шаг к превращению Java в COBOL XXI-го века?

Да простят меня приверженцы Java, но будучи любителем побросать камешки в Java-огород, я не могу не позлорадствовать на дошедшие и до меня новости:

As of the release of Java for Mac OS X 10.6 Update 3, the version of Java that is ported by Apple, and that ships with Mac OS X, is deprecated.

This means that the Apple-produced runtime will not be maintained at the same level, and may be removed from future versions of Mac OS X. The Java runtime shipping in Mac OS X 10.6 Snow Leopard, and Mac OS X 10.5 Leopard, will continue to be supported and maintained through the standard support cycles of those products.

Т.е. Apple прекращает разработку и развитие собственного порта Java для своих Mac OS X. И, возможно, вообще выкинет Java из Mac OS X в будущем (хотя то, что вошло в версии Snow Leopard и Leopard будет сопровождаться согласно стандартному жизненному циклу).

В другом месте при обсуждении этого же события упоминают еще один фактор. Дело в том, что в Mac App Store не должны приниматься программы, которые зависят от устаревших технологий. И, поскольку Java объявлена устаревшей, то и Java приложения могут перестать принимать в Mac App Store.

Я не маркетолог и вообще далекий от бизнеса человек, но как по мне, так все выглядит довольно разумно. Apple за счет Mac OS и iOS (iPhone и iPad) создает собственный рынок программного обеспечения. И так уж повелось, что для данных платформ основным инструментом является Objective-C (а так же, по совместительству, еще и C с C++). Нужно вспомнить еще и про недавние расширения языков C-шной группы от Apple: туда были добавлены блоки кода. Т.е. Apple планомерно и непрерывно сажает разработчиков на собственную иглу. Ведь Apple должно быть выгодно, чтобы софт изначально затачивался под Mac OS/iOS и не был бы кроссплатформенным.

Итак, что получается. Хороших desktop-ных приложений на Java не так уж и много. Смысла писать Windows-only приложения на Java нет, т.к. для этих целей .NET подходит гораздо лучше (имхо, конечно). Смысла писать Mac OS-овские приложения на Java уже нет. Что остается? Большой и жирный сегмент Ынтырпрайза, где у Java уже давно очень и очень мощные позиции. Там она, похоже, и обречена оставаться. А это означает (да еще с ее темпами развития), что Java идет по пути COBOL-а.

Впрочем, для нынешних Java-разработчиков это, скорее, даже хорошие новости. Ведь тот же COBOL очень даже жив и каждый год на нем пишется огромное количество кода. А на Java, вероятно, уже написано намного больше. Так что без работы хорошие Java-программисты точно не останутся. А вот нужно ли сейчас Java изучать молодежи – вот это вопрос не праздный, имхо. Мы в свое время ни про COBOL, ни про FORTRAN, ни про PL/1 даже слышать не хотели :)

PS. Кстати, эти новости об Apple и Java прокомментировал и Джеймс Гослинг. Он сказал, что Apple сделала для Java чуть ли не больше “секретных API”, чем в свое время Microsoft. И что одной из причин этого был Oracle, который уж очень хотел, чтобы в JVM на Apple-овских системах была графика без сглаживания, как и под Windows.

вторник, 26 октября 2010 г.

[prog.flame] Впечатления от Go-шных defer, panic и recover

Фактически, это продолжение спора, завязавшегося в комментариях к заметке “Почему я не использую языки D и Go”. Прочитал о таких механизмах языка Go, как defer, panic и recover (ссылка #1 на блог разработчиков языка Go, ссылка #2 на Effective Go). Поскольку на Go я не программировал, то буду рассказывать то, что я понял. А это может быть совсем не то, что есть в действительности ;)

Итак, что же такое defer, panic и recover в Go и зачем они там? Ключевое слово defer позволяет зарегистрировать вызов функции, который должен быть сделан автоматически при выходе из текущей функции. Например, пусть мы открываем файл и должны гарантировать его закрытие при выходе из функции. Механизм defer позволяет нам это сделать просто и элегантно:

file, err := os.Open(filename, os.O_RDONLY, 0)
if err != nil {
   // Какая-то ошибка...
   // Обрабатываем ее и уходим.
   return err
}
// Ошибок нет, файл должен быть закрыт.
defer file.Close() // Теперь файл автоматически будет закрыт.

Если в текущей функции сделано несколько обращений к defer, то зарегистрированные отложенные вызовы будут произведены в обратном порядке (по аналогии с тем, как в C++ происходят вызовы деструкторов объектов). Собственно и назначение defer аналогично деструкторам C++ – очистка ресурсов.

Но, в отличии от деструкторов C++, отложенные функции в Go могут изменять возвращаемое значение той функции, в которой был зарегистрирован их отложенный вызов. Например:

func sample() (res int) {
   defer func() {
      res = 1
   }()

   return 0
}

Если вызывать sample(), то вернет она 1, а не 0, т.к. возвращаемое значение замещается в отложенной функции. Сделано это для того, чтобы можно было управлять возвращаемым значением в случае panic-ов.

Конструкция panic прерывает выполнение текущей функции и начинает “раскрутку стека”. В этом процессе вызываются лишь все зарегистрированные через defer функции (т.е. программисту дается возможность очистить ресурсы). Если процесс раскрутки стека доходит до корня текущей goroutine, то приложение аварийно завершается.

Но, в случаях, когда приложение может восстановиться после сбоя, возникший panic можно перехватить с помощью инструкции recover. Вызывать ее имеет смысл лишь в отложенных функциях. Если recover возвращает nil, то раскрутка стека сейчас не выполняется. Но если recover возвратила отличное от nil значение, значит сейчас идет раскрутка стека в результате panic. И возвратила recover как раз объект, переданный в panic. Например:

func openAndReadFileContent() (content string, err os.Error) {
   // Регистрируем отложенную функцию, которая все panic-и
   // будет преобразовывать в отрицательный ответ (если паника
   // была вызвана os.Error).
   defer func() {
      if r := recover(); r != nil {
         err = r.(os.Error) // Это, на самом-то деле, хитрая строка.
      }
   }

   file, err := os.Open(someFileName, os.O_RDONLY, 0)
   if err != nil {
      return nil, err
   }
   defer file.Close()

   content := readAndParseFileContent(file)

   return content, nil
}

func readAndParseFileContent(file File) string {
   // Выполнение чтение исодержимого файла и при каждой
   // ошибке порождение паники.
   rawContent, err := ioutil.ReadAll(file)
   if err != nil {
      panic(err)
   }
   ... // Преобразование прочитанного содержимого.
}

Здесь в начале функции openAndReadFileContent регистрируется отложенная функция, которая преобразует панику в обычное возвращаемое значение. Что позволяет писать саму функцию openAndReadFileContent (и все подчиненные ей функции) так, чтобы инициировать панику в любых ситуациях, когда что-то идет не так.

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

Лично мне кажется, что обычные исключения все-таки лучше.

Во-первых, в Go исповедуется стиль с возвращением ошибок. Т.е. код будет пестреть if-ами с последующими return-ами. Такой стиль увеличивает объем кода и усложняет его восприятие. Но самое важное, он череват опасностью забыть написать if и, тем самым, проглотить ошибку.

Отсюда вытекает и во-вторых. А именно: вот когда разработчику использовать коды ошибок, а когда panic? Если язык программирования изначально поддерживает исключения (скажем, как Ruby), то там все просто – все библиотеки кидают исключения и ты сам пишешь в том же духе. А что здесь?

В-третьих, если все-таки panic-и начинают использоваться как исключения (например, в блоге разработчиков Go советуют посмотреть, как этот прием используется в модуле разбора JSON-а), то получается, что разработчик пишет свой аналог catch (через отложенную функцию с обращением к recover). Но если в языках с исключениями (вроде C++, Java, C#, Python, Ruby и в том же Erlang-е) это намерение разработчика явно декларируется специальной языковой конструкцией try-catсh вокруг проблемного кода, то в Go все это дело уводится в отложенный вызов (который далеко не всегда будет лямбда-функцией). Что не есть хорошо.

В-четверных, в языках с исключениями принято делать иерархии исключений. А конструкции catch позволяют ловить исключения как по конкретным классам, так и по целым семействам исключений. Причем делается это, опять же, посредством специального синтаксиса. Скажем, если я использую библиотеку для шифрования, у которой корнем иерархии исключений является класс CryptoError, то я могу легко записать перехват только этих исключений и игнорирование всех остальных. А вот в Go подобные иерархии, в принципе, можно выстраивать, но потом определение типа ошибки нужно будет писать вручную:

func (d *decodeState) unmarshal(v interface{}) (err os.Error) {
    defer func() {
        if r := recover(); r != nil {
            if _, ok := r.(runtime.Error); ok {
                panic(r)
            }
            err = r.(os.Error)
        }
    }()

Здесь ошибку поймали, проверили, принадлежит ли оно семейству runtime.Error. Если принадлежит, то пробросили эту ошибку дальше (посредством еще одного вызова panic). А если это не runtime.Error, то считается, что это os.Error и именно os.Error возвращается.

Как по мне, так запись (это язык Ruby):

begin
  doSomething
rescue OsError => x
  return x
end

представляется более простой, компактной и надежной.

Так что я бы предпочел иметь обычные исключения, а не Go-шные panic и recover-у. Ну, а аналог defer-а есть в том же D в виде конструкций scope(exit). Да еще и более гибкий, имхо.

PS. Кстати, на счет очень хитрой сроки err=r.(os.Error). Хитрость ее заключается в том, что это приведение типа. И если r не принадлежит типу os.Error то будет сгенерирована новая паника (это если я правильно понял документацию). Так что в связи с этим последний пример с функцией unmarshal (взятый как раз из модуля декодирования JSON-а) не кажется мне надежным.

понедельник, 25 октября 2010 г.

[prog.flame] И за это я тоже не люблю С++

Несколько раз за мою бытность C++ником происходили случаи, когда мои C++ные программы падали, а я не мог объяснить причины этого. Причем всегда это было связано с Visual C++ компиляторами. Вспоминаются следующие случаи.

В первый раз это было где-то в 1998-м, когда я под VC++ 4.2 тестировал свою собственную объектную СУБД. Сервер БД падал, когда к нему несколько раз подключались, активно работали, а потом отключались клиенты. Падал в достаточно произвольные моменты. В принципе, я смог выстроить цепочку действий, которая гарантировано ломала сервер, но произойти это могло как через 5 минут, так и через 15 минут работы.

Долго я тогда искал причины проблемы, наверное дня три сидел за машиной с утра до вечера. И ничего не мог найти, да и тот же самый сервер под OS/2 работал вообще без проблем. В результате все закончилось тем, что в одном из мест программы я заменил один свой самописный контейнер на другой – программа падать перестала.

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

Пользовались мы тогда VC++ 6.0. Пару дней я убил чтобы проблему найти, благо машина заказчика тогда у нас стояла. Ничего не нашел. Просто перекомпилировал приложение VC++ 7.1 – зависать перестало. И под MinGW так же не зависало. Такой эффект только под VC++ 6.0 проявлялся.

С VC++ 9.0 (это который из VS2008) недавно прикол был. Компилирую маленькую утилитку, в которой библиотека TCLAP используется. Запускаю без аргументов (чтобы выдачу справки спровоцировать) из FAR-а или Cygwin-овского bash-а – падает. Если тоже самое из cmd.exe – не падает. На машине разработчика вообще не падает. Пытаешься отлаживаться – отладчик ничего путного не говорит. Перешли на новую версию TCLAP, таких приколов больше не наблюдается. Если же компилироваться VC++ 7.1, то вообще никогда не падает.

А вот последний случай произошел на прошлой неделе. Потребовалось доработать приложение, которое некоторое время назад было переведено с VC++ 7.1 на VC++ 9.0. Доработал. Стало эпизодически падать.

В Release режиме падает. В Debug нет. Если скомпилировать в Release с PDB, то падает. Но студийный отладчик не может показать нормального stack trace. Т.е. даже вообще ничего не показывает, из какого места нашего кода мы оказались в MS-овской DLL-ке – фиг его знает. Как искать причину, ведь явно место сбоя – это уже последствия какой-то наведенной ошибки, а где ее причина… Ничего не понять.

Опыт подсказывает, что вероятность моей собственной ошибки гораздо больше, чем ошибки где-то в компиляторе. Но опыта не хватает, чтобы проблему выявить. Проект-то очень не маленький, плюс сторонних библиотек в нем достаточно (одни только ACE с POCO и OTL чего стоят). Тем более, что под VC++ 7.1 все работает как часы. И так хочется верить, что это глючит оптимизатор в проклятой мастдаевской мелкомягкой поделке! :)))

Блин, не люблю я C++ за такие вещи. Убиваешь время на пустом месте. Жалко, что я в свое время поиск замены C++ так и не закончил. Хочется временами чего-нибудь железобетонного, чтобы не то что ногу отстрелить, чтобы даже прицелиться в нее нельзя было :)))

воскресенье, 24 октября 2010 г.

[life.sport.darts] Во что превращается мишень для дартс…

…после почти четырех месяцев ежедневных тренировок.

Ниже фотографии двух сизалевых мишеней китайского производителя под именем Forfi с толстой круглой разделительной проволокой. Слева новая, только сегодня распакованная. А справа та, на которой я тренировался дома с июля.

[life.photo] О фотоконкурсе Nikon Small World 2010

Сегодня в рубрике “Знакомство с фотомастером” будет ссылка на галерею фотографий лауреатов конкурса Nikon Small World 2010. Оказывается, с 1974-го года компания Nikon проводит конкурс фотографий, сделанных через микроскоп. Эти фотографии, как правило, выполняются учеными во время проведения серьезных исследований. Но иногда их снимки оказываются удивительно красивыми. Под катом несколько снимков, которые понравились лично мне (они взяты отсюда).