在C ++ 11中,您可以使用带有thread_local存储的非平凡对象:
class X { ... }
void f()
{
thread_local X x = ...;
...
}
不幸的是,此功能尚未在gcc中实现(从4.7开始)。
gcc确实允许您拥有线程局部变量,但仅具有普通类型。
我正在寻找一种解决方法:
这是我到目前为止的内容:
#include <iostream>
#include <type_traits>
using namespace std;
class X
{
public:
X() { cout << "X::X()" << endl; };
~X() { cout << "X::~X()" << endl; }
};
typedef aligned_storage<sizeof(X), alignment_of<X>::value>::type XStorage;
inline void placement_delete_x(X* p) { p->~X(); }
void f()
{
static __thread bool x_allocated = false;
static __thread XStorage x_storage;
if (!x_allocated)
{
new (&x_storage) X;
x_allocated = true;
// TODO: add thread cleanup that
// calls placement_delete_x(&x_storage)
}
X& x = *((X*) &x_storage);
}
int main()
{
f();
}
我需要帮助的是在当前线程的出口处调用placement_delete_x(&x_storage)。我可以使用pthreads和/或linux中的机制来做到这一点吗?我需要向某种pthread清理堆栈中添加函数指针和参数吗?
更新:
我想pthread_cleanup_push
可能就是我想要的:
http://www.kernel.org/doc/man-
pages/online/pages/man3/pthread_cleanup_push.3.html
这会在正确的使用情况下调用清理处理程序吗?
更新2:
看起来boost::thread_specific_ptr
最终会pthread_key_create
使用destructor
参数而不是pthread_cleanup_push
-来调用其tls清理函数:
http://pubs.opengroup.org/onlinepubs/009696799/functions/pthread_key_create.html
目前尚不清楚这两种方法之间的区别(如果有)。?
正如迈克所说pthread_cleanup_push
的不合适。正确的方法是使用pthread_key_create
。
我已经实现了一个小型演示程序,以演示如何执行此操作。我们实现thread_local
您使用的宏,如下所示:
使用真正的C ++ 11功能,它将是:
void f()
{
thread_local X x(1,2,3);
...
}
与此是:
void f()
{
thread_local (X, x, 1, 2, 3);
...
}
与boost ::
thread_specifc_ptr之间的区别是动态内存分配为零。一切都与__thread
持续时间一起存储。它的重量也轻得多,但特定于gcc /
linux。
概述:
std::aligned_storage
为变量创建__thread持续时间空间__thread
为展示位置删除调用分配了一个链接列表条目pthread_setspecific
用来跟踪每个线程的列表头pthread_key_create
会在线程退出时删除调用放置的列表。…
#include <iostream>
#include <thread>
using namespace std;
static pthread_key_t key;
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
struct destructor_list
{
void (*destructor)(void*);
void* param;
destructor_list* next;
};
static void execute_destructor_list(void* v)
{
for (destructor_list* p = (destructor_list*) v; p != 0; p = p->next)
p->destructor(p->param);
}
static void create_key()
{
pthread_key_create(&key, execute_destructor_list);
}
void add_destructor(destructor_list* p)
{
pthread_once(&once_control, create_key);
p->next = (destructor_list*) pthread_getspecific(key);
pthread_setspecific(key, p);
}
template<class T> static void placement_delete(void* t) { ((T*)t)->~T(); }
#define thread_local(T, t, ...) \
T& t = *((T*) \
({ \
typedef typename aligned_storage<sizeof(T), \
alignment_of<T>::value>::type Storage; \
static __thread bool allocated = false; \
static __thread Storage storage; \
static __thread destructor_list dlist; \
\
if (!allocated) \
{ \
new (&storage) T(__VA_ARGS__); \
allocated = true; \
dlist.destructor = placement_delete<T>; \
dlist.param = &storage; \
add_destructor(&dlist); \
} \
\
&storage; \
}));
class X
{
public:
int i;
X(int i_in) { i = i_in; cout << "X::X()" << endl; };
void f() { cout << "X::f()" << endl; }
~X() { cout << "X::~X() i = " << i << endl; }
};
void g()
{
thread_local(X, x, 1234);
x.f();
}
int main()
{
thread t(g);
t.join();
}
笔记:
__thread
哪个是GNU扩展本文向大家介绍ASP 提示非法赋值的解决方法,包括了ASP 提示非法赋值的解决方法的使用技巧和注意事项,需要的朋友参考一下 分析可能是: asp的一些保留字段导致,具体的大家可以参考这篇文章:ASP常见的保留字整理 正常来说 代码没问题```ID也有值 但是库改成了SQL SERVER库 因不长用所以请教各位这个错误是哪里问题 Microsoft VBScript 运行时错误 错误 '800a01
问题内容: 我需要使用这种结构将一些数据库表的内容转储到XML文件中 每个表在未知状态下的真实记录数,因此我无法将单个表的所有数据存储在内存中并转储到XML。 我的工作现在定义为: 这项工作不完整,无法满足我的需求,因为输出看起来像 我认为我必须丰富作家和/或编组人员的组件才能实现我的目标,但我还没有找到继续前进的好方法:( 我的问题是: 如何按照开始时所述构建复杂的XML结构,并使作业完全可重新
经过稍加搜索,我找到了一个StackOverflow的答案,它用comonoids必须满足的定律更好地解释了这一点。所以我想我明白了为什么在Haskell中只有一个假设的Comonoid类型的可能实例。 因此,要找到一个非平凡的comonoide,我想我们必须从其他类别中寻找。当然,如果范畴理论家有一个comonoids的名字,那么有一些有趣的。该页上的其他答案似乎暗示了一个涉及的示例,但我找不出
本文向大家介绍详解django使用include无法跳转的解决方法,包括了详解django使用include无法跳转的解决方法的使用技巧和注意事项,需要的朋友参考一下 一般的django项目我都喜欢采用以下的文件结构,使用include的方式,实现从总的url分配给apps里面的url Example: 但突然发现无法跳转,竟然是总url的这个错误! 以下是错误做法 以下是正确做法,主要问题在于u
本文向大家介绍PHP中函数gzuncompress无法使用的解决方法,包括了PHP中函数gzuncompress无法使用的解决方法的使用技巧和注意事项,需要的朋友参考一下 前言 gzuncompress函数不是php自带的系统函数而是一个插件函数了所以要使用 gzuncompress函数我们必须安装一个插件,下面来看看PHP函数gzuncompress无法使用的问题解决办法吧。 一、解决过程 1.
本文向大家介绍Centos 升级到python3后pip 无法使用的解决方法,包括了Centos 升级到python3后pip 无法使用的解决方法的使用技巧和注意事项,需要的朋友参考一下 一. 问题 pip无法使用. 二. 系统环境 三. 解决方法 设置软连接. 1.查找pip所在位置 2.设置软连接 语法参见: 检测一下效果: 以上这篇Centos 升级到python3后pip 无法使用的解决方