Замена кода "на лету"
От: md03t4  
Дата: 15.06.09 10:23
Оценка:
Я знаю, что subj реализован в Erlang-е.
Есть ли еще языки/системы, где реализован похожий функционал?
Re: Замена кода "на лету"
От: SergH Россия  
Дата: 15.06.09 10:24
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

Загрузка dll?

Делай что должно, и будь что будет
Re: Замена кода "на лету"
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 15.06.09 10:25
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

В Ruby.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 15.06.09 10:41
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

Что подразумевается под этим? А то, вон в дотнете такое возможно.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[2]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 15.06.09 10:42
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

M>>Я знаю, что subj реализован в Erlang-е.

M>>Есть ли еще языки/системы, где реализован похожий функционал?
AS>Что подразумевается под этим?
Замена работающего кода.

AS>А то, вон в дотнете такое возможно.

Невозможно.
Sapienti sat!
Re: Замена кода "на лету"
От: Quintanar Россия  
Дата: 15.06.09 10:47
Оценка: +2
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

Думаю, для любого интерпретируемого языка с проверкой типов во время исполнения такое элементарно реализовывается.
Классический пример — Лисп.
Re[3]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 15.06.09 10:49
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Aen Sidhe, Вы писали:


M>>>Я знаю, что subj реализован в Erlang-е.

M>>>Есть ли еще языки/системы, где реализован похожий функционал?
AS>>Что подразумевается под этим?
C>Замена работающего кода.

Непонимаю.

AS>>А то, вон в дотнете такое возможно.

C>Невозможно.

А как же тогда ASP.NET работает? Перезаписал dll, код для новых запросов — новый. Или это не то?
С уважением, Анатолий Попов.
ICQ: 995-908
Re[4]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 15.06.09 10:52
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

C>>Замена работающего кода.

AS>Непонимаю.
Что тут непонятного? Erlang позволяет заменять код уже загруженных и работающих модулей.

AS>>>А то, вон в дотнете такое возможно.

C>>Невозможно.
AS>А как же тогда ASP.NET работает? Перезаписал dll, код для новых запросов — новый.
А ещё можно приложение перезапустить. Тоже код заменится!

AS>Или это не то?

Совсем.
Sapienti sat!
Re[5]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 15.06.09 10:54
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Aen Sidhe, Вы писали:


C>>>Замена работающего кода.

AS>>Непонимаю.
C>Что тут непонятного? Erlang позволяет заменять код уже загруженных и работающих модулей.

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

Всё, что описано здесь возможно.

AS>>Или это не то?

C>Совсем.

Укажите разницу.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[6]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 15.06.09 11:00
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

C>>Что тут непонятного? Erlang позволяет заменять код уже загруженных и работающих модулей.

AS>Непонятно то, что дотнет тоже это позволяет. Мне никто не мешает выгрузить пару сборок (вместе , загрузить другие и заставить их работать).
AS>Всё, что описано здесь возможно.
Ещё раз — можно менять уже работающий код.

Грубо говоря, оно было бы таким же, если бы можно было для:
class Blah
{
    int a, b;
}

В рантайме добавить ко всем существующим инстансам этого класса новое поле или поменять тип поля.
Sapienti sat!
Re: Замена кода "на лету"
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 15.06.09 11:01
Оценка: 44 (6)
md03t4,

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

С очень маленькой гранулярностью (единица загрузки — символ)
Lisp, Scheme, J, K, ... ну можно даж до Васика наверное дойти

С маленькой гранулярностью (единица загрузки — функция/метод, бинд или тип)
Haskell (библиотека hs-plugins), .net dml, C (с мегахаком
Автор: Lazy Cjow Rhrr
Дата: 01.02.07
), Smalltalk

Со средней гранулярностью (единица загрузки — класс/модуль)
Java, Ocaml

С большой гранулярностью (единица загрузки — домен)
.net 1.0

// Не уверен насчёт Смоллтока, возможно там-таки очень маленькая гранулярность
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[2]: Замена кода "на лету"
От: md03t4  
Дата: 15.06.09 11:01
Оценка:
Здравствуйте, Quintanar, Вы писали:

Q>Здравствуйте, md03t4, Вы писали:


M>>Я знаю, что subj реализован в Erlang-е.

M>>Есть ли еще языки/системы, где реализован похожий функционал?

Q>Думаю, для любого интерпретируемого языка с проверкой типов во время исполнения такое элементарно реализовывается.

Q>Классический пример — Лисп.
Для любого интерпретируемого, или любого функционального?
Как выгрузить модуль (любую другую единицу компиляции), если ссылки на его переменные могут быть со[ранены в других модулях? функции в чистом функциональном языке не имеют сторонних эффектов, чистый функциональный язык не имеет и глобальных переменных, да и переменных как таковых не имеет , но лисп не таков. Руби — тем более. Простая замена DLL — в двойне "тем более".
Спасибо, я покопаю Руби, попытаюсь понять как там это сделано, если сделано. Пока мне не удалось ничего похожего найти.
Re: Замена кода "на лету"
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 15.06.09 11:03
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

Кроме названного — Python, перезагрузка модулями.
The God is real, unless declared integer.
Re[5]: Замена кода "на лету"
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.06.09 11:04
Оценка:
Здравствуйте, Cyberax, Вы писали:

AS>>>>А то, вон в дотнете такое возможно.

C>>>Невозможно.
AS>>А как же тогда ASP.NET работает? Перезаписал dll, код для новых запросов — новый.
C>А ещё можно приложение перезапустить. Тоже код заменится!
В случае asp.net при изменении страницы приложение не перезапускается.

В принципе вполне возможно заменять код в .NET, приседаний много надо
Re[7]: Замена кода "на лету"
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.06.09 11:06
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Aen Sidhe, Вы писали:


C>>>Что тут непонятного? Erlang позволяет заменять код уже загруженных и работающих модулей.

AS>>Непонятно то, что дотнет тоже это позволяет. Мне никто не мешает выгрузить пару сборок (вместе , загрузить другие и заставить их работать).
AS>>Всё, что описано здесь возможно.
C>Ещё раз — можно менять уже работающий код.

C>Грубо говоря, оно было бы таким же, если бы можно было для:

C>
C>class Blah
C>{
C>    int a, b;
C>}
C>

C>В рантайме добавить ко всем существующим инстансам этого класса новое поле или поменять тип поля.

А где здесь работающий код?
Re[7]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 15.06.09 11:09
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Aen Sidhe, Вы писали:


C>>>Что тут непонятного? Erlang позволяет заменять код уже загруженных и работающих модулей.

AS>>Непонятно то, что дотнет тоже это позволяет. Мне никто не мешает выгрузить пару сборок (вместе , загрузить другие и заставить их работать).
AS>>Всё, что описано здесь возможно.
C>Ещё раз — можно менять уже работающий код.

Очевидно, в примере с ASP.NET меняется не работающий код. Я вас правильно понял?

C>В рантайме добавить ко всем существующим инстансам этого класса новое поле или поменять тип поля.


Ну, к существующим нельзя так вот просто сделать. К новым — легко. Буквально, одна строка кода/одна настройка в конфиге
С уважением, Анатолий Попов.
ICQ: 995-908
Re[8]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 15.06.09 11:16
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

C>>Ещё раз — можно менять уже работающий код.

AS>Очевидно, в примере с ASP.NET меняется не работающий код. Я вас правильно понял?
Да. В примере с ASP.NET загружается новый код, который просто начинает обслуживать новые запросы.

C>>В рантайме добавить ко всем существующим инстансам этого класса новое поле или поменять тип поля.

AS>Ну, к существующим нельзя так вот просто сделать. К новым — легко. Буквально, одна строка кода/одна настройка в конфиге
Нет, не легко. Например, если я передам в новый код инстанс старого класса — получится фигня.
Sapienti sat!
Re[3]: Замена кода "на лету"
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 15.06.09 11:21
Оценка: 16 (3) +1
Здравствуйте, md03t4, Вы писали:

M>Для любого интерпретируемого, или любого функционального?

M>Как выгрузить модуль (любую другую единицу компиляции), если ссылки на его переменные могут быть со[ранены в других модулях? функции в чистом функциональном языке не имеют сторонних эффектов, чистый функциональный язык не имеет и глобальных переменных, да и переменных как таковых не имеет :), но лисп не таков. Руби — тем более. Простая замена DLL — в двойне "тем более".

Я использовал это в Питоне. У него, с одной стороны, можно переопределять практически всё (например, определения класса), с другой стороны, старые определения сохраняются, пока на них есть ссылки. В результате получается следующий эффект. Если использовать, например, так:

from Module import Class
...
c = Class()

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

import Module
...
c = Module.Class()

то разрешение происходит в момент вызова Class(), и грузится новый код.

Думаю, в Ruby эффекты не отличаются. В результате такого подхода, может быть произвольное количество копий старых определений, пока они используются. Это определённый плюс — по сравнению с Erlang, например, где может быть только текущая и предыдущая копия — но тут же и минус: процесс перехода может растянуться надолго. Эффекты от необходимости перезапускать операции "from X import Y" обсуждаются, например, здесь, вместе с методами надёжного перезапуска. Но для разных случаев надо это делать достаточно по-разному. У меня, например, получались группы модулей, внутри которых связи надо было обновлять сразу, а за их пределами — не обязательно или вообще нежелательно (объект должен доработать с кодом своего класса, а не с обновлённым).

В последних версиях делал перезагрузку модуля специальной функцией, которая до и после этого вызывала в нём специальные хуки (_prereload, _postreload). Это давало возможность модулю произвести "дочистку" определений по необходимости.

Перезагрузку в Erlang'е собираемся применять, но тут таки много особенностей, которые в стандартный relup не укладываются. И все его методы не помогают против того, что если логика сменилась, например, с использованием других модулей или смены порядка прохождения обработчиков (при пересылке между ними), оказывается необходимо ставить не просто версию B после версии A, а версию "вариант B для перехода с A" и только когда этот переход произошёл успешно — переходить на окончательную B. relup помогает только тривиальным случаям, когда нет несовместимых изменений межмодульной логики или интерфейсов, а лучше — все изменения локализованы внутри модуля.
The God is real, unless declared integer.
Re[3]: Замена кода "на лету"
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 15.06.09 11:24
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Спасибо, я покопаю Руби, попытаюсь понять как там это сделано, если сделано. Пока мне не удалось ничего похожего найти.


http://rsdn.ru/forum/philosophy/2091241.1.aspx
Автор: eao197
Дата: 04.09.06


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Замена кода "на лету"
От: thesz Россия http://thesz.livejournal.com
Дата: 15.06.09 13:34
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

В старом добром Си.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Re: Замена кода "на лету"
От: MasterZiv СССР  
Дата: 15.06.09 15:40
Оценка:
md03t4 wrote:

> Я знаю, что subj реализован в Erlang-е.

> Есть ли еще языки/системы, где реализован похожий функционал?

Common Lisp. Правда, я не уверен, что это стандартно и гарантированно,
но я это сам наблюдал в SBCL.
Posted via RSDN NNTP Server 2.1 beta
Re[7]: Замена кода "на лету"
От: MasterZiv СССР  
Дата: 15.06.09 15:41
Оценка:
Cyberax wrote:

> В рантайме добавить *ко всем существующим* инстансам этого класса новое

> поле или поменять тип поля.

А, тогда в COmmon Lisp это есть, и гарантировано стандартом.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Замена кода "на лету"
От: MasterZiv СССР  
Дата: 15.06.09 15:42
Оценка:
Quintanar wrote:

> Думаю, для любого интерпретируемого языка с проверкой типов во время

> исполнения такое элементарно реализовывается.
> Классический пример — Лисп.

Хочу сделать поправку. Лисп -- не интерпретируемый язык.
(common lisp).
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Замена кода "на лету"
От: MasterZiv СССР  
Дата: 15.06.09 15:51
Оценка:
md03t4 wrote:

> Для любого интерпретируемого, или любого функционального?


На самом деле это всё неважно.

> Как выгрузить модуль (любую другую единицу компиляции), если ссылки на

> его переменные могут быть сохранены в других модулях?

в common lisp ВСЕ определения/переопределения ВСЕХ элементов
программ происходят ВСЕГДА на ходу, т.е. при возможно уже
определённых в лисп-машине этих же элементах. Это — штатный
режим работы лисп-машины. При этом даже инстансы объектов
изменяемых классов сохраняются, только их поля меняются/
добавляются/удаляются, и даже есть возможность эти изменения
программно обработать. Что про "Ссылки на переменные" ...
Переменные вообще-то сами являются ссылками. Так что не очень
понятно, что имеется в виду.

Другое дело, что не все реализации common lisp поддерживают
реальную многозадачность, или вообще какую-то многозадачность,
а вот как с переопределением на ходу в уже поддерживающих
многозадачность лиспах, -- это вопрос "честности" реализаций.
Posted via RSDN NNTP Server 2.1 beta
Re[8]: Замена кода "на лету"
От: Воронков Василий Россия  
Дата: 15.06.09 15:58
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>Ну, к существующим нельзя так вот просто сделать. К новым — легко. Буквально, одна строка кода/одна настройка в конфиге


А dynamic method как же?
Re[2]: Замена кода "на лету"
От: FR  
Дата: 16.06.09 03:52
Оценка: +1
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>// Не уверен насчёт Смоллтока, возможно там-таки очень маленькая гранулярность


Там еще веселей, перезагрузка кода нормальное рутино используемое явление, даже простой набор текста метода ее использует.
Re: Замена кода "на лету"
От: Pavel Dvorkin Россия  
Дата: 17.06.09 07:56
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

Дай точное определение, о чем идет речь. Иначе я тебе заявлю, что на ассемблере ты можешь заменять на лету все, что тебе в голову придет, вплоть до генерации нового кода на основе данных, полученных откуда угодно.
With best regards
Pavel Dvorkin
Re[3]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 17.06.09 17:46
Оценка:
Здравствуйте, Cyberax, Вы писали:

AS>>А то, вон в дотнете такое возможно.

C>Невозможно.

Возможно.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 17.06.09 18:21
Оценка:
Здравствуйте, IT, Вы писали:

AS>>>А то, вон в дотнете такое возможно.

C>>Невозможно.
IT>Возможно.
Как?

(DLR, понятное дело, не считаем)
Sapienti sat!
Re[5]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 17.06.09 19:23
Оценка:
Здравствуйте, Cyberax, Вы писали:

IT>>Возможно.

C>Как?

Домен можно загрузить по-новой, не выгружая старый пока он выполняет запросы.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 17.06.09 19:46
Оценка: +1
Здравствуйте, IT, Вы писали:

IT>>>Возможно.

C>>Как?
IT>Домен можно загрузить по-новой, не выгружая старый пока он выполняет запросы.
Не, ну я так хоть в С++ сделаю перезагрузку кода. Это не то.
Sapienti sat!
Re[7]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 18.06.09 02:45
Оценка:
Здравствуйте, Cyberax, Вы писали:

IT>>Домен можно загрузить по-новой, не выгружая старый пока он выполняет запросы.

C>Не, ну я так хоть в С++ сделаю перезагрузку кода. Это не то.

Как?
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 18.06.09 06:54
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, Cyberax, Вы писали:


IT>>>Домен можно загрузить по-новой, не выгружая старый пока он выполняет запросы.

C>>Не, ну я так хоть в С++ сделаю перезагрузку кода. Это не то.

IT>Как?


Сэмулирует эти же самые домены, скорее всего. Просто граждане не понимаю, что единственное различие — единица перезагрузки. Штатными средствами, без приседаний в .NET — это домен, где-то метод, где-то класс.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[8]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 18.06.09 11:01
Оценка:
Здравствуйте, IT, Вы писали:

IT>>>Домен можно загрузить по-новой, не выгружая старый пока он выполняет запросы.

C>>Не, ну я так хоть в С++ сделаю перезагрузку кода. Это не то.
IT>Как?
Загружаем DLL с новым кодом и вперёд с песней. Ну или в случае CGI — просто отправляем новые запросы новому exe-шнику.
Sapienti sat!
Re[9]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 18.06.09 13:22
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Загружаем DLL с новым кодом и вперёд с песней.


Ты сам пробовал?
Если нам не помогут, то мы тоже никого не пощадим.
Re[10]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 18.06.09 15:07
Оценка:
Здравствуйте, IT, Вы писали:

C>>Загружаем DLL с новым кодом и вперёд с песней.

IT>Ты сам пробовал?
Да. Использовалось для переключения между software и hardware реализациями OpenGL.

Разница с С# тут будет в чисто процессуальных вопросах.
Sapienti sat!
Re[11]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 18.06.09 16:09
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Разница с С# тут будет в чисто процессуальных вопросах.


Т.е. замена кода на лету возможна не только в Эрланге, а практически везде. Почему же тогда считается, что эта фича есть только в нём?
Если нам не помогут, то мы тоже никого не пощадим.
Re[12]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 18.06.09 16:57
Оценка:
Здравствуйте, IT, Вы писали:

C>>Разница с С# тут будет в чисто процессуальных вопросах.

IT>Т.е. замена кода на лету возможна не только в Эрланге, а практически везде. Почему же тогда считается, что эта фича есть только в нём?
Потому, что в Эрланге она намного мощнее. Тут я это уже объяснял.
Sapienti sat!
Re[13]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 18.06.09 17:22
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, IT, Вы писали:


C>>>Разница с С# тут будет в чисто процессуальных вопросах.

IT>>Т.е. замена кода на лету возможна не только в Эрланге, а практически везде. Почему же тогда считается, что эта фича есть только в нём?
C>Потому, что в Эрланге она намного мощнее. Тут я это уже объяснял.

Угу. Майбах может ездить. И ауди может ездить. Но майбах делает это круче, поэтому ауди не ездит.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[5]: Замена кода "на лету"
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.06.09 17:28
Оценка:
Здравствуйте, Cyberax, Вы писали:

AS>>А как же тогда ASP.NET работает? Перезаписал dll, код для новых запросов — новый.

C>А ещё можно приложение перезапустить. Тоже код заменится!

А какая разница то, если состояние один фиг остается целым?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 18.06.09 17:28
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, IT, Вы писали:


C>>>Разница с С# тут будет в чисто процессуальных вопросах.

IT>>Т.е. замена кода на лету возможна не только в Эрланге, а практически везде. Почему же тогда считается, что эта фича есть только в нём?
C>Потому, что в Эрланге она намного мощнее. Тут я это уже объяснял.

оффтопный вопрос про Erlang. Чисто академический интерес.
Есть метод:
void M()
{
  a = 1;
  b = 2; {x}
  c = a + b; {y}
}


Предположим, что у нас выполняется код в точке {x} и в этот момент (до начала выполнения {y}) мы подменяем код на

void M()
{
  a = 1;
  b = 2; 
  c = a - b;
}


Чему равно c?

А если подменить на вот такой код:
void M()
{
  d = "abc";
  b = "def"; {x}
  c = a + b; {y}
}


Чему тут будет равно с? (для упрощения представим, что вместо + для строк мы написали валидную по синтаксису Эрланга конкатенацию строк, с числами же — обычные арифметические операции с 32битными числами).
С уважением, Анатолий Попов.
ICQ: 995-908
Re[14]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 18.06.09 17:30
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

Следует читать так:

AS>
AS>void M()
AS>{
AS>  d = "abc";
AS>  b = "def"; {x}
AS>  c = d + b; {y}
AS>}
AS>
С уважением, Анатолий Попов.
ICQ: 995-908
Re[14]: Замена кода "на лету"
От: Курилка Россия http://kirya.narod.ru/
Дата: 18.06.09 17:35
Оценка: 4 (1)
Здравствуйте, Aen Sidhe, Вы писали:

AS>оффтопный вопрос про Erlang. Чисто академический интерес.

[cut]

AS>Чему тут будет равно с? (для упрощения представим, что вместо + для строк мы написали валидную по синтаксису Эрланга конкатенацию строк, с числами же — обычные арифметические операции с 32битными числами).


Единицей гранулярности замены является модуль, единицей "переключения" является функция (плюс ещё есть "ньюанс", что должно быть написано полное имя module:function(...)), поэтому описываемая тобой ситуация произойти не может. Т.е. программист (если он понимает эрланг) знает, где именно может быть "переключение версии" (с этой же целью можно использовать "внутренние вызовы", если логика, которая может быть переключена не умещается в 1 функцию).
Re[15]: Замена кода "на лету"
От: Курилка Россия http://kirya.narod.ru/
Дата: 18.06.09 17:41
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Единицей гранулярности замены является модуль, единицей "переключения" является функция (плюс ещё есть "ньюанс", что должно быть написано полное имя module:function(...)), поэтому описываемая тобой ситуация произойти не может. Т.е. программист (если он понимает эрланг) знает, где именно может быть "переключение версии" (с этой же целью можно использовать "внутренние вызовы", если логика, которая может быть переключена не умещается в 1 функцию).


И ещё функция это единица переключения контекста планировщика, точней выполнение функции называется редукцией и процессы переключаются по-моему через 100 редукций. А загрузка кода — это же тоже будет процесс, насколько я понимаю. Поэтому "вклиниться" в выполнение функции (как это делает планировщик ОС) по-моему нельзя стандартными средствами.
Re[15]: Замена кода "на лету"
От: Aen Sidhe Россия Просто блог
Дата: 18.06.09 18:00
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Здравствуйте, Aen Sidhe, Вы писали:


AS>>оффтопный вопрос про Erlang. Чисто академический интерес.

К>[cut]

AS>>Чему тут будет равно с? (для упрощения представим, что вместо + для строк мы написали валидную по синтаксису Эрланга конкатенацию строк, с числами же — обычные арифметические операции с 32битными числами).


К>Единицей гранулярности замены является модуль, единицей "переключения" является функция (плюс ещё есть "ньюанс", что должно быть написано полное имя module:function(...)), поэтому описываемая тобой ситуация произойти не может. Т.е. программист (если он понимает эрланг) знает, где именно может быть "переключение версии" (с этой же целью можно использовать "внутренние вызовы", если логика, которая может быть переключена не умещается в 1 функцию).


Большое спасибо за разъяснение, теперь всё понятно.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[14]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 18.06.09 18:01
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>Чему тут будет равно с? (для упрощения представим, что вместо + для строк мы написали валидную по синтаксису Эрланга конкатенацию строк, с числами же — обычные арифметические операции с 32битными числами).

Подмена осуществляется в чётко определённых местах.
Sapienti sat!
Re[13]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 18.06.09 20:30
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Потому, что в Эрланге она намного мощнее. Тут я это уже объяснял.


Мощнее понятие недетерминированное.
Если нам не помогут, то мы тоже никого не пощадим.
Re[14]: Замена кода "на лету"
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.06.09 06:04
Оценка: 183 (7)
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, Cyberax, Вы писали:


C>>Потому, что в Эрланге она намного мощнее. Тут я это уже объяснял.


IT>Мощнее понятие недетерминированное.


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

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

(Я использовал тут для ясности понятия "клиент" и "соединение". Но этот подход можно использовать и там, где таких понятий нет или они называются иначе — как, например, процесс и открытый файл на FS, если нужно обновить драйвер FS. Основной момент в тех условиях, которые в принципе требуют формулировки понятия "на лету". Если работа с чем-то идёт по методу "открыл-чихнул-закрыл", тривиально организовать момент, когда ничего не "открыто" — и вопрос о замене на лету не стоит.)

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

Сравнивая известные мне среды, Erlang'овая реализация действительно является одной из максимально мощных, потому что:

1. Позволяет провести замену кода максимально быстро и прозрачно для приложения, незаметно для всех существующих соединений. На момент отработки запроса о запуске нового кода, со старым кодом будут работать только те процессы, которые уже с ним начали отрабатывать одно входное сообщение. При рекомендованной организации кода (по стандартам OTP) это доли секунды, в худшем случае единицы секунд (если отработка сообщения требует синхронного вызова чего-то длительного внешнего).
2. Содержит средства организации апгрейда (называемые relup), автоматизирующие выполнение этого процесса для широкого набора случаев.

Python'овая реализация:

1. Позволяет провести замену кода максимально быстро и прозрачно для приложения, незаметно для всех существующих соединений — но для этого требуется организация выполнения в уже известном стиле Erlang'а: чтобы один и тот же код для одного соединения выполнялся или отработкой целевых действий, или апгрейдом, но не одновременно. Иначе, возможности другие, но тоже симпатичные — можно существующие соединения отрабатывать старым кодом сколь угодно долго (и вручную разбираться с последствиями такой организации;))
2. Автоматизации апгрейда нет, надо организовывать свой закат солнца вручную именно для данного приложения.

А теперь если сравнить, например, с Java (сразу дисклеймер — все мои знания про эти её возможности только по документации) — организация кода в виде именованных классов с глобально уникальными именами (причём фиксированными в момент компиляции кода) резко усложняет возможность замены кода на лету, ибо существование двух одноимённых классов невозможно — а, значит, замена потребует
1) сохранения всех данных, хранимых в объектах этих классов, в некотором внешнем (для них) хранилище (в памяти, чтобы сохранить всякие открытые файлы)
2) собственно фазы перезагрузки кода
3) восстановления состояния из хранилища

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

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

На основании этих примеров можно вывести числовую оценку мощности механизма замены кода. Начнём с того, что отсутствие такой возможности оценим в 0 баллов:) Далее, возможность сосуществования старого и нового кода штатными средствами языка/среды ,оценим в 50 баллов, возможность поддержки более двух версий — в 60 баллов для языков с организацией на сообщениях и 70 — на общей памяти. (Это, конечно, грубо, потому что на сообщениях можно писать на всех;)) Стандартную поддержку замены кода соответствующим библиотечным кодом оценим в зависимости от мощности этой поддержки — до 50 баллов (Эрланговая примитивна и недостаточна для случаев конверсии межпроцессной логики, но более простые случаи исполняет "на ура", дадим 30.)

Итого: Erlang — 80 баллов. Python — 70. Java (JVM) — 10. .NET — 10. По остальным — пусть расставляют те, кто их достаточно знает и может оценить.

Достаточно это для детерминации понятия мощности данной возможности? ;)
The God is real, unless declared integer.
Re[15]: Замена кода "на лету"
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.06.09 07:06
Оценка:
Здравствуйте, netch80, Вы писали:

N>А теперь если сравнить, например, с Java (сразу дисклеймер — все мои знания про эти её возможности только по документации) — организация кода в виде именованных классов с глобально уникальными именами (причём фиксированными в момент компиляции кода) резко усложняет возможность замены кода на лету, ибо существование двух одноимённых классов невозможно — а, значит, замена потребует

N>1) сохранения всех данных, хранимых в объектах этих классов, в некотором внешнем (для них) хранилище (в памяти, чтобы сохранить всякие открытые файлы)
N>2) собственно фазы перезагрузки кода
N>3) восстановления состояния из хранилища

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


N>Насколько я знаю, в .NET точно так же. Если ошибаюсь — исправьте, это будет мне полезно в плане оценки, куда двигать систему дальше.


В .NET несколько другой механизм.
Единица загрузки в .NET — сборка, единица выгрузки — домен. В один домен может быть загружено несколько сборок с одинаковыми именами (если они не strongname). Кроме того есть механизм shadowcopy, который позволяет не лочить образ на диске при заргрузке кода (это обегчает деплой нового кода).

Теперь как выглядит процесс.
1)Содается новый домен, туда грузится код, с которым идет взаимодействие через IPC, если появился новый код (даже в сборке с тем же именем), то он спокойно грузится в домен и новые запросы запускаются на него, сатрый код при этом никуда не девается и клиенты продолжают работать с ним.
2)Создается счетчик загрузок для домена, когда он достигает определенного числа новые сбокри перестают грузиться в домен и создается новый домен для загрузки новых сборок.
3)Каждый домен внутри себя считает количество клиентов, так как через IPC не поддерживаются механизмы управления временем жизни. Когда домен закрыт и нету клиентов, то он выгружается.

Естественно реализацию этого всего надо делать ручками, а сложность там немаленькая.

Что касается джавы, то там тоже все не так однозначно, как написано выше. Там есть класслоадеры, которые управляют загрузкой, так вот каждый класслоадер может загрузить свою копию класса.
Re[15]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 19.06.09 13:22
Оценка:
Здравствуйте, netch80, Вы писали:

N>Достаточно это для детерминации понятия мощности данной возможности?


Совсем другое дело.

Один вопрос. Что будет с Эрлангом, если у нового кода меняется контракт, например, изменлилось количество параметров у вызываемой функции?
Если нам не помогут, то мы тоже никого не пощадим.
Re[16]: Замена кода "на лету"
От: Курилка Россия http://kirya.narod.ru/
Дата: 19.06.09 14:04
Оценка: +1
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, netch80, Вы писали:


N>>Достаточно это для детерминации понятия мощности данной возможности?


IT>Совсем другое дело.


IT>Один вопрос. Что будет с Эрлангом, если у нового кода меняется контракт, например, изменлилось количество параметров у вызываемой функции?


Это будет уже другая функция, т.е. или разработчик предусмотрит такой вариант (добавит некий "переходник") или код "отвалится".
Сколь бы не были мощны возможности какой-либо платформы потребность думать, прежде чем делать, не отменяется
Re[17]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 19.06.09 14:06
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Сколь бы не были мощны возможности какой-либо платформы потребность думать, прежде чем делать, не отменяется


Т.е. без чудес. Ну и славненько.
Если нам не помогут, то мы тоже никого не пощадим.
Re[18]: Замена кода "на лету"
От: Курилка Россия http://kirya.narod.ru/
Дата: 19.06.09 14:12
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, Курилка, Вы писали:


К>>Сколь бы не были мощны возможности какой-либо платформы потребность думать, прежде чем делать, не отменяется


IT>Т.е. без чудес. Ну и славненько.


Ты ожидал увидеть внутри вечный двигатель?
Re[15]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 19.06.09 14:18
Оценка:
Здравствуйте, netch80, Вы писали:

N>А теперь если сравнить, например, с Java (сразу дисклеймер — все мои знания про эти её возможности только по документации) — организация кода в виде именованных классов с глобально уникальными именами (причём фиксированными в момент компиляции кода) резко усложняет возможность замены кода на лету, ибо существование двух одноимённых классов невозможно

Возможна, если другой одноимённый класс будет в другой ветке дерева ClassLoader'ов. Но по сути это для приложения анлогично "загрузить другую DLL".
Sapienti sat!
Re[19]: Замена кода "на лету"
От: IT Россия linq2db.com
Дата: 19.06.09 15:15
Оценка: :)
Здравствуйте, Курилка, Вы писали:

IT>>Т.е. без чудес. Ну и славненько.


К>Ты ожидал увидеть внутри вечный двигатель?


Скорее ответ на главный вопрос жизни, вселенной и всего такого
Если нам не помогут, то мы тоже никого не пощадим.
Re[16]: Замена кода "на лету"
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 20.06.09 08:10
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>В .NET несколько другой механизм.


[...]

Спасибо. Исправлю тогда цифровую оценку из предыдущего сообщения так: .NET — 35 (пока не видно ни одного средства нормальной автоматизации), JVM — 15. Всё это, конечно, на глаз и наугад (плюс/минус 10 от направления ветра), но для первичной прикидки сойдёт.

G>Единица загрузки в .NET — сборка, единица выгрузки — домен.


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

G>Естественно реализацию этого всего надо делать ручками, а сложность там немаленькая.


Угу.
The God is real, unless declared integer.
Re[16]: Замена кода "на лету"
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.06.09 10:52
Оценка:
Здравствуйте, Cyberax, Вы писали:
C>Возможна, если другой одноимённый класс будет в другой ветке дерева ClassLoader'ов. Но по сути это для приложения анлогично "загрузить другую DLL".
1. Гранулярность несколько другая. Хотя, чисто теоретически, никто не запрещает размещать каждый метод в отдельной либе.
2. В "классическом" неуправляемом приложении данные существуют совершенно отдельно от кода. Это означает, что можно поменять DLL, и следующий вызов DoSomeProcessing(&myOldData) пойдёт в новый код. В Java инстанс объекта жестко связан с классом; выгрузить класс, для которого есть достижимые экземпляры, афаик, нельзя. Это не проблема для stateless-приложений, но для стейтфул это тупик: сколько нового кода ни грузи, существующие объекты будут по-прежнему процесситься старым.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[17]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 22.06.09 11:08
Оценка:
Здравствуйте, Sinclair, Вы писали:

C>>Возможна, если другой одноимённый класс будет в другой ветке дерева ClassLoader'ов. Но по сути это для приложения анлогично "загрузить другую DLL".

S>1. Гранулярность несколько другая. Хотя, чисто теоретически, никто не запрещает размещать каждый метод в отдельной либе.
Гранулярность примерно одинаковая. Т.е. непрактично для большинства случаев.

S>2. В "классическом" неуправляемом приложении данные существуют совершенно отдельно от кода. Это означает, что можно поменять DLL, и следующий вызов DoSomeProcessing(&myOldData) пойдёт в новый код.

Обычный паттерн для перегружаемых unmanaged-приложений — это экспорт функциональности из библиотеки через абстрактные классы (или их аналог), так что тут особой разницы с Java нет.

Т.е. статических вызовов между компонентами разных библиотек не будет.

S>В Java инстанс объекта жестко связан с классом; выгрузить класс, для которого есть достижимые экземпляры, афаик, нельзя. Это не проблема для stateless-приложений, но для стейтфул это тупик: сколько нового кода ни грузи, существующие объекты будут по-прежнему процесситься старым.

Да, я про это и говорю.
Sapienti sat!
Re[18]: Замена кода "на лету"
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.06.09 11:26
Оценка:
Здравствуйте, Cyberax, Вы писали:
C>Гранулярность примерно одинаковая. Т.е. непрактично для большинства случаев.
В каком-то смысле да. Там, где динамические класслоадеры используются в полный рост — в вебприложениях — ничуть не хуже себя ведут и ISAPI.

C>Обычный паттерн для перегружаемых unmanaged-приложений — это экспорт функциональности из библиотеки через абстрактные классы (или их аналог), так что тут особой разницы с Java нет.

Есть. Абстрактный класс — это структура VMT; его реализация — состав VMT. Подменив библиотеку, мы получим при myOldObject.VirtualMethod() вызов нового кода — из-за того, что указатель на VMT теперь указывает куда надо. Ну, то есть это как я понимаю смысл вопроса — на практике такое я не применял никогда; обычно плагинные неуправляемые приложения всё же убивают экземпляры при перезагрузке плагинов.

C>Да, я про это и говорю.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 22.06.09 11:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

C>>Гранулярность примерно одинаковая. Т.е. непрактично для большинства случаев.

S>В каком-то смысле да. Там, где динамические класслоадеры используются в полный рост — в вебприложениях — ничуть не хуже себя ведут и ISAPI.
Ну да. Поэтому такой случай и неинтересен.

C>>Обычный паттерн для перегружаемых unmanaged-приложений — это экспорт функциональности из библиотеки через абстрактные классы (или их аналог), так что тут особой разницы с Java нет.

S>Есть. Абстрактный класс — это структура VMT; его реализация — состав VMT. Подменив библиотеку, мы получим при myOldObject.VirtualMethod() вызов нового кода — из-за того, что указатель на VMT теперь указывает куда надо.
Ты что? Ссылка на VMT сохраняется в каждом объекте, при загрузке новой библиотеки новые объекты будут получать ссылку на новую VMT, а старые так и будут со старой таблицей работать.

S>Ну, то есть это как я понимаю смысл вопроса — на практике такое я не применял никогда; обычно плагинные неуправляемые приложения всё же убивают экземпляры при перезагрузке плагинов.

Не обязательно.
Sapienti sat!
Re[20]: Замена кода "на лету"
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.06.09 03:31
Оценка:
Здравствуйте, Cyberax, Вы писали:
C>Ты что? Ссылка на VMT сохраняется в каждом объекте, при загрузке новой библиотеки новые объекты будут получать ссылку на новую VMT, а старые так и будут со старой таблицей работать.
Хм. Интересно, куда будет показывать ссылка на VMT, и куда будут показывать слоты VMT после того, как код был выгружен.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: Замена кода "на лету"
От: Cyberax Марс  
Дата: 23.06.09 06:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

C>>Ты что? Ссылка на VMT сохраняется в каждом объекте, при загрузке новой библиотеки новые объекты будут получать ссылку на новую VMT, а старые так и будут со старой таблицей работать.

S>Хм. Интересно, куда будет показывать ссылка на VMT, и куда будут показывать слоты VMT после того, как код был выгружен.
Как куда? В invalid memory, как обычно. Поэтому, выгружать надо только когда убедился, что не осталось ссылок на старую библиотеку.

Ну или загружать новую библиотеку параллельно старой.
Sapienti sat!
Re[22]: Замена кода "на лету"
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.06.09 07:13
Оценка:
Здравствуйте, Cyberax, Вы писали:
S>>Хм. Интересно, куда будет показывать ссылка на VMT, и куда будут показывать слоты VMT после того, как код был выгружен.
C>Как куда? В invalid memory, как обычно. Поэтому, выгружать надо только когда убедился, что не осталось ссылок на старую библиотеку.
C>Ну или загружать новую библиотеку параллельно старой.
То есть всё то же самое. Хотя и можно нагнуться и сделать late binding, опасностей от этого будет больше, чем бенефитов.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: Замена кода "на лету"
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.06.09 12:52
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Cyberax, Вы писали:

C>>Ты что? Ссылка на VMT сохраняется в каждом объекте, при загрузке новой библиотеки новые объекты будут получать ссылку на новую VMT, а старые так и будут со старой таблицей работать.
S>Хм. Интересно, куда будет показывать ссылка на VMT, и куда будут показывать слоты VMT после того, как код был выгружен.

А куда в яве указывают? Там же без проблем можно отдельные классы загружать.

Среда управляемая. Все ссылки известны. Технических проблем проверить отсутствие ссылок на типы из старой сборки нет. Так что это какая-то недоработка в CLR. В Яве такое работает.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[22]: Замена кода "на лету"
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.06.09 03:51
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>А куда в яве указывают? Там же без проблем можно отдельные классы загружать.
Выгрузить класс, у которого есть живые экземпляры, нельзя.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Замена кода "на лету"
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.06.09 11:51
Оценка:
Здравствуйте, Sinclair, Вы писали:

VD>>А куда в яве указывают? Там же без проблем можно отдельные классы загружать.

S>Выгрузить класс, у которого есть живые экземпляры, нельзя.

Это и не является проблемой. Главное, что нет нужды выгружать целое приложение только потому, что нужно заменить версию класса. Так что это скорее недоработка CLR.

В прочем, лично меня бы очень устроила бы реализация SIP-ов из Сингулярити.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Замена кода "на лету"
От: Michael7 Россия  
Дата: 02.07.09 19:24
Оценка:
Здравствуйте, md03t4, Вы писали:

M>Я знаю, что subj реализован в Erlang-е.

M>Есть ли еще языки/системы, где реализован похожий функционал?

Common Lisp, SmallTalk, если я правильно понял.
Re[2]: Замена кода "на лету"
От: LaptevVV Россия  
Дата: 06.07.09 07:21
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Со средней гранулярностью (единица загрузки — класс/модуль)

LCR>Java, Ocaml

LCR>С большой гранулярностью (единица загрузки — домен)

LCR>.net 1.0

Добавлю еще сюда БлэкБокс с Компонентным паскалем. Единица загрузки — модуль.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.