我需要将流程的标准输出(二进制数据)放入字符串缓冲区,并在另一个线程中使用它。
这是生产者:
while (ReadFile(ffmpeg_OUT_Rd, cbBuffer, sizeof(cbBuffer), &byteRead, NULL)){
tByte += byteRead; //total bytes
sb->sputn(cbBuffer, byteRead);
}
m_bIsFinished = true;
printf("%d bytes are generated.\n", tByte);
这是消费者:
while (!PCS_DISPATCHER_INSTANCE->IsFinished())
Sleep(200);
Sleep(5000);
Mystringbuf* sb = PCS_DISPATCHER_INSTANCE->sb;
printf("Avail: %d\n", sb->in_avail());
事实证明,消费者无法获得生产者生产的所有字节。
(
tByte <> sb->in_avail()
)这是一种内部缓冲问题吗?如果是,如何强制stringbuf刷新其内部缓冲区?
最佳答案
streambuf
与flush完全不同:写操作直接在缓冲区中完成。如果您使用派生的对象(例如filebuf),则 pubsync()
成员可能会有所帮助。但这不适用于您的情况。
您的问题肯定来自 sputn()
或is_avail()
上的数据竞赛。通过互斥或 atomic
保护对streambuf的访问。如果m_bIsFinished
不是原子的,并且取决于您对isFinished()
的实现,则可能无法保证线程之间的同步(例如:生产者可以写入内存,但是使用者仍然从CPU内存高速缓存中获取过时的值),这可以进行此类数据竞赛。
编辑:
如果您在一个线程中遇到此问题,从而消除了任何潜在的竞争状况,则可能来自streambuf
的实现。我可以在单线程应用程序中通过MSVC13体验到这一点:
in_avail()
结果始终小于或等于tByte。 此行为是合规的。根据C++标准:如果有可用的读取位置和其他showmanyc(),
in_avail()
应返回egptr()-gptr()。后者定义为返回序列中可用字符数的估计。给出的唯一保证是,您可以读取至少in_avail()
字节而不会遇到eof。解决方法是使用
sb->pubseekoff(0,ios::end)- sb->pubseekoff(0,ios::beg);
来计数可用的字节数,并确保在读取streambuf之前将其重新定位在sb-> pubseekoff(0,ios::beg)处。关于c++ - C++如何刷新std:stringbuf?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25833193/