gpt4 book ai didi

c++ - C++ 异常是否足以实现线程本地存储?

转载 作者:IT老高 更新时间:2023-10-28 12:54:40 26 4
gpt4 key购买 nike

我是 commenting on an answer线程本地存储很好,又想起了另一个 informative discussion关于我认为的异常(exception)情况

The only special thing about the execution environment within the throw block is that the exception object is referenced by rethrow.

将两个和两个放在一起,会不会在其主函数的函数捕获 block 内执行整个线程并为其注入(inject)线程本地存储?

它似乎工作正常,虽然速度很慢。这本小说还是有特色的?是否有另一种解决问题的方法?我最初的前提是正确的吗? get_thread 在您的平台上会产生什么样的开销?优化的潜力是什么?

#include <iostream>
#include <pthread.h>
using namespace std;

struct thlocal {
string name;
thlocal( string const &n ) : name(n) {}
};

struct thread_exception_base {
thlocal &th;
thread_exception_base( thlocal &in_th ) : th( in_th ) {}
thread_exception_base( thread_exception_base const &in ) : th( in.th ) {}
};

thlocal &get_thread() throw() {
try {
throw;
} catch( thread_exception_base &local ) {
return local.th;
}
}

void print_thread() {
cerr << get_thread().name << endl;
}

void *kid( void *local_v ) try {
thlocal &local = * static_cast< thlocal * >( local_v );
throw thread_exception_base( local );
} catch( thread_exception_base & ) {
print_thread();

return NULL;
}

int main() {
thlocal local( "main" );
try {
throw thread_exception_base( local );
} catch( thread_exception_base & ) {
print_thread();

pthread_t th;
thlocal kid_local( "kid" );
pthread_create( &th, NULL, &kid, &kid_local );
pthread_join( th, NULL );

print_thread();
}

return 0;
}

这确实需要定义从 thread_exception_base 派生的新异常类,并使用 get_thread() 初始化基类,但总的来说,这不像是一个无产的失眠星期天早上……

编辑: 看起来 GCC 在 get_thread 中对 pthread_getspecific 进行了 三个 调用。 编辑: 并对堆栈、环境和可执行格式进行了大量令人讨厌的自省(introspection),以找到我在第一次演练中错过的 catch block 。这看起来高度依赖于平台,因为 GCC 正在从操作系统调用一些 libunwind。大约 4000 个周期的开销。我想它还必须遍历类层次结构,但可以控制。

最佳答案

本着这个问题的俏皮精神,我提出了这个可怕的噩梦创作:

class tls
{
void push(void *ptr)
{
// allocate a string to store the hex ptr
// and the hex of its own address
char *str = new char[100];
sprintf(str, " |%x|%x", ptr, str);
strtok(str, "|");
}

template <class Ptr>
Ptr *next()
{
// retrieve the next pointer token
return reinterpret_cast<Ptr *>(strtoul(strtok(0, "|"), 0, 16));
}

void *pop()
{
// retrieve (and forget) a previously stored pointer
void *ptr = next<void>();
delete[] next<char>();
return ptr;
}

// private constructor/destructor
tls() { push(0); }
~tls() { pop(); }

public:
static tls &singleton()
{
static tls i;
return i;
}

void *set(void *ptr)
{
void *old = pop();
push(ptr);
return old;
}

void *get()
{
// forget and restore on each access
void *ptr = pop();
push(ptr);
return ptr;
}
};

利用根据 C++ 标准,strtok 隐藏其第一个参数这一事实,以便后续调用可以传递 0 以从同一字符串中检索更多标记,因此,在线程感知实现中,它必须使用 TLS。

example *e = new example;

tls::singleton().set(e);

example *e2 = reinterpret_cast<example *>(tls::singleton().get());

只要 strtok 没有在程序的其他任何地方以预期的方式使用,我们就有另一个备用 TLS 插槽。

关于c++ - C++ 异常是否足以实现线程本地存储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2487509/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com