2010-09-15 64 views
4

我有一个程序,我与许多图书馆链接。我在探查器上运行我的应用程序,发现大部分时间都是在一些网络请求后用于“等待”状态。 这些请求是我的代码从外部库调用sleeping_function()的影响。 我在一个执行许多次循环的循环中调用这个函数,这样所有的等待时间总计为大量。如何链接非线程安全的库,以便每个线程都有它自己的全局变量?

因为我不能修改sleeping_function()我想开始几个线程来并行运行我的循环的几个迭代。问题是这个函数在内部使用了一些全局变量。

有没有办法告诉SunOS上的链接器,我想以某种方式链接特定的库,将所有变量从它们放置在线程本地存储中?

+1

不错的问题。请Linux/Windows解决方案也。 – 2010-09-15 13:22:54

回答

0

我不认为你就可以只用连接器来实​​现这一点,但你也许能够得到的东西与一些代码工作中C.

的问题是,调用加载已加载的库将返回对已加载实例的引用,而不是加载新副本。快速浏览dlopenLoadLibrary的文档似乎证实,无法多次加载相同的库,至少在您希望图像准备好执行时无法加载。避免这种情况的一种方法是防止操作系统知道它是同一个库。要做到这一点,你可以制作一份文件的副本。

一些伪代码,只需用电话代替调用sleeping_functioncall_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);  
} 

对于windows dlopen变得LoadLibrarydlsym成为GetProcAddress等...但其基本思想仍然能工作。

+0

这将不起作用,因为我必须静态链接整个程序。 – elmo 2010-09-15 14:15:16

1

一般来说,这是一个坏主意。全局数据不是唯一可能阻止非线程安全库在多线程环境中运行的问题。

作为一个例子,如果库有一个全局变量指向一个内存映射文件,它总是映射到一个单一的硬编码地址。在这种情况下,使用您的技术,每个线程都会有一个全局变量,但它们都指向相同的内存位置,这将会被多线程访问所破坏。

+0

我同意,但事实并非如此。我有权访问库的来源,但我无法更改任何内容,而必须链接到给定的静态库对象。 – elmo 2010-09-15 14:24:18

+0

这就是一个例子。你确定图书馆没有假设它是在一个单独的线程中运行吗?甚至没有隐含的假设? – 2010-09-15 16:38:28