Lib-ы которым нужен явный init/deinit
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 24.03.08 11:56
Оценка:
Доброго дня!

Столкнулся с библиотекой OTL, для которой в начале программы нужно сделать явную инициализацию посредством вызова otl_initialize, а затем -- otl_terminate:
int main() {
  otl_connect::otl_initialize();
  ...
  otl_connect::otl_terminate();
}


Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.

Спасибо.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Lib-ы которым нужен явный init/deinit
От: Conr Россия  
Дата: 24.03.08 12:34
Оценка: 19 (1)
Здравствуйте, eao197, Вы писали:

E>Столкнулся с библиотекой OTL, для которой в начале программы нужно сделать явную инициализацию посредством вызова otl_initialize, а затем -- otl_terminate:

E>
E>int main() {
E>  otl_connect::otl_initialize();
E>  ...
E>  otl_connect::otl_terminate();
E>}
E>


E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.


Сходу только Botan и libcurl вспоминаются.
Re: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 24.03.08 12:35
Оценка: 19 (1)
Здравствуйте, eao197, Вы писали:

E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.



По-моему это очень распространённая практика. Вот что дал беглый проход по библиотекам для работы с XML:

Apache Portable Runtime (http://apr.apache.org/docs/apr/0.9/group__apr__library.html):
apr_initialize()/apr_terminate()

Xerces-C++ (http://xerces.apache.org/xerces-c/apiDocs/classXMLPlatformUtils.html#378a0935e1d80c64b7a53dc35baad8f6):
XMLPlatformUtils::Initialize()/XMLPlatformUtils::Terminate()

libxml2 (http://xmlsoft.org/html/libxml-globals.html#xmlInitGlobals):
xmlInitializeGlobalState()

libcurl (http://curl.haxx.se/libcurl/c/libcurl-tutorial.html):
curl_global_init()


Более того, иногда требуется, что бы функция инициализации вызывалась глобально *и* для каждого потока в отдельности. Например: COMInitialize(). Я лично тоже так зачастую делаю.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Lib-ы которым нужен явный init/deinit
От: zaufi Земля  
Дата: 24.03.08 13:37
Оценка: 19 (1)
ну и в догонку libltdl (портабельная работа с динамиескими библами. часть libtool'a) требует lt_dlinit/lt_dlexit
Re: Lib-ы которым нужен явный init/deinit
От: Mazay Россия  
Дата: 24.03.08 13:47
Оценка: 19 (1) +1 :)
Здравствуйте, eao197, Вы писали:

E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.


Дык хотя бы srand() для CRT'шного rand()

Или посерьёзнее: Библиотека от Агнера Фога
Главное гармония ...
Re: Lib-ы которым нужен явный init/deinit
От: uzhas Ниоткуда  
Дата: 24.03.08 19:52
Оценка:
E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.

E>Спасибо.


Лично я считаю наличие таких функций моветоном.
Инициализация _библиотеки_ — крайне бессмысленное понятие и должно быть спрятано от пользователя этой библиотеки. Это наследие си (где полно глобальных функций).
Re: Lib-ы которым нужен явный init/deinit
От: Roman Odaisky Украина  
Дата: 24.03.08 20:11
Оценка:
Здравствуйте, eao197, Вы писали:

E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.


Да хотя бы WSAInitialize/WSACleanup из Winsock.

А вот <iostream> инициализирует свои объекты правильно.
До последнего не верил в пирамиду Лебедева.
Re[2]: Lib-ы которым нужен явный init/deinit
От: MasterZiv СССР  
Дата: 24.03.08 20:44
Оценка: 1 (1) +1
uzhas пишет:

> Лично я считаю наличие таких функций моветоном.

> Инициализация _библиотеки_ — крайне бессмысленное понятие и должно быть
> спрятано от пользователя этой библиотеки.

Абсолютно не согласен. В С++ дофига проблем с инициализациий
статических глобальных данных (взять например проблему
потокобезопасной инициализации singleton-ов). А наличие такой функции
инициализации легко и просто разрешает проблему. И является
чуть ли не единственным способом сделать эту инициализацию вообще.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 24.03.08 22:01
Оценка:
Здравствуйте, uzhas, Вы писали:

E>>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.


E>>Спасибо.


U>Лично я считаю наличие таких функций моветоном.

U>Инициализация _библиотеки_ — крайне бессмысленное понятие и должно быть спрятано от пользователя этой библиотеки. Это наследие си (где полно глобальных функций).


Ну хорошо, допустим функцию инициализации для процесса можно заменить ленивой инициализацией, заплатив дополнительной проверкой на основном пути. Допустим, функцию деинициализации для процесса можно вообще опустить, или зарегистрировать atexit(). Допустим инициализацию для потока можно тоже сделать ленивой. НО КАК БЫТЬ С ДЕИНИЦИАЛИЗАЦИЕЙ ДЛЯ ПОТОКА?
Как ты предлагаешь делать? Не освобождать ресурсы, связанные с потоком? А если приложение создаёт и рушит по 100 потоков в секунду?



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Lib-ы которым нужен явный init/deinit
От: c-smile Канада http://terrainformatica.com
Дата: 24.03.08 23:13
Оценка: 26 (2)
Здравствуйте, eao197, Вы писали:

E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.


htmlayout static lib имеет Initialize/Finalize методы по двум соображениям:

1) не определен порядок статических конструкторов/деструкторов в lib, а надо.
2) тулзы проверющие расход памяти очень себя неадекватно ведут.
3) очень умный линковщик может выкинуть объекты инициализированные статически но которые нужны.

Например файл behavior_path.cpp

struct path: public behavior
{
    // ctor
    path(): behavior(HANDLE_DRAW, "path") {}
    ...
};

// instantiating and attaching it to the global list
path path_instance;


включенный в статическую библиотеку будет викинут линковщиком хотя инстанс:
  path path_instance; // instantiating and attaching it to the global list

нужен в коде.
Re: Lib-ы которым нужен явный init/deinit
От: Аноним  
Дата: 26.03.08 13:45
Оценка:
Здравствуйте, eao197, Вы писали:

E>Столкнулся с библиотекой OTL, для которой в начале программы нужно сделать явную инициализацию посредством вызова otl_initialize, а затем -- otl_terminate:

E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.

здесь упоминали про <iostream> (cout, cin..)
в главе 21(вроде. НО про потоки) у Страутсрупа (3изд) есть пара страниц на метод инициализации глобальных объектов
Re: Lib-ы которым нужен явный init/deinit
От: iyura  
Дата: 26.03.08 15:39
Оценка: 19 (1)
Здравствуйте, eao197, Вы писали:

E>Доброго дня!


E>Столкнулся с библиотекой OTL, для которой в начале программы нужно сделать явную инициализацию посредством вызова otl_initialize, а затем -- otl_terminate:

E>
E>int main() {
E>  otl_connect::otl_initialize();
E>  ...
E>  otl_connect::otl_terminate();
E>}
E>


E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.


E>Спасибо.


Stingray... например Objective Grid
Re[3]: Lib-ы которым нужен явный init/deinit
От: Pzz Россия https://github.com/alexpevzner
Дата: 27.03.08 01:14
Оценка: 20 (1)
Здравствуйте, remark, Вы писали:

R>Ну хорошо, допустим функцию инициализации для процесса можно заменить ленивой инициализацией, заплатив дополнительной проверкой на основном пути. Допустим, функцию деинициализации для процесса можно вообще опустить, или зарегистрировать atexit(). Допустим инициализацию для потока можно тоже сделать ленивой. НО КАК БЫТЬ С ДЕИНИЦИАЛИЗАЦИЕЙ ДЛЯ ПОТОКА?

R>Как ты предлагаешь делать? Не освобождать ресурсы, связанные с потоком? А если приложение создаёт и рушит по 100 потоков в секунду?

В винде в статической библиотеке — повесьте отдельный поток, который следит за завершением тех потоков, о которых знает Ваша библиотека, и подчищает за ними.

В виндовой DLL функции DllMain сообщают о приходе/уходе потоков. Реально эти нотификации можно получить и в статической библиотеке, но я не очень знаю, как.

В юниксе можно создать TLS-объект с деструктором, его позовут при завершении потока.

Так что непреодолимых проблем нет
Re: Оцените решение
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.03.08 07:09
Оценка:
Спасибо всем, кто привел свои примеры в данной теме. Стало понятно, что подобная инициализация широко используется и, как говорит c-smile, временами только она и работает надежно.

Мне эта информация нужна была для решения одной задачки: у меня есть программы, написанные с использованием плагинов. Т.е. существует некая стандартная реализация main(), в которой запускается плагинная система. Эта система затем грузит DLL-ки с плагинами и стартует сами плагины на основании информации из конфигурационных файлов. Одному из плагинов потребовалось использовать OTL и встал вопрос: как и когда вызывать otl_initialize/otl_terminate? Этот вопрос сложен еще и тем, что плагины загружаются и стартуют не на главной нити приложения, а на каких-то рабочих нитях.

В результате появилась следующая идея. Штатная реализация функции main получает вид:
int main( int argc, char ** argv ) {
  try {
    custom_app_init( argc, argv );
    ... остальные действия для системы плагинов ...
  }
  catch( const std::exception & x ) {
    ...
  }
}


Где, по умолчанию, функция custom_app_init() пустая, не содержит никаких действий. Когда появляется необходимость инициализации 3rd party библиотек, программист пишет свою реализацию custom_app_init() вида:
class otl_starter_stopper_t {
  public :
    otl_starter_stopper_t() { otl_connect::otl_initialize(); }
    ~otl_starter_stopper_t() { otl_connect::otl_terminate(); }
};

void
custom_app_init() {
  static otl_starter_stopper_t otl_starter;
}


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

Если приложению потребуется инициализация нескольких библиотек, то для каждой библиотеки в custom_app_init() должна быть своя статическая переменная:
void
custom_app_init() {
  static otl_starter_stopper_t otl_starter;
  static libxms2_initializer_t xml2_initializer;
  static libcurl_initializer_t libcurl_initializer;
}


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

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

Может кто-нибудь подсказать, какие здесь есть подводные камни?

Более подробную информацию о том, зачем мне это понадобилось, можно найти здесь


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: 27.4.2.1.6
От: gear nuke  
Дата: 27.03.08 09:02
Оценка: 19 (1)
Здравствуйте, eao197,

Фактически так и сделано в Standard I/O library, только с подсчётом ссылок

27.4.2.1.6/1 The class Init describes an object whose construction ensures the construction of the eight objects
declared in <iostream> (27.3) that associate file stream buffers with the standard C streams provided for
by the functions declared in <cstdio> (27.8.2).

People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[4]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 27.03.08 10:44
Оценка:
Здравствуйте, Pzz, Вы писали:

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


R>>Ну хорошо, допустим функцию инициализации для процесса можно заменить ленивой инициализацией, заплатив дополнительной проверкой на основном пути. Допустим, функцию деинициализации для процесса можно вообще опустить, или зарегистрировать atexit(). Допустим инициализацию для потока можно тоже сделать ленивой. НО КАК БЫТЬ С ДЕИНИЦИАЛИЗАЦИЕЙ ДЛЯ ПОТОКА?

R>>Как ты предлагаешь делать? Не освобождать ресурсы, связанные с потоком? А если приложение создаёт и рушит по 100 потоков в секунду?

Pzz>В винде в статической библиотеке — повесьте отдельный поток, который следит за завершением тех потоков, о которых знает Ваша библиотека, и подчищает за ними.


Pzz>В виндовой DLL функции DllMain сообщают о приходе/уходе потоков. Реально эти нотификации можно получить и в статической библиотеке, но я не очень знаю, как.


Pzz>В юниксе можно создать TLS-объект с деструктором, его позовут при завершении потока.


Pzz>Так что непреодолимых проблем нет


Согласен — с помошью отдельного потока можно более-менее решить.
Но останется та же засада, что и в WinSock (где работа с сетью вынесена в отдельный поток) — невозможно отлаживать в отладчике. Плюс — не понятно с какой частотой запускать процесс чистки. Синхронно при удалении потока нотифицировать не получится, а отложенно — непонятно сколько мусора накопится. Я, например, могу сделать ограничение для пользователя — что бы одновременно существовало не более N потоков работающих с библиотекой. С асинхронной сборкой это условие придётся переписать как — что бы одновременно существовало не более N потоков работающих с библиотекой + не создавайте потоки *слишком часто*, что такое *слишком часто* определяйте на практике методом тыка
Ну в общем не очень красиво получается.

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

Идеально было бы получать нотификации о создании/удалении потоков, но не с помощью отдельной динамической библиотеки. Но как это захачить под Win32, я не видел... Поищу в форуме Win32 — может кто знает...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Lib-ы которым нужен явный init/deinit
От: Sergey Россия  
Дата: 27.03.08 11:22
Оценка: 30 (1)
> Идеально было бы получать нотификации о создании/удалении потоков, но не с
> помощью отдельной динамической библиотеки. Но как это захачить под Win32,
> я не видел... Поищу в форуме Win32 — может кто знает...

IMHO, в случае статической либы это можно захачить только если CRT тоже
прилинкована статически. Подробности можно посмотреть в boost::thread, в
реализации очистки tss. Смысл метода в том, что для очистки связаных с
потоком вещей сама CRT должна откуда-то получать нотификации. Ну она их и
получает, и при желании туда можно вклинится — там насколько помню есть
специальным образом названная PE-секция, и все что в ней лежит CRT считает
коллбэками на функции зачистки. То ли статья, то ли развернутый пост в
форуме про этот способ были на кодепроджекте. Другие способы широкой
общественности вроде как не известны. Я правда года два назад этим вопросом
интересовался, может чего и появилось с тех пор.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[5]: Lib-ы которым нужен явный init/deinit
От: Pzz Россия https://github.com/alexpevzner
Дата: 27.03.08 11:33
Оценка:
Здравствуйте, remark, Вы писали:

R>Согласен — с помошью отдельного потока можно более-менее решить.

R>Но останется та же засада, что и в WinSock (где работа с сетью вынесена в отдельный поток) — невозможно отлаживать в отладчике.

Что именно отлаживать? Поток, подчищающий за другими потоками?

R> Плюс — не понятно с какой частотой запускать процесс чистки. Синхронно при удалении потока нотифицировать не получится, а отложенно — непонятно сколько мусора накопится.


Завершение потока можно ждать с помощью WaitFor...(). Совершенно не обязательно устраивать поллинг.

R>С динамической библиотекой — с одной стороны лучше, но с другой свои проблемы. Заставять пользователя таскать за собой отдельную библиотеку...


R>Идеально было бы получать нотификации о создании/удалении потоков, но не с помощью отдельной динамической библиотеки. Но как это захачить под Win32, я не видел... Поищу в форуме Win32 — может кто знает...


Нотификации есть, но хорошо запрятаны. За 10 минут поиска по MSDN'у я не смог их найти
Re[6]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 27.03.08 12:02
Оценка:
Здравствуйте, Pzz, Вы писали:

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


R>>Согласен — с помошью отдельного потока можно более-менее решить.

R>>Но останется та же засада, что и в WinSock (где работа с сетью вынесена в отдельный поток) — невозможно отлаживать в отладчике.

Pzz>Что именно отлаживать? Поток, подчищающий за другими потоками?


Да вообще всё.
Вот проходишь отладчиком по функции send(), а ничего на самом деле не отослалось. И когда отошлётся — не понятно.


R>> Плюс — не понятно с какой частотой запускать процесс чистки. Синхронно при удалении потока нотифицировать не получится, а отложенно — непонятно сколько мусора накопится.


Pzz>Завершение потока можно ждать с помощью WaitFor...(). Совершенно не обязательно устраивать поллинг.


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


R>>С динамической библиотекой — с одной стороны лучше, но с другой свои проблемы. Заставять пользователя таскать за собой отдельную библиотеку...


R>>Идеально было бы получать нотификации о создании/удалении потоков, но не с помощью отдельной динамической библиотеки. Но как это захачить под Win32, я не видел... Поищу в форуме Win32 — может кто знает...


Pzz>Нотификации есть, но хорошо запрятаны. За 10 минут поиска по MSDN'у я не смог их найти


Да. Я тоже ничего не нахожу. Вообще глупо — понятно, что эта функциональность есть в Win, но почему она работает только для dll?! Почему нельзя сделать что-то типа RegisterThreadMonitor()? Или на худой конец — at_thread_exit(), что б можно было эмулировать объекты с деструкторами в TLS...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 27.03.08 12:15
Оценка:
Здравствуйте, Sergey, Вы писали:


>> Идеально было бы получать нотификации о создании/удалении потоков, но не с

>> помощью отдельной динамической библиотеки. Но как это захачить под Win32,
>> я не видел... Поищу в форуме Win32 — может кто знает...

S>IMHO, в случае статической либы это можно захачить только если CRT тоже

S>прилинкована статически. Подробности можно посмотреть в boost::thread, в
S>реализации очистки tss. Смысл метода в том, что для очистки связаных с
S>потоком вещей сама CRT должна откуда-то получать нотификации. Ну она их и
S>получает, и при желании туда можно вклинится — там насколько помню есть
S>специальным образом названная PE-секция, и все что в ней лежит CRT считает
S>коллбэками на функции зачистки. То ли статья, то ли развернутый пост в
S>форуме про этот способ были на кодепроджекте. Другие способы широкой
S>общественности вроде как не известны. Я правда года два назад этим вопросом
S>интересовался, может чего и появилось с тех пор.


Да. Действительно. Я ведь там смотрел. Но куда-то не туда посмотрел, и решил, что они всё ещё требуют чтобы thread был как dll под win32.
Вот статья:
http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/

Реализация в libs\thread\src\tss_pe.cpp

То, что работает только со статическим ран-таймом я пока не нашёл. И это очень многообещающе.
Там только написано:
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && defined(_MSC_VER)

И в статье написано только:
Environment: Visual C++ 6 and above (may work on earlier versions too), for .exe's and DLL's running under Windows 95 and later, including console apps.




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.