我需要将流程的标准输出(二进制数据)放入字符串缓冲区,并在另一个线程中使用它。

这是生产者:

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。
  • 在读取streambuf时,读取了正确的字节总数(因此比in_avail()指示的要多)。

  • 此行为是合规的。根据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/

    10-12 22:54