Pot*_*ter 26 c++ exception thread-local
我正在评论一个线程本地存储很好的答案,并回忆起关于异常的另一个信息性讨论
throw块中执行环境的唯一特殊之处在于rethrow引用了异常对象.
将两个和两个放在一起,不会在其主函数的函数catch块中执行整个线程,并将其与线程本地存储一起使用?
虽然很慢,但似乎工作正常.这是小说还是很有特色?还有另一种解决问题的方法吗?我最初的前提是否正确?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;
}
Run Code Online (Sandbox Code Playgroud)
这确实需要定义派生的新异常类thread_exception_base,初始化基础get_thread(),但总的来说这并不像一个无效的失眠缠身的星期天早晨......
编辑:看起来像GCC使得3个调用pthread_getspecific在get_thread.编辑:和堆栈,环境和可执行格式的很多讨厌的内省,找到catch我在第一次演练中错过的块.这看起来高度依赖于平台,因为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;
}
};
Run Code Online (Sandbox Code Playgroud)
利用根据C++标准的事实,将strtok其第一个参数存储起来以便后续调用可以传递0以从同一个字符串中检索更多的令牌,因此在线程感知实现中它必须使用TLS.
example *e = new example;
tls::singleton().set(e);
example *e2 = reinterpret_cast<example *>(tls::singleton().get());
Run Code Online (Sandbox Code Playgroud)
因此,只要strtok程序中的任何其他地方没有以预期的方式使用,我们就有另一个备用TLS插槽.