Новая Thread-модель C6 - как всегда через одно место!

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Гость

Сообщение Гость »

Здравствуйте!

Помнится тут недавно была небольшая "разборка" насчет использования явных и неявных конструкторов-деструкторов.
Большинство коллег (в том числе и я), кроме Вадима, сошлись на том, что использование неявных Construct/Destruct для классов не есть криминал а даже наоборот - круто и удобно.

Теперь я хочу поправиться - БЫЛО удобно и надежно до выхода последней версии C60!
Как я уже упоминал в этой рассылке, разработчики в одном из релизов C60 изменили порядок неявной инициализации обьектов.
Чем внесли приличный бардак в ранее стройную систему инициализации.
Они неявно это и сами признали, введя в последних релизах C6 новый ключ проектной системы для компилятора init_priority, позволяющий разработчику в случае необходимости задавать явный порядок инициализации своих модулей. Вплоть до того, что можно инициализировать свои модули вообще в первую очередь.
Можно сказать - удобно! НО! Удобно, если четко знаешь порядок инициализации ВСЕХ обьктов программы! В том числе конструкторов ядра и драйверов. Но об этом, как всегда, разработчики SV забыли нас проинформировать! А не имея такой инфы, вышеупомянутый ключ просто превращается в мертвую опцию, которую рискнет использовать лишь экстремал-экспериментатор!

Но и это не все!
Разработчики так-же ЗАБЫЛИ упомянуть, что вместе с системой инициализации обьектов подверглась "переработке" и система их уничтожения! Причем настолько круто, что я просто пребываю в небольшом шоке! Возможно я чего не понимаю, но тому, что они сделали с шатдауном программы я не могу найти приличного определения!
А именно - при сборке приложения с внешними либами, без использования DLL (режим сборки Local), при завершении приложения сначала уничтожаются все глобальные обьекты библиотеки а уже потом - глобальные статические экземпляры, порожденные классами этой библиотеки!
Т.е., предположим, подключили к программе некую либу, которая содержит реализацию класса MyClass.
Для связи различных экземпляров этого класса или для других каких целей в этой либе обьявлены некие глобальные обьекты.
Конструктор и деструктор класса MyClass этой либы использует каким-то образом эти глобальные обьекты. Никакого криминала нет! Даже используем синхронизацию доступа к этим глобальным обьектам. Вообщем - все по правилам!
Теперь в секции глобальных данных программы пишем:

NewClass MyClass ! или CLASS(MyClass).

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

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

А перейти к так любимой Вадимом системе явных Init/Kill, увы, не получается - теряется часть функционала.

Ну, ладно - поплакался и достаточно - пойду посплю!
Может и правда - "утро вечера мудренее" - встану "утром" ближе к обеду:)) - глядишь и проблема сама собой "рассосется"!?

Удачи!

=============================
С уважением, Олег А. Руденко.
Oleg_Rudenko@mail.ru
Oleg_Rudenko@mail333.com
Библиотека DynaLib
http://dynalib.narod.ru

(Добавление)

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

Предположим в либе есть глобальная очередь, в которой регистрируются экземпляры, созданные классами этой либы.
Естественно, что конструктор экземпляра заносит запись о себе в эту очередь, а деструктор убирает эту запись из очереди. При такой ситуации вышеописанна проблема не приведет к GPF при доступе деструктора к глобальной очереди. Но, как я уже писал, для этой очереди уже будет выполнен ее деструктор, который уничтожит все внутренние буфера. А при ЛЮБОМ действии с такой очередью производится повторная инициализация всех этих внутренних буферов.

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

И если ОС корректно не "подчистит" за такой прогой "хвосты", то получим "высячую" память и, кроме того, еще и выбывшие из оборота дескрипторы памяти, кол-во которых у ОС типа W9x имеет тенденцию очень быстро уменьшаться!

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

=============================
С уважением, Олег А. Руденко

(Добавление)

Грустно, однако!

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

Кстати, в первом письме я уже упоминал о ключе компилятора, для явного задания приоритета модулей при инициализации.
Так вот, оказывается этот ключ действует и на приоритет деинициализации модулей. Вот только не так, как ожидалось.
Может я не прав, но я всегда следовал правилу FILO (первым вошел, последним вышел). Т.е., если какой-либо модуль инициализируется первым, то этот-же модуль должен уничтожаться последним. Иначе просто-напросто нарушаются рамки вложения процессов инициализации/деинициализации.
Однако разработчики SV считают по другому - если модуль был инициализирован первым, то и деинициализация его производится так-же первым. Бред, имхо!

Итак, возвращаемся к теме.
Предположим имеем все ту-же либу MyLib, которая линкуется к приложению в режиме Local. В этой либе есть класс MyClass и глобальная очередь регистрации экземплятор этого класса MyClassQueue. Полностью следуем рекомендации SV о том, что желательно глобальные данные делать трейдовыми и обьявляем эту очередь как MyClassQueue QUEUE,THREAD.

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

MyFirstClass MyClass,THREAD

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

Как и в предыдущем письме, здесь так-же имеем:
- при завершении трейда первым будет выполнена деинициализация трейдовых обьектов самой либы MyLib.
При этом будет вызван деструктор для очереди MyClassQueue, который освободит память, занятую всеми внутренними управляющими структурами этой очереди.
- следом будет выполнена деинициализация трейдовых обьектов уже программы. При этом будет вызван деструктор экземпляра MyFirstClass.
Мало того, что мы получим в этот момент уже очищенные глобальные трейдовые статические переменные и уничтоженные динамические (т.е. уже имеем потенциальные проблемы, могущие привести как неверной логике последующей работы программы, так и к банальному GPF при обращении к динамическому глобальному трейдовому обьекту.
Мы стабильно получаем повторную иниицализацию очереди MyClassQueue с выделением памяти для ее внутренних управляющих структур.
- полное завершение трейда с потерей памяти, выделенной на предыдущем шаге для внутренних структур очереди MyClassQueue!

Вышеописанных проблем можно избежать ТОЛЬКО в случае обьявления экземпляра MyFirstClass в секции локальных данных процедуры, в которой он используется. В этом случае ВСЕГДА первыми отрабатывают деструкторы локальных обьектов.
Правда, тогда непонятно, что делать, если необходим глобальный экземпляр по отношению к текущему трейду?!

Получаем, как это ни печально, вывод - использование во внешних либах ЛЮБЫХ глобальных обьектов потенциально чревато проблемами при использовании классов этих либ. Вот такой вот неутешительный вывод!

2Сергей Чушкин.
Может ты, все-таки, попробуешь донести до разработчиков SV информацию о данной проблеме. Я как-то пытался им обьяснить, что их новый порядок инициализации обьектов потенциально ведет к нестабильной работе приложения. Они тогда только отмахнулись - "у нас все нормально - у самого кривые руки"!
Правда, их что-то все таки заставило ввести этот ключ init_priority.
И вот теперь еще одна проблема - уже с порядком деинициализации обьектов.
Мне, честно говоря, уже даже и нехочется с ними общаться по этому поводу! Но что-то делать надо-же!
Или пускай так прямо и напишут в доке - "в связи с новой логикой иниицализации/деинициализации обьектов НЕ рекомендуется использовать в готовых библиотеках (LIB-модули) глобальные обьекты, которые будут использоваться конструкторами/деструкторами классов этой библиотеки" !!!

=============================
С уважением, Олег А. Руденко

(Добавление)
Я как-то пытался им обьяснить, что их новый порядок инициализации обьектов потенциально ведет к нестабильной работе приложения. Они тогда только отмахнулись - "у нас все нормально - у самого кривые руки"!
ТАМ, в SV работают больные люди, им надо терпеливо и настойчиво указывать на их ошибки. Пости эту инфу в clarion6 на их новостной сервак, с периодичностью раз в месяц. Тогда межет и будет эффект. Подобные проблемы ставят под вопрос готовность C6 вообще, что конечно очень грустно. Думаю "широкой" кларионовской общественности это не очень понравится и SV вынуждены будут принимать меры. Они конечно будут ругаться и посылать тебя в закрытую группу, bugreports или как она там называется. Но ее-то не читают потенциальные клиенты, значит и пинок получится слабым. А им хороший пинок нужен, волшебный такой пендаль.
Мне, честно говоря, уже даже и нехочется с ними общаться по этому поводу! Но что-то делать надо-же!
Угу, а кому сейчас легко.

Удачи!
__________________________________
Владимир Якимченко (IСQ 16 993 194)
При завершении трейда имеем абсолютно ту-же картину.
В том-то и дело, что лики памяти у завершающегося процесса никого не волнуют - процесс умер, вся память отошла системе. А вот в случае потоков действительно грустно получается :(

--
Best regards,
Maxim Yemelyanov,
Enigma Soft Company
phone: +380 572 177977
WEB: http://enigmasoft.com.ua
e-mail: clalist@enigmasoft.com.ua
ICQ: 12253836
Написал: ClaList(2)
Гость

Сообщение Гость »

Слишком много переводить надо!
А у меня проблемы с формированием осмысленного англ.текста.
Тут ведь как - чуть ошибешься в склонении или времени и получится уже совершенно другой смысл!

=============================
С уважением, Олег А. Руденко

А не надо много объяснять что, как и почему. Маленький примерчик и вопрос - откуда GPF. И пусть сами репу чешут. А то опять сам дурак будешь.

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

ЗЫ. Твое сообщение как раз вовремя. В пятницу народ звонил, жаловался на GPF при выходе из проги на C6.

WBR, Nick Tsigouro. MailTo:Nick@arsis.ru

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

Я вот тут думал о шаблонной генерации... Не о кларе, а вообще... О своем движке..

Зачем ограничиваться одной парой для каждого языка: gui тулкит - библиотека БД?!
Я уже сейчас в могу сделать следующие вещи (что-то лучше, что-то хуже):

язык -- шаблонный тулкит -- библиотека БД:

перл:
тулкиты:
HTML::Template (я сейчас его использую не только для веба)
Template Toolkit (TT2)
Tk (десктопные приложения)
БД:
DBI (она там одна и самая лучшая)
С++:
тулкиты:
wxWindows (оконная библиотека под Win32/GTK/Motiff (то, что не винда))
MFC (только под win32, если кому-то надо?..)
БД:
libODBC (ODBC драйверы есть под многие СУБД под win32 и unix)
libdbi (крутая штука по мотивам perl-овой DBI, только драйверов БД мало)
php:
тулкиты:
Smarty
куча других (я php давно забросил)
БД:
родная php-шная
гы :)
можно даже для извращенцев для клары перенести стандартные или ШВС ;)
...куча-куча других, языков, тулкитов и библиотек которых я не знаю/не использую. Портеры всегда как из-под земли вырастают :)

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

Это позволит людям, работающим на 1-2 языках воспользоваться такой системой, не изучая новый для них язык.

Вот думаю, может кому-то идея тоже понравится, и можно будет на sf.net проект сделать? Одному лень, от писания десктопных приложений у меня тоска зеленая :)

--
Best regards,
Maxim Yemelyanov

Написал: ClaList(2)
Гость

Сообщение Гость »

...а вот сделали б клару проектом с открытыми исходниками
Что, свежую травку завезли? ;D
- открылось бы второе дыхание, и никакое финансирование не нужно - фанатов-энтузазыстов у клары хоть отбавляй. А так - загнется проект от жадности руководства разработчиков... А если и захотят сделать когда-нить открытым, или кто-то решит финансировать... Как бы поздно не оказалось.
А что - ещё не поздно? IMHO трупик-то остывает уже... :)
php:
тулкиты:
Smarty
куча других (я php давно забросил)
БД:
родная php-шная
???? Это КАКАЯ ЖЕ?! Я что-то пропустил в развитии PHP?
Или ты уже мюскуль родным считаешь? ;)
Вот думаю, может кому-то идея тоже понравится, и можно будет на sf.net проект сделать?
По пунктам:
1. Идея - нравится ;)
2. КАКОЙ проект?
3. КТО делать-то будет? И - ЧТО?
Одному лень, от писания десктопных приложений у меня тоска зеленая :)
ГЫ!!! (c) Ты :D

--
С уважением,
Степанец Александр Валентинович.
...а вот сделали б клару проектом с открытыми исходниками - открылось бы второе дыхание, и никакое финансирование не нужно - фанатов-энтузазыстов у клары хоть отбавляй.
Не получилось бы так как было с Netscape :(
Вот думаю, может кому-то идея тоже понравится, и можно будет на sf.net проект сделать? Одному лень, от писания десктопных приложений у меня тоска зеленая :)
Кстати, а кто-нибудь следит, что там на clarionforge происходит? Там же люди собирались сделать что-то подобное.

--
Благодарень за терпение и понимание,
Ravenous mailto:gottmituns@mail.ru


(Добавление)
Не получилось бы так как было с Netscape :(
А что - "Netscape"? ;) НетШкаф-то Ожил... :D
Взялись за старое... ;)
Кстати, а кто-нибудь следит, что там на clarionforge происходит? Там же люди собирались сделать что-то подобное.
А там вообще что-нибудь происходило? Кроме намерений, конечно... :)

--
С уважением,
Степанец Александр Валентинович.
ЗЫ. Твое сообщение как раз вовремя. В пятницу народ звонил, жаловался на GPF при выходе из проги на C6.
Попробую сделать небольшой пример.
Хотя, допускаю, что может получиться как в предыдущий раз - на реальных больших проектах имеем стабильный GPF, а в тестовом примере - все нормально.
Все таки, эти глюки при старте программы и ее завершении связаны именно с неверной таблицей Init/Kill модулей, которая строится компилятором. Поэтому тут очень многое зависит именно от обьема и количества разных модулей.

Кстати, обошел я эти глюки довольно просто - переписал классы синхронизации из модуля CWSYNCHC, вставив в них обязательное обNull-ение указателей в деструкторе и проверку на Null во всех остальных методах этих классов.
Писать там - "кот наплакал"!
Вот еще один пример, что НЕ НАДО экономить на проверках указателей и ОБЯЗАТЕЛЬНО Null-ить их при уничтожении, если этого не делает компилятор.

=============================
С уважением, Олег А. Руденко


(Добавление)
Вот думаю, может кому-то идея тоже понравится, и можно будет на sf.net проект сделать? Одному лень, от писания десктопных приложений у меня тоска зеленая :)

а чем не подходит Rational Rose?

--
Всего наилучшего, porutchik mailto:porutchik@mail.primorye.ru
http://personal.primorye.ru/porutchik/
---------------------------------------------------------
Советские боевые слоны - самые боевые слоны в мире!
Написал: ClaList(2)
Гость

Сообщение Гость »

Что, свежую травку завезли? ;D
это сезонное. старую скурили, теперь колбасит новыми идеями :)
Или ты уже мюскуль родным считаешь? ;)
Я имею в виду родные для php библиотечные функции для работы с различными БД:
mysql_*, ibase_*, OCI* и т.д.
1. Идея - нравится ;)
2. КАКОЙ проект?
В первом приближении: многоязыковая классово-шаблонная система генерации десктопных/web приложений, для раздельной генерации кода для user interface и для работы с БД.

Сейчас это работает как набор cgi-скриптов и perl-модулей под апачем.
3. КТО делать-то будет? И - ЧТО?
А кто его знает... Может я все-таки когда-нить займусь. Нетуть мотивации :) Все равно - нафиг никому оно не надо, я ее потихоньку пописываю себе...
Почему собсно возникла мысль о sf.net, и вообще о том, что это кому-то может быть нужно - т.к. существует Tk для перла, то можно не имея установленного апача поиметь такую систему в виде десктопного приложения на Tk. Которая заработает под win32 и X-Windows без к-либо настроек. Просто, очень не хочется отказываться от возможностей перлового парсера (для разбора SQL). Ну а если под рукой есть работающий веб сервер, то оно и так заработает. К тому же, набор контролов для веба и десктопных приложений несколько отличается. Не хотелось бы выходить за рамки HTML4.0 а ваять апплеты на яве (ведь ClarioNet так работает?). Поэтому и есть идея разделить GUI и DB части - можно будет то же самое в том или ином приближении генерить для разных платформ.
ГЫ!!! (c) Ты :D
Можно и так сказать...
Не хотелось бы выходить за рамки HTML4.0 а ваять апплеты на яве (ведь ClarioNet так работает?).
имелось в виду "и ваять"

--
Best regards,
Maxim Yemelyanov

(Добавление)
ваять апплеты на яве (ведь ClarioNet так работает
Нет не так. Зачем ему аплеты на яве в кларионовском приложении? Ему даже браузер не нужен. Никакой. Только HTTP.

WBR, Nick Tsigouro

Стоп. А о чем этот пост от 20.04.2004 :
Нет. Там совсем другая технология. Клиенту передается инфа о типе контрола и всех его атрибутах. А клиент с помощью CREATE создает на своем окне соотв. контрол и через ?Control{PROP:...} = ... управляет его поведением. Поэтому Для ?Image{Prop:Text} = ... нужен файл на клиенте. Короче. ?Image{Prop:Text} = '~File.ico' не поддерживается. Только ?Image{Prop:Text} = 'File.ico'.
Какой такой клиент, если есть только браузер? Так что же все-таки есть на стороне клиента?

Кстати, преимущества html, а не апплетов - я могу из lynx (консольный браузер) полноценно работать с html-формами.
Недавно ставил себе xFce а потом Gnome с нуля, из сорцов на голый юникс.
Замучился по факам лазить. Если б не lynx, пришлось бы искать машину, на которой установлен win32 или X-Windows, чтобы заюзать тамошний браузер.

--
Best regards,
Maxim Yemelyanov

Нет НИКАКОГО браузера. Есть только клиент, написаный на клаше. Поставляется в т.ч. частично в исходниках для кастомизации. Один единственный для всех случаев жизни. Точно так же как в TS, только кишки и возможности другие.
Удаленный терминал на клаше.

На серверной стороне есть IIS, если это через интернет/интранет. Или app server, если это локалка.

WBR, Nick Tsigouro

Тады непонятно, зачем HTTP. Клиент с сервером по HTTP что-ли обмениваются? =8-O
А зачем? Свой компактный протокол писать не стали? Или для буржуев с их каналами оверхед от заголовков HTTP траффиком не является?

--
Best regards,
Maxim Yemelyanov

Именно так.
А зачем? Свой компактный протокол писать не стали? Или для ...
Чтобы без вопросов проходить везде, где есть интернет..
... буржуев с их каналами оверхед от заголовков HTTP траффиком не является?
А чего это тебя в обычном браузере не волнует? И еще учти, что трафик в нем минимизирован. Ты проакцептил ENTRY. Значение ушло на сервер. А обратно придет не страничка целиком, как в обычном браузере, а только изменения текущей страницы. Т.е. "CHANGE(control,value)", и все. На скролирование в браузере придут новые верхние или нижние строки, на переключение закладок - "Select(NewTab)". И т.д. и т.п.

WBR, Nick Tsigouro

(Добавление)
А что - "Netscape"? ;) НетШкаф-то Ожил... :D
Взялись за старое... ;)
Сейчас как раз идет компания по "уговорам" SUN Microsystems, чтобы они открыли исходники JAVA.
По-этому поводу многие аналитики вспомнили эту историю с Netscape - когда открыли исходники народ посмотрел,ужаснулся и решили, что переписать заново будет намного проще чем править всю ту помойку.
Что собственно и сделали и на мой взгляд удачно.
А там вообще что-нибудь происходило? Кроме намерений, конечно... :)
Что-то делается. Даже шаблончики какие-то лежат 4-х месячной давности.

--
Благодарень за терпение и понимание,
Ravenous mailto:gottmituns@mail.ru
Написал: ClaList(2)
Ответить