пятница, 23 января 2009 г.

DjangoCon 2008: GeoDjango

http://www.youtube.com/watch?v=zOaimbSe6n8

Отличная презентация системы GeoDjango. Вводит вас в базовые понятия и архитектуру системы.


Слайды для презентации:

http://geodjango.org/presentations/GeoDjango%20-%20A%20world-class%20Geographic%20Web%20Framework%20(DjangoCon%20-%20Sept.%206,%202008).pdf

  • OpenLayers
  • KML GML WKT GeoJSON GeoRSS

четверг, 22 января 2009 г.

C++ exception handlers

В любом объектом языке должны выполнятся несколько правил позволяющие создавать понятные и проыстые логические конструкции.

Среди этих правил есть: однозначное создание\инициализация объекта и его удаление\деинициализация. Кроме того, должна быть эффективная система обработки ошибок, позволяющая в любой момент прерывать исполнение и передавать работу контролееру за исключительными ситуациями: обработчику исключений. Теперь самое главное правило - любой объектный язык должен эффективно совмещать эти правила вместе. Правильно, я говорю про исключения в конструкторе.

Любой опытный разработчик знает о том, что в С++ нельзя бросать исключения в конструкторе и это приводит к ужасным последствиям, я постораюсь объяснить почему.

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

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

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

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

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

class My
{
  int i;
  int *k;
  int *j;

public:
  My ()
  {
    i = 0;
    k = new int[5];
    throw exception();
    j = new int[5];
  }
  ~My ()
  {
    fprint("%x\n",i);
    fprint("%x\n",k);
    fprint("%x\n",j);
    delete k;
    delete j;
  }
};

int main(int c, const char** a)
{
  try
  {
    int k = 0;
    {
       My m;
    } // в этом месте мог бы быть вызван деструктор класса m. Но так как память m была не инициализированна этого не происходит.
      // хочу обратить внимание, что если бы до класса My m стоял бы другой успешно инициализированный класс, его дестркуртор был бы вызван
  }catch(std::exception &e)
  {
    // solve it
  }
  return 0;
};


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

class My2
{
  int i;
  MyNormal m;
  My m;

  My2() try
  {
    // body constructor
  } catch(std::exception &e)
  {
     // solve it
  }
};

В этом случае я часто встречаю решение данной проблеммы - игнорирование исключений. Разработчики вставляют конструкцию try/catch в тело конструктора и любые исключительные ситуации отправляют в системный журнал - это крайне не допустимо! В использовать журналирование - означает игнорировать ошибку и создавать класс не инициализированный, не пригодный для использования, что порождает ошибку второго уровня. Это в свою очередь опять таки не допустимо.



Вывод:
Из всего вышесказанного я делаю вывод, что в С++ нельзя инициализировать класс в его конструкторе, нельзя использовать локальные переменные состоящие не из простых типов и указателей (тоже простой тип), так как это в ряде случаев приводит к серезным ошибкам. Следовательно - С++ не объектный язык :)

Для того чтобы писать на С++ вам необходимо проработать с языком не меньше 5 лет и узнать обо всех тонкостях, выработать и научится хорошему стилю программирования и исключать из своих разработок код привиденный выше.

вторник, 20 января 2009 г.

Microsoft come to linux!!!

Check this out:

Ctrl+F "Linux"


Operating System Windows Internet Explorer 7 Internet Explorer 6 Firefox 1.5, 2, 3 Safari
Windows Vista
Windows Server 2008
Windows 7 (beta)
Yes - Yes -
Windows XP SP2 Yes Yes Yes -
Windows 2000 SP4 + all post-SP4 hotfixes, updates, and security updates - Yes** - -
Windows Server 2003 (excluding IA-64) Yes Yes Yes -
Mac OS 10.4.8+ (PowerPC) - - Yes* Yes*
Mac OS 10.4.8+ (Intel-based) - - Yes Yes
Linux, FreeBSD or SolarisOS Various browsers. For details, see Novell.

Opensource webmail services

Выбор есть:

Источник:

Red Devil Dance!

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

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

http://en.wikipedia.org/wiki/ESP_Game

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


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


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


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


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


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


Для этого необходимо использовать стандартную игровую модель, каких существует уже сотни - MMORG. Каждый участник радио-сообщества может создавать своего персонажа, с изображением \ 3д моделью. У персонажа есть лимитировано количество points, которые необходимо распределить между понравившимся композициями\направлениями.



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



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



Таким образом мы добиваемся, что участник ассоциирует с имиджем виртуального персонажа (аватором или его моделью) музыкальное направление, которое нравится этому виртуальном персонажу, а не просто лепит композиции. Это позволяет нам заинтересовать участника уделять гораздо больше внимания той информации, которую он пытается ассоциировать с персонажем . После того как персонаж дошел до 100 очков его развитие прекращается, и участник должен создать нового персонажа. Это позволит избавиться от эволюционирования вкусов участника.


После создания персонажа он автоматически становится доступным для просмотра другими участниками сообщества. И как не трудно догадаться представляет из себя простую радио станцию :) У которой есть свои очки: постоянные слушатели, общее число прослушиваний и текущий онлайн.


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


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


Это вкратце, что касается игры. Теперь как на этом заработать.


Да в прочем вы сами поняли:


- продажа музыкальных композиций
- продажа аваторов
- продажа анимаций
- продажа постановок
- создание реальных вечеринок.


Вы спросите меня почему это будет работать? Очень просто: люди которые приходят слушать музыку будут получать именно то, что они хотят. Те кто приходят с серьезными намерениями и надолго - создадут хорошую базу по музыке и репутацию себе как диджею. Прибыль же получить будет можно и с тех и других.

Ссылки по теме:

суббота, 17 января 2009 г.

apple vs microsoft

1. http://www.google.com/search?q=site%3Aapple.com+linux
 Results 1 - 10 of about 118,000 from apple.com for linux. (0.22 seconds) 

2. http://www.google.com/search?q=site%3Amicrosoft.com+linux
 Results 1 - 10 of about 201,000 from microsoft.com for linux. (0.15 seconds)


3. http://www.google.com/search?q=site%3Anovell.com+linux
 Results 1 - 10 of about 259,000 from novell.com for linux. (0.32 seconds)

4. http://www.google.com/search?q=site%3Agoogle.com+linux
 Results 1 - 10 of about 437,000 from google.com for linux. (0.18 seconds)

5. http://www.google.ru/search?q=site%3Asun.com+linux
 Results 1 - 10 of about 472,000 from sun.com for linux. (0.19 seconds)

6. http://www.google.com/search?q=site%3Aibm.com+linux
 Results 1 - 10 of about 943,000 from ibm.com for linux. (0.23 seconds)


linux sponsor.org:
http://www.google.ru/search?q=site%3Amozilla.org+linux
 Results 1 - 10 of about 3,070,000 from mozilla.org for linux. (0.28 seconds)


http://www.google.ru/search?q=site%3Ablog.axet.ru+linux
Результаты: 1 - 10 из приблизительно 317 из домена blog.axet.ru для linux. (0,34 секунд)

Keyboard mapping continue...

Обновление дистрибутива Федора9 до Федора 10 дало продолжение истории с преобразованием global keybinding событий от клавиатуры.

В новой версии Федора 10 изменена вся система ввода\вывода и переведена на использование hal. Это безусловно очень серьезный шаг к созданию гибкой системы с автоматической настройкой любых устройств ввода\вывода. В результате этих изменений получилось полностью отказаться от использования конфигурационного файла xorg.conf, и перейти на определение устройств на лету.

Я напомню читателям, о чем шла речь:я изучал проблему маппинга клавиш на своем ноутбуке начиная с Федора 9. Проблема заключалась в том, что используя стандартный механизм маппинга клавиш не позволял переопределять специальные клавиши такие как Windows Key и Print Src, новые значения игнорировались системой.

В новой версии Федора 10 была полностью изменена работа с устройствами ввода, в результате таких преобразований ошибка с global keybinding стала проявляться еще сильней. Так как новый дистрибутив полностью отказался от старой модели с событиями от клавиатуры посредством xkb, это позволяет нам перейти к поиску проблемы непосредственно в x window system.

Помимо X11, проблема может находится в обработчиках и обертках window managers. Анализ содержимого файлов gconf позволяет найти еще две критичные точки, это gnome и metacity.

gconftool-2 -g /apps/metacity/general/mouse_button_modifier

gconftool-2 -g /apps/panel/global/screenshot_key
gconftool-2 -g /apps/panel/global/window_screenshot_key

gconftool-2 -g /apps/metacity/global_keybindings/run_command_screenshot
gconftool-2 -g /apps/metacity/global_keybindings/run_command_window_screenshot

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

Функции: window managers keybinding:
- metacity
- gnome

Функции: передача событий, отслеживание глобальных keybinding, механизм xmodmap
- x11

Функции: чтение событий с устройства
- evdev
- kbd/xkb
- hal

Для справки, я привожу новые коды xev log для Fedora 10:

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24266678, (1005,395), root:(1008,440),
    state 0x0, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24266741, (1005,395), root:(1008,440),
    state 0x8, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24266869, (1005,395), root:(1008,440),
    state 0x0, keycode 133 (keysym 0xffeb, Super_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24266917, (1005,395), root:(1008,440),
    state 0x40, keycode 133 (keysym 0xffeb, Super_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24267597, (1005,395), root:(1008,440),
    state 0x0, keycode 134 (keysym 0xffec, Super_R), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24267661, (1005,395), root:(1008,440),
    state 0x40, keycode 134 (keysym 0xffec, Super_R), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24267797, (1005,395), root:(1008,440),
    state 0x0, keycode 104 (keysym 0xff8d, KP_Enter), same_screen YES,
"   XLookupString gives 1 bytes: (0d) "
"   XmbLookupString gives 1 bytes: (0d) "
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 24267862, (1005,395), root:(1008,440),
    state 0x0, keycode 104 (keysym 0xff8d, KP_Enter), same_screen YES,
"   XLookupString gives 1 bytes: (0d) "
    XFilterEvent returns: False

MappingNotify event, serial 30, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 248

MappingNotify event, serial 30, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 247

FocusOut event, serial 30, synthetic NO, window 0x4a00001,
    mode NotifyGrab, detail NotifyAncestor

FocusIn event, serial 32, synthetic NO, window 0x4a00001,
    mode NotifyUngrab, detail NotifyAncestor

KeymapNotify event, serial 32, synthetic NO, window 0x0,
    keys:  1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   

MappingNotify event, serial 32, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 248

MappingNotify event, serial 32, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 247

Для корректной работы xmodmap необходимо обновить файл ~/.xmodmap и keycodes для hal драйвера.

~/.xmodmap
keycode 64 = Super_L
keycode 133 = Alt_L
keycode 134 = Alt_R
keycode 104 = Delete
keycode 169 = Print Sys_Req

После применения файла, обновленный xev log.

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27496232, (785,378), root:(788,423),
    state 0x0, keycode 64 (keysym 0xffeb, Super_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27496288, (785,378), root:(788,423),
    state 0x8, keycode 64 (keysym 0xffeb, Super_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27496456, (785,378), root:(788,423),
    state 0x0, keycode 133 (keysym 0xffe9, Alt_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27496488, (785,378), root:(788,423),
    state 0x8, keycode 133 (keysym 0xffe9, Alt_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27497104, (785,378), root:(788,423),
    state 0x0, keycode 134 (keysym 0xffea, Alt_R), same_screen YES,
    XKeysymToKeycode returns keycode: 108
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27497160, (785,378), root:(788,423),
    state 0x8, keycode 134 (keysym 0xffea, Alt_R), same_screen YES,
    XKeysymToKeycode returns keycode: 108
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27497304, (785,378), root:(788,423),
    state 0x0, keycode 104 (keysym 0xffff, Delete), same_screen YES,
    XLookupString gives 1 bytes: (7f) ""
    XmbLookupString gives 1 bytes: (7f) ""
    XFilterEvent returns: False

KeyRelease event, serial 30, synthetic NO, window 0x4a00001,
    root 0x8b, subw 0x0, time 27497352, (785,378), root:(788,423),
    state 0x0, keycode 104 (keysym 0xffff, Delete), same_screen YES,
    XLookupString gives 1 bytes: (7f) ""
    XFilterEvent returns: False

MappingNotify event, serial 30, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 248

MappingNotify event, serial 30, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 247

FocusOut event, serial 30, synthetic NO, window 0x4a00001,
    mode NotifyGrab, detail NotifyAncestor

FocusIn event, serial 32, synthetic NO, window 0x4a00001,
    mode NotifyUngrab, detail NotifyAncestor

KeymapNotify event, serial 32, synthetic NO, window 0x0,
    keys:  1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   

MappingNotify event, serial 32, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 248

MappingNotify event, serial 32, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 247

Из которого следует, что все преобразования прошли успешно. Однако, глобальные keybinding по прежнему не работают как надо. А именно: после применения файла xmodmap ~/.xmodmap по прежнему на нажатие клавиши Eject (новой print screen) не происходит взятия снимка экрана, а нажатие на alt option (новая Window key) не возможно перетаскивать окно.

Из предыдущего опыта настройки маппинга для федора 9 я делаю вывод, что проблема находится в X11. Очивидно, что после запуска x11, некоторый модуль грузит карту клавиатуры и считывает значения специальных клавишь модификаторов и возможно системных кнопок. Такой вывод я делаю потому, что значения клавиш модефикаторов невозможно переопределить стандартыми средствами которые позволяют xmodmap. Кроме того, даже при наличии корректно сформированного xkb файла с расскладкой, данная ошибка продолжает пресутствовать, если расскладка загружена уже после старта X11. Другими словами, существует только один способ переопределить коды клавишь модификаторов - при старте x11 в файле xorg.conf.

Думаю проблемма всплыла значительно раньше и была бы уже исправлена если бы клавиатуры использовали различные коды для модификаторов. Если бы каждая клавиатура которую вы подключали к компьютеру имела бы сильно отличающийся layout, включая другое расположение кнопок shift, windows key, alt и другие. Но на сягодняший день видимо только у меня возникла необходимость переопределить занчения специальных кнопок на новые.

Продолжение следует...

понедельник, 12 января 2009 г.

Python object

Начало здесь: http://blog.axet.ru/2008/02/object-languages.html

Пожалуй самой большой ошибкой в стандарте python есть отсутствие деструкторов.

Создатели языка поторопились и поместили в язык все преимущества и отказались от всех недостатков C++, заисключением понятия самоочистки.

Идея деструктора в С++ - производить очистку объекта. Дополнительно к этому комплилятор снабжает код, дополнительными проверками и деструкторами локальных объектов.

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

Например, когда вы создаете объект в С++, у него вызывается функция инициализатор, которая подготавливает объект к использованию. Когда вы заканчиваете работать с объектом, вы вызываете delete *pointer. Она освобождает память, очищает локальные переменные и вызывает их дестркуторы. После чего объект удаляется. Однако, если не смотня на то что вы удалили объект, вы продолжаете с ним работать - вызывается исключения защиты памяти или что нибудь другое.

Выходит что в С++ разработана одна из самых лучших моделей работы с объектами, содержащая небольшие проблемы и понтенциальные проблемы вызывающие недостаток по защите среды исполнения и кучи памяти. В питоне же наоборот.

В питоне вы получаете обсолютную защиту по памяти, но получаете куда более страшные ошибки по утечкам памяти и не линейности работы и временем жизни объектов.

Теперь я продемонстрирую наглядно мои слова:

C++

class My
{
   Some m_some;

  public:
   My(){}
   ~My(){};
};

{
  My *m =  new My();
  delete m;
}

Вы легко создате объект и компилятор помогает вам удалить его, среда исполнения следит за тем чтобы объект не использовался повторно. Разумеется было бы правильей и надежей делать это через использование счетчика ссылок на объект (refcount). Но такая модель была бы менее эффективной и мнее производительной. Главное здесь - вы получаете полное понимание и контрольза жизнью объекта и система помогает вам избежать ошибок, правдо ценой стабильности.


Возмем питон.

class Data:
  some = None

  def __init__(self):
    None

  def __del__(self):
    None

  def close(self):
    None

Если вы работаете с объектом и захотели его удалить, вы не можете быть увереным, что объект не испльзуется!

self.data = {}
self.data[obj] = Data()

self.data[obj].close()
del self.data[obj]

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

И все равно вы не получаете полной гарантий в том, что объект удален!

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

Куда было бы приятней такая конструкция:


self.data = {}
self.data[obj] = Data()

superdel self.data[obj]

В которой superdel - вызывает деструктур именуемый __superdel__ у класса, после чего удаляет объект из массива и проверяет (!) количство ссылок на объект. В случае если фукнция деструктора класса __superdel__ не смогла очистить объект от локальных или глобальных ссылок superdel вызывает исключение!

И это все, что отделяет питон от самого гибкого и удобного инструмента разработки!

воскресенье, 11 января 2009 г.

gedit encoding converter

Казалось бы такая бытовая операция как открытие текстового файла, представляет из себя серезную проблемму если вы находитесь под ОС линукс.

Если вы недавно перешли на операционную систему Линукс наверняка захватите с собой все файлы сохраненные под Windows в кодировке CP-1251. Чье содержимое при просмотре стандартными программами под Линукс привидет к искожению содержимого. Так например станартный редактор текста gedit показывается содержимое виндус файлов в кодировке ISO-8859-15, что не позволяет читать его содержимое. Так же вы можете попробовать вывести файл в терминал или, напирмер посмотреть фильм с русскими субтитрами программой VLC Player. Во всех этих случаях вы получаете искаженный вывод.

Одно из возможных решений - перевести файлы в формат UTF-8.

Для этой цели я набросал небольшой плагин для текстового редактора gedit. В настоящий момент он поддерживает переобразование из кодировки CP-1251 в UTF-8. Но без труда может быть доработан до включения всех поддерживаемых расскладок.

~/.gnome2/gedit/plugins/encodingconverter.gedit-plugin
[Gedit Plugin]
Loader=python
Module=encodingconverter
IAge=2
Name=Encoding Converter
Description=Converts open files to other encoding
Authors=Alexey Kuznetsov
Copyright=Copyright © 2009 Alexey Kuznetsov <ak@axet.ru>
Website=http://axet.ru

~/.gnome2/gedit/plugins/encodingconverter.py
'''
thx to http://live.gnome.org/Gedit/PythonPluginHowTo

Copyright (C) 2009 Alexey Kuznetsov <ak@axet.ru>

version 1.0.0

'''

import gedit
import gtk
import codecs
import os
import sys
from os.path import join, getsize

class EncodingConverterPluginHelper:
  submenu = """<ui>
    <menubar name='MenuBar'>  
      <menu name='ToolsMenu' action='Tools'>
        <menuitem action='fromCP1251'/>
      </menu>
    </menubar>
  </ui>"""

  def __init__(self, plugin, window):
    self.window = window
    self.plugin = plugin

    doc = self.window.get_active_document()

    actions = (
        ("fromCP1251", None, "Convert text from CP1251", None, "Convert text from CP1251", self.fromCP1251),
    )

    self.action_group = gtk.ActionGroup("GeditToUTF8EncodingConverterPluginActions")
    self.action_group.add_actions(actions, window)

    manager = window.get_ui_manager()
    manager.insert_action_group(self.action_group, -1)
    self.ui_id = manager.add_ui_from_string(self.submenu)

  def __del__(self):
    manager = self.window.get_ui_manager()
    manager.remove_ui(self.ui_id)
    manager.remove_action_group(self.action_group)
    manager.ensure_update()

  def update_ui(self):
    doc = self.window.get_active_document()
    self.action_group.set_sensitive(bool(doc and not doc.get_readonly()))

  def fromCP1251(self, widget, window):
    doc = window.get_active_document()
    start, end = doc.get_bounds()

    text = doc.get_text(start, end)

    currentencoder = codecs.lookup(doc.get_encoding().get_charset())[0]

    utf8decoder = codecs.lookup('utf-8')[1]
    windecoder = codecs.lookup('windows-1251')[1]
    utf8encoder = codecs.lookup('utf-8')[0]

    text = utf8decoder(text)[0]

    text = currentencoder(text)[0]

    text = windecoder(text)[0]

    text = utf8encoder(text)[0];

    doc.begin_user_action()
    it = doc.get_iter_at_mark(doc.get_insert())
    line = it.get_line()
    doc.delete(start, end)
    doc.insert(start, text)
    doc.end_user_action()

class EncodingConverterPlugin(gedit.Plugin):
  def __init__(self):
    gedit.Plugin.__init__(self)
    self._instances = {}

  def activate(self, window):
    self._instances[window] = EncodingConverterPluginHelper(self, window)

  def deactivate(self, window):
    del self._instances[window]

  def update_ui(self, window):
    self._instances[window].update_ui()


Домашняя страница проекта:

пятница, 9 января 2009 г.

Skype for linux 3.0.0.93

Скайп версии 3 доступен для скачивания!


Выпущен релиз для MID устройств, что означает полную совместимость с desktop версиями линукса! Из приятных дополнений появилась поддержка отправки SMS!


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

суббота, 3 января 2009 г.

Creative Commons Attribution-Share Alike 3.0 Unported

Хочу дать сообщение, что все тексты данного журнала принадлежать мне, за исключением цитат и картинок и товарных знаков, на которые я могу ссылаться. Все содержимое как ранее написанное так и те тексты, которые я выложу в будущем, я выкладываю под лицензией Creative Commons Attribution-Share Alike 3.0 Unported. Если изменения в лицензировании содержимого произойдут, то я оповещу читателей через аналогичное сообщение в журнале и оно будет иметь силу над настоящим.

Вкратце, Creative Commons Attribution-Share Alike 3.0 Unported означает:
- копируйте
- цитируйте
- создавайте материалы на основе существующих
- получайте прибыль от тех материалов, которые вы тут нашли и скопировали и не нужно делиться со мной
- но, при этом, не забывайте указывать автора, мой сайт и говорить спасибо
- а так же - распространять свои работы на тех же условиях


Текст лицензии:

Java. Interacting with C++

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

Очередная статья, которую я не хочу ставить в оппозицию к уже существующим языковым средам и показывать ее преимущества. Ява платформа со своим многолетним опытом и прекрасной базой ее создателей практически не оставляет себе конкурентов и является образцом взаимодействия, которое только себе можно представить с любой другой внешней средой. Без труда можно получить все решения доступные программисту без всяких усилий, в то время как в среде ерангла о таких возможностях приходится только мечтать. Нельзя оставить без внимания такой важный момент как возможность инициализировать состояние виртуальной машины из среды С++ и передать ей управление! Что очень напоминает нам все современные шумные решения последних лет от sun (javafx), adobe (flash) и google (native client). Но давайте остановимся, я не буду позволять себе больше высказывать свою позицию относительно эффективного решения ниже этого абзаца, которое не нуждается в модификации уже далеко за первый десяток лет!

Взаимодействие явы с языком С++ осуществляется через набор библиотек JNI, интерфейсы которой открывают всю виртуальную машину со всеми ее внутренними особенностями разработчику. Все интерфейсы подробно описаны в документации и представляют из себя полноценную документацию по которой можно разобраться в тонкостях взаимодействия с виртуальной средой.


Взаимодействие ява среды с С++ происходит через создание оберток test_cpp.java && test_cpp.cpp двух файлов. В них происходит преобразования типов данных и образование новых структур для прозрачной передачи их между двумя средами.

Первым делом идут два библиотечных файла test.cpp && test.h, которые были представлены в предудущих статьях. Наша задача постараться использовать эти библиотеки из среды ява.

test.cpp
#include "test.h"

int test1(int i)
{
  return i*2;
}

Res test2(int i, int k)
{
  return Res(i*2,k*2);
}

test.h
struct Res
{
  int i,k;
  Res(int ii,int kk):i(ii),k(kk){}
};

int test1(int i);
Res test2(int i, int k);


Приложение на яве представляет из себя слегка модифицированный код стандратной процедуры main, с тем только отличием, что теперь это выполняется на языке ява.

app.java
public class app {

  public static void main(String args[]) {
    System.out.println(test_cpp.wr_test1(2));

    test_cpp.ResJ c = test_cpp.wr_test2(2,4);
    System.out.println(c.i + "; " + c.k);
  }

}

Для успешного вызова test_cpp.wr_test1 нам необходимо создать совместимый с виртуальной машиной класс на том же языке для обертывания нашей библиотеки test.cpp. Все функции, которые мы будем вызывать из виртуальной среды java мы называем в коде native. Это позволяет исполняемой среде подгружать нужную библиотеку и вызывать функцию написанную на других языках (в нашем примере на С++).

test_cpp.java
public class test_cpp {

  public static class ResJ {
     public int i,k;
  };

  static native int wr_test1(int i);
  static native ResJ wr_test2(int i, int k);

  static {
     System.loadLibrary("test_cpp");
  }

}


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

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

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

test_cpp.cpp
#include "test_cpp.h"
#include "test.h"

#include <exception>

class JavaException:public std::exception
{
public:
  JNIEnv * m_env;
  jthrowable m_exp;

  JavaException(const JavaException&je)
  {
    m_env=je.m_env;
    m_exp=je.m_exp;
  }
  JavaException(JNIEnv * env):m_env(env)
  {
    m_exp=(jthrowable)m_env->NewGlobalRef(m_env->ExceptionOccurred());
    m_env->ExceptionDescribe();
  }
  ~JavaException() throw()
  {
    m_env->DeleteGlobalRef(m_exp);
  }
  const char* what() const throw()
  {
    return "Java Exception";
  }
};


JNIEXPORT jint JNICALL Java_test_1cpp_wr_1test1 (JNIEnv *env, jclass test_cpp_class, jint i_p)
{
  try
  {
    return test1(i_p);
  }catch(JavaException &e)
  {
    env->Throw(e.m_exp);
    return 0;
  }catch(std::exception &e)
  {
    env->ThrowNew(env->FindClass("java/lang/Throwable"),e.what());
    return 0;
  }
}

JNIEXPORT jobject JNICALL Java_test_1cpp_wr_1test2 (JNIEnv *env, jclass test_cpp_class, jint i_p, jint k_p)
{
  try
  {
    Res res = test2(i_p, k_p);

    jclass resj_class=env->FindClass("test_cpp$ResJ");
    if(env->ExceptionOccurred())
      throw JavaException(env);

    jmethodID resj_init=env->GetMethodID(resj_class,"","()V");
    if(env->ExceptionOccurred())
      throw JavaException(env);

    jobject res_obj=env->NewObject(resj_class,resj_init);
    if(env->ExceptionOccurred())
      throw JavaException(env);

    jfieldID i_id=env->GetFieldID(resj_class,"i","I");
    if(env->ExceptionOccurred())
      throw JavaException(env);

    env->SetIntField(res_obj,i_id,res.i);
    if(env->ExceptionOccurred())
      throw JavaException(env);

    jfieldID k_id=env->GetFieldID(resj_class,"k","I");
    if(env->ExceptionOccurred())
      throw JavaException(env);

    env->SetIntField(res_obj,k_id,res.k);
    if(env->ExceptionOccurred())
      throw JavaException(env);

    return res_obj;

  }catch(JavaException &e)
  {
    env->Throw(e.m_exp);
    return jobject();
  }catch(std::exception &e)
  {
    env->ThrowNew(env->FindClass("java/lang/Throwable"),e.what());
    return jobject();
  }
}

test_cpp.h
/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

#ifndef __test_1cpp__
#define __test_1cpp__

#ifdef __cplusplus
extern "C"
{
#endif

JNIEXPORT jint JNICALL Java_test_1cpp_wr_1test1 (JNIEnv *env, jclass, jint);
JNIEXPORT jobject JNICALL Java_test_1cpp_wr_1test2 (JNIEnv *env, jclass, jint, jint);

#ifdef __cplusplus
}
#endif

#endif /* __test_1cpp__ */



Исполняемый файл, запускает приложение.


test_cpp.sh
#!/bin/bash

java -classpath . app

пятница, 2 января 2009 г.

Free computing

Предновогоднее муссирование таких тем как OpenCL (Open Computing Language), переход Apple на использование этой технологии, а так же открытие компаний ATI спецификации на их современные видео карты демонтируют скрытую гонку на этом рынке.

С наступившим, кстати!

К этому списку нужно добавить уже стабильную поддержку 3Д ускорения для видко карт Nvidia, открытие исходного кода на чипы VIA и постоянную модернизацию и совершенствование открытых драйверов компании Intel для их видео адаптеров.

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

Вернемся в начало 90-х когда появились первые компьютеры с 3д ускорением. Мы еще помним как вставляли в компьютер параллельно (!) основной видео картой дополнительную, которая соединялась множеством проводов со своим собратом 3д-ускорителем 3dfx! Собрав такой агрегат можно было поиграть в крутые игры, для того времени, и получить картинку не хуже чем на игровых приставках! И самое главное потрясающие спец. эффекты и трехмерную графику!

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

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

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

Это то время когда купив простую плату и видео-карту без поддержки 3д ускорения, и процессор с поддержкой ММХ можно было бегать по трехмерным лабиринтам и убивать монстров без использования пресловутого 3д ускорителя.

А что если предположить, что в настоящий момент процессорных мощностей 4,8,16 ядер уже достаточно что бы позволить обрабатывать любой поток медия данных и получать картинку ни чем не хуже чем это делают современные видо-ускорители?

Следовательно, чтобы ответить на этот вопрос нам необходимо разобраться в том как работают 3д ускорители. Давайте почитаем! Для того, чтобы точно узнать насколько современные 3д ускорители действительно нам нужны, мы хотим прочитать документацию на чипы.

Возьмем любое устройство с красивой графикой и посмотрим как это работает, например приставку playstation - документация закрыта по NDA. Хм, ничего нас не хотят посвящать в святую святых. Возьмем другое устройство, полностью открытый телефон Neo FreeRunner! Его программное обеспечение полностью открыто, открыты спецификации на чипы, открыты вся проектная документация. Его можно спаять хоть дома! Тут то уж точно будет то что мы ищем, для этого зайдем в раздел документации Graphics 3d acceleration.

ДОКУМЕНТАЦИЯ ЗАКРЫТА ПО NDA!

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

Возможно именно такая ситуация привела ATI компанию к банкротству и скупки ее AMD. Вторая компания по иронии судьбы оказалась компанией производителем процессоров! После покупки именно АМД открывает дата шиты на чипы и исходный код драйверов, все это направлено на уничтожение свого конкурента - NVIDIA, и делает AMD это самым эффективным средством - гласностью!


В очередной раз хочу поздравить читателя! Мы живем в эпоху перемен,  где не возможно ничего скрыть. В силу рудементарности, 3д акселерация доживает свой век! И вы уже в скором времени вы не пойдете в магазин покупать новый GFORCE 50000, а просто зайдете на сайт производителя и скачаете и установите эту видео карту как программный пакет!

А если вам не терпится, уже сейчас вы можете познакомиться с тем, как нарисовать свой первый треугольник средствами процессора, пока еще GPU.

Ссылки по теме: