c++ - 原子和 `errno`:使用 C++11 原子读取受保护的 errno 值是否合理?
问题描述
处理 errno 是在多线程环境中使用 POSIX API 的难题之一。使用std::atomic
像下面这样的锁是否合理?
class FastLock{
std::atomic_int value;
public:
FastLock()
: value{0}{}
void unlock()
{
value.store(0,std::memory_order_release);
}
bool try_lock()
{
int r = value.exchange(1,std::memory_order_acquire);
return !r;
}
};
上下文将与此类似:
template<typename function, typename ...args>
auto shield(function _fn){
static FastLock* lk = new FastLock{};
return [=](args... _v){
while(lk->try_lock());
auto ret = std::forward(_fn, _v...);
auto errval = errno;
lk->unlock();
return std::make_pair(ret,errval);
};
}
这会导致任何类型的未定义行为或实现定义的行为吗?
解决方案
虽然 1988 年的旧 POSIX 标准曾经要求errno
是一个全局对象,但在以后的修订版中不再是这种情况。至少 POSIX.1-2001 需要errno
是线程本地的。我怀疑指定 POSIX 线程的 POSIX.1c-1995 已经要求这样做,但我无权访问该文档,因此无法验证。
我不希望支持 C++11 的 POSIX 系统也不会支持 POSIX 2001,因此,使用 C++11 原子似乎不太必要。
也就是说,虽然 C 标准不需要errno
是全局对象(至少 C99 不需要),但它也不保证errno
. errno
因此,在非 POSIX 系统或不提供线程局部性的旧 POSIX 系统上可能需要锁定。如果由于某种原因平台确实支持 C++11,那么 C++11 原子可能是实现锁的理想选择 - 或者它可能不是。至少在理论上。
请注意,为了保证线程安全,您必须确保对可能设置的函数的所有调用都errno
必须使用锁。如果您使用任何可能使用此类标准函数的库,则还必须锁定对此类函数的调用。
推荐阅读
- tkinter - 如何获得小部件大小?
- python - 运行时错误 mat1 dim 1 必须匹配 mat2 dim 0
- r - 如何合并 tibble 的行以将单元格折叠成一个单元格
- html - 列表中的子元素缺少键,尽管已分配
- javascript - Javascript计数动画停止用逗号计数
- php - 删除已购买该产品的特定用户的添加到购物车按钮
- hyperlink - 内嵌视频的丰富链接预览
- python - SMOTE 有时无法对代表性最不足的班级进行过度抽样
- python - Visual Studio 代码:未访问“matplotlib” Pylance
- python - 如何使用 boto3 获取 AWS Glue 架构注册表架构定义?