我查了这个问题,但这不是我想要的.
我正在试图找出如何限制日志文件的大小(比方说,10MB),并且一旦它被击中,就会:
不要真的关心语言 - 只要有可能:)
注意:我知道滚动日志文件方法(达到目标大小,重命名并继续记录).我希望避免这样的滚动.
有一篇文章在http://lwn.net/Articles/378262/上描述了Linux内核的循环缓冲区实现.我有一些问题:
这是"生产者":
spin_lock(&producer_lock);
unsigned long head = buffer->head;
unsigned long tail = ACCESS_ONCE(buffer->tail);
if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
/* insert one item into the buffer */
struct item *item = buffer[head];
produce_item(item);
smp_wmb(); /* commit the item before incrementing the head */
buffer->head = (head + 1) & (buffer->size - 1);
/* wake_up() will make sure that the head is committed before
* waking anyone up */
wake_up(consumer);
}
spin_unlock(&producer_lock);
Run Code Online (Sandbox Code Playgroud)
问题:
我有一个需要将数据传递给低优先级进程的高优先级进程.我写了一个基本的环形缓冲区来处理数据的传递:
class RingBuffer {
public:
RingBuffer(int size);
~RingBuffer();
int count() {return (size + end - start) % size;}
void write(char *data, int bytes) {
// some work that uses only buffer and end
end = (end + bytes) % size;
}
void read(char *data, int bytes) {
// some work that uses only buffer and start
start = (start + bytes) % size;
}
private:
char *buffer;
const int size;
int start, end;
};
Run Code Online (Sandbox Code Playgroud)
这是问题所在.假设低优先级进程有一个oracle,它确切地告诉它需要读取多少数据,因此count()永远不需要调用.然后(除非我遗漏了什么)没有并发问题.但是,只要低优先级线程需要调用count()(高优先级线程可能也想调用它来检查缓冲区是否太满),count()或更新中的数学可能会结束不是原子的,引入了一个bug.
我可以在访问周围放置一个互斥体来开始和结束但如果高优先级线程必须等待低优先级线程获取的锁定,那么这将导致优先级倒置. …
我找到了关于如何实现循环缓冲区的伪代码.
// Producer.
while (true) {
/* produce item v */
while ((in+1)%n == out)
/* Wait. */;
b[in] = v;
in = (in + 1) % n
}
// Consumer.
while (true) {
while (in == out)
/* Wait. */;
w = b[out];
out = (out + 1) % n;
/* Consume item w. */
}
Run Code Online (Sandbox Code Playgroud)
我不明白的是"消费项目w".评论,因为我认为w = b[out];我们正在消费w,不是吗?
我想要一个简单而有效的循环缓冲区/队列.如果我使用std::vector,我必须这样做:
if ( v.size() >= limit ) {
std::vector<int> it = v.begin();
v.insert( it, data );
v.erase( it+1 );
}
Run Code Online (Sandbox Code Playgroud)
有没有更简单的解决方案?
我想知道循环缓冲区(循环队列或双端队列)标准化的历史。
AFAIK,当前的 C++ 标准(C++ 2023)在 STL 中没有提供循环缓冲区。我用 google 搜索了一下,只发现了一个提案,ring_span大约是在 2015 年。Boost 的circular_buffer. 有些提供内部实现,例如cqueue.
如果使用 a 重复推入和弹出操作std::deque,则会重复分配和释放堆块。在 Qt(最大的 C++ 项目之一)中,情况更糟,QQueue不断分配堆块(并且从不释放)。
我不是在征求意见。我想了解历史。我认为标准化循环缓冲区如此困难有充分的理由。
我正在使用C#在.Net环境中工作.我需要一些替代堆栈数据结构.某种绑定堆栈.集合中元素的数量不应超过某个固定的指定数量.并且,如果实现了该数字并且推送了新元素,则必须删除大多数旧元素.我需要这个来存储撤消/重做策略的命令.
对于我的游戏iOS项目,我需要一个环形缓冲区.它应该类似于一个队列,其中元素输出并进入,但缓冲区中元素的总量应保持不变.
我使用java成功实现了环形缓冲区,但我不熟悉objective-c.我在网上找到了一个名为CHCircularBuffer的环形缓冲区实现:https://bitbucket.org/devartum/chdatastructures/src/4d6d7194ee94/source/CHCircularBuffer.m 但是我没能正确实现它.
循环缓冲区是名为TerrainManager的类的属性,它可以生成所有数学地形.
@interface TerrainManager : NSObject{
int terrainParts;
CHCircularBuffer* circularTerrainBuffer;
}
@property(nonatomic, retain) CHCircularBuffer *circularTerrainBuffer;
@end
Run Code Online (Sandbox Code Playgroud)
这是如何在TerrainManager的实现中初始化环形缓冲区
circularTerrainBuffer = [[CHCircularBuffer alloc] initWithCapacity:parts];
Run Code Online (Sandbox Code Playgroud)
这将创建缓冲区的实例,并将size属性设置为parts.现在我使用addObject方法将对象添加到缓冲区:
[circularTerrainBuffer addObject:[NSNumber numberWithDouble:0.2]];
Run Code Online (Sandbox Code Playgroud)
有时这行会收到错误"exec_bad_access".例如,当我初始化容量为15的缓冲区时,一切都很好,20我得到了错误.
我现在尝试从绘图发生的terrain类访问缓冲区.但每当我尝试访问对象时,我都会收到"bad_access"错误.
NSArray *arr = [terrainManager.circularTerrainBuffer allObjects];
Run Code Online (Sandbox Code Playgroud)
例如,这一行会产生错误.
所以我的代码有问题.也许我不理解缓冲区并以错误的方式添加对象.我不知道.任何想法或建议?
最近,在一次采访中我被问到使用循环队列的缺点.我什么都想不到.在互联网上搜索我发现的唯一答案是它比线性队列更难实现:).还有其他缺点吗?
我对deque的实现进行了一些搜索.根据这篇文章,deque使用向量的向量.我知道在开始和结束时推送应该是恒定的时间,并且还需要随机访问.我认为循环缓冲区满足所有这些要求,并且更加简单.那么为什么不使用循环缓冲区?
我还发现了增强循环缓冲区.它与deque相比如何?
编辑:好的,所以它与迭代器失效规则有关.它指出:
所有迭代器和引用都是无效的,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但对元素的引用不受影响)
我的理解是重载像iter ++这样的运算符,迭代器必须拥有一个指向节点映射的指针和一个指向块的指针,所以如果重新分配节点映射,迭代器就会失效.但由于数据从未移动,因此引用仍然有效.