- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在寻找一种方法来保护整数以原子方式递增但并进行边界检查。我四处寻找其他帖子,但似乎都没有好的解决方案(有些是 C++11 之前的帖子)。
我需要的是像下面这样的库:
class bounded_atomic_uint
{
private:
uint32_t ctr;
uint32_t max;
mutex mtx;
public:
bounded_atomic_uint(uint32_t max = UINT32_MAX) : ctr(0), max(max) {}
~bounded_atomic_uint() = default;
// make in uncopyable and un-movable
bounded_atomic_uint(bounded_atomic_uint&&) = delete;
bounded_atomic_uint& operator=(bounded_atomic_uint&&) = delete;
bool inc();
bool dec();
uint32_t get();
};
bool bounded_atomic_uint::inc() {
lock_guard<mutex> lck (mtx);
if (ctr < max) {
ctr++;
return true;
}
else
{
cout << "max reached (" << max << ")" << endl; // to be removed!
return false; // reached max value
}
}
bool bounded_atomic_uint::dec() {
lock_guard<mutex> lck (mtx);
if (ctr > 0) {
ctr--;
return true;
}
else {
cout << "min reached (0)" << endl; // to be removed!
return false; // reached min value
}
}
uint32_t bounded_atomic_uint::get() {
lock_guard<mutex> lck (mtx);
return ctr;
}
像这样使用:
#include <iostream>
#include <mutex>
#include <cstdint>
using namespace std;
int main() {
bounded_atomic_uint val(3);
if (val.dec())
cout << "error: dec from 0 succeeded !!" << endl;
cout << val.get() << endl; // make sure it prints 0
val.inc();
val.inc();
cout << val.get() << endl;
if (!val.inc())
cout << "error: havent reached max but failed!!" << endl;
if (val.inc())
cout << "error max not detected!!" << endl;
cout << val.get() << endl;
return 0;
}
有没有更简单(或更正确)的方法来做到这一点?std::atomic 和 boost::atomic 似乎都没有办法避免出界检查(在锁内)。
如果不是,这个简单类是否足够好?还是我在这里遗漏了什么?
注意库中的couts将在实际使用时被删除!
最佳答案
您问题的这一部分有图书馆吗 is off-topic ,所以让我来回答“我们如何实现”这个问题,这个问题很切题,也很有趣。
让我们首先从您的示例中删除锁并将普通 int
替换为 atomic
s :
class bounded_atomic_uint
{
private:
atomic<uint32_t> ctr;
uint32_t max;
public:
bounded_atomic_uint(uint32_t max = UINT32_MAX) : ctr(0), max(max) {}
~bounded_atomic_uint() = default;
// make in uncopyable and un-movable
bounded_atomic_uint(bounded_atomic_uint&&) = delete;
bounded_atomic_uint& operator=(bounded_atomic_uint&&) = delete;
bool inc();
bool dec();
uint32_t get();
};
bool bounded_atomic_uint::inc() {
if (ctr < max) {
ctr++;
return true;
}
else
{
cout << "max reached (" << max << ")" << endl; // to be removed!
return false; // reached max value
}
}
此代码的问题在于,在边界检查和增量之间,值可能已更改。所以只能保证在没有争用的情况下不越界。
您可以通过确保值在增量之间没有变化来轻松解决此问题。这正是compare_exchange
提供:
bool bounded_atomic_uint::inc() {
while(true) {
auto ctr_old = ctr.load();
if (ctr_old < max) {
if(ctr.compare_exchange_weak(ctr_old, ctr_old + 1)) {
return true;
}
}
else
{
cout << "max reached (" << max << ")" << endl; // to be removed!
return false; // reached max value
}
}
}
现在如果计数器在边界检查和增量写入之间发生变化,compare_exchange_weak
将失败,因此我们必须重试。如果在此期间数字超出了界限,我们将在下一次循环迭代中检测到这一点并相应地退出。请注意,如果您忽略 compare_exchange
的虚假故障*,则只有在对原子进行实际并发写入时才需要循环,因此此实现实际上是 lock-free .
我们可以通过将原子的重复加载分解为 compare_exchange
来稍微提高效率(记住 compare_exchange
将原子的实际值写回到第一个参数):
bool bounded_atomic_uint::inc() {
auto ctr_old = ctr.load();
do {
if (ctr_old >= max) {
cout << "max reached (" << max << ")" << endl; // to be removed!
return false; // reached max value
}
} while(!ctr.compare_exchange_weak(ctr_old, ctr_old + 1));
return true;
}
*我们可以通过使用 compare_exchange_strong
来消除虚假的失败,但由于无论如何我们都必须循环,所以实际上没有充分的理由在这里这样做。
关于c++ - 用原子做饱和运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45504920/
我在 Java 7 上有一个 java servlet 应用程序,它在系统资源消耗方面通常非常健康。服务器上的 CPU 使用率通常低于 50%。然而,在启动后的几分钟内,它的行为会大不相同,以至于如果
我有大约 10k 个视频流需要监控。将有一个小型集群(例如:5-10 个)的异构机器来监视这些流。由于没有足够的 CPU 来完成所有这些工作,我将不得不对流进行洗牌,一次监控其中的几个,然后切换到下一
我已经使用 boost::asio 在 C++ 中开发了一个迷你 HTTP 服务器,现在我正在使用多个客户端对其进行负载测试,但我一直无法接近 CPU 饱和。我在 Amazon EC2 实例上进行测试
我有一个简单的 Ruby 应用程序,基本上它通过 HTTP 端点获取一些数据,对其进行一点处理,将其分组并分批发送到某个远程 HTTP 端点。 当我在裸机上运行它时 - 我将 4 个 CPU 饱和到
我需要使用半径为 17 或更大的 3D 结构元素来计算形状为 (400,401,401)、大小为 64320400 字节的 3D 数组的形态学开度。结构元素ndarray的大小为 42875 字节。使
我一直在看 MMX/SSE,我想知道。有用于无符号字节和字的压缩、饱和减法的指令,但没有双字的指令。 有没有办法做我想做的事,或者如果没有,为什么没有? 最佳答案 如果您有可用的 SSE4.1,我认为
我需要创建一个脚本,让用户可以将一些类似 instagram 的过滤器应用于他们的图像。首先它应该在浏览器中完成。最简单的方法当然是 css3 过滤器。然后图像应该上传到服务器,并且必须使用与在浏览器
我是一名优秀的程序员,十分优秀!