2010-09-15 4 views
4

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

Как я не могу изменить sleeping_function() Я хочу начать несколько потоков, чтобы запустить несколько итераций моего цикла параллельно. Проблема в том, что эта функция внутренне использует некоторые глобальные переменные.

Есть ли способ рассказать компоновщику на SunOS, что я хочу связать определенные библиотеки таким образом, чтобы все переменные помещали их в локальное хранилище потоков?

+1

Хороший вопрос. Пожалуйста, Linux и Windows решения также. –

ответ

0

Я не думаю, что вы будете в состоянии добиться этого только компоновщика, но вы можете быть в состоянии получить что-то работает с некоторым кодом на C.

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

Некоторые псевдо-код, просто заменить вызовы sleeping_function с призывами call_sleeping_function_thread_safe:

char *shared_lib_name 

void sleeping_function_thread_init(char *lib_name); 

void call_sleeping_function_thread_safe() 
{ 
    void *lib_handle; 
    pthread_t pthread; 
    new_file_name = make_copy_of_file(shared_lib_name); 

    pthread_create(&pthread, NULL, sleeping_function_thread_init, new_file_name); 
} 

void sleeping_function_thread_init(char *lib_name) 
{ 
    void *lib_handle; 
    void (*)() sleeping_function; 

    lib_handle = dlopen(lib_name, RTLD_LOCAL); 
    sleeping_function = dlsym(lib_handle, "sleeping_function") 
    while (...) 
    sleeping_function; 
    dlclose(lib_handle); 
    delete_file(lib_name);  
} 

dlopen Для окон становится LoadLibrary и dlsym становится GetProcAddress ... и т.д., но основная идея будет работать.

+0

Это не сработает, так как мне нужно связать всю программу статически. – elmo

1

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

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

+0

Согласен, но это не тот случай. У меня есть доступ к источникам библиотеки, но я ничего не могу изменить и должен ссылаться на данный объект статической библиотеки. – elmo

+0

Это был один пример. Вы уверены, что библиотека не делает никаких предположений, что она работает в одном потоке? Даже неявные предположения? –

 Смежные вопросы

  • Нет связанных вопросов^_^