C++线程安全括号运算符代理
C++ thread-safe bracket operator proxy
给定一个围绕标准向量的简单包装器,以线程安全的方式实现operator[]
以便能够像往常一样设置内容的好方法是什么?
struct bracket_operator_proxy;
struct example
{
auto operator[](size_t i) const { return bracket_operator_proxy(v, m, i); }
private:
std::vector<double> v;
std::mutex m;
};
以下是我对bracket_operator_proxy
:的快速而天真的尝试
struct bracket_operator_proxy
{
bracket_operator_proxy(std::vector<double>& v, std::mutex& m, int i)
: v(v), m(m), i(i) {}
operator double() const
{
std::lock_guard<std::mutex> l(m);
return v[i];
}
auto operator=(double d)
{
std::lock_guard<std::mutex> l(m);
v[i] = d;
return d;
}
//... further assignment operators ...
private:
std::vector<double>& v;
std::mutex& m;
int i;
};
这已经足够了吗?还是我错过了什么会把我的腿炸飞的东西?
一旦您有了operator->
(这非常有用),您将需要返回一个->
代理,它将延长锁的生存期,直到语句结束,并使您面临单线程死锁。
看看像这里这样的线程安全monads/functor/包装器。它不会使锁完全透明,但它们不应该是。
-
不在线程之间共享数据
-
如果您共享数据,请使其成为不可变的
-
如果必须进行变异,则通过已知安全设计的瓶颈隔离访问。一个消息队列说。
-
如果你不能做到这一点,可以考虑重新设计
-
真的。也许是原子弹?
-
具有一组有限的功能,可以显式管理锁定
-
好的,现在用简单的ish复合操作完成上面的读写器monad
-
让代码神奇地获得锁,看起来就像非线程交互的代码,从而让读者产生一种虚假的安全感和效率
偏好递减。
线程安全的危险和困难之处并不在于语法的尴尬。基于锁的线程安全性几乎不可能被证明是正确和安全的。使语法更易于使用并不是一个高价值的目标。
例如,v[i]=v[i+1]
充满了缺乏同步的问题:在读取和写入之间,任何事情都可能发生变化。更不用说"i
是有效索引吗?"
相关文章:
- 为什么比较运算符如此快速
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 代理对象的常量正确性
- 增量运算符与后缀混淆
- 一个关于在C++中重载布尔运算符的问题
- 运算符C++ "delete []"仅删除 2 个前值
- 为流运算符返回代理类时解压缩参数
- Gnu 的 <Iterator>reverse_iterator::运算符>和代理迭代器
- C++ - (零成本?) 代理类运算符=(值) -> std::map[key]=类内的值
- C++线程安全括号运算符代理
- 使用两个非类参数的 C++ 运算符重载(使用代理解决)
- 重载 - >运算符通过代理转发成员访问
- 运算符 [] 错误的矩阵类代理
- 我已经在我的运算符 [] 中使用了一个代理来隐式转换 boost::变体。如何通过运算符 [] 维护分配?
- 如何使用具有模板转换运算符的非模板代理对象来避免指定boost::变体的类型
- 代理包装类,运算符>链接
- 右值中的代理类-如何实现赋值运算符
- c++中的向量,代理类和点运算符