[Boost-users] [iostreams] filtering_ostream does not flush std::cout.

30 views
Skip to first unread message

Duncan Smith

unread,
Sep 1, 2010, 10:33:11 AM9/1/10
to boost...@lists.boost.org, bo...@lists.boost.org
I'm using Boost 1.43.0, and I've found that filtering_ostream does not
flush "std::cout".  I found a relevant (and recent) ticket against
Boost 1.44.0, but my issue is slightly different.
 https://svn.boost.org/trac/boost/ticket/4590
I'm using GCC 4.3.4 on Gentoo Linux.

I'm hoping that I'm just doing something wrong, but if you think
there's a bug, I'll add my testcase to the ticket.

The basic recipe:

filtering_ostream out;
out.push(any_filter_at_all());
out.push(std::cout);
out << "Hello World!" << std::flush;
sleep(10); // Observe an empty console.
std::cout << std::flush;
sleep(10); // Observe printed text on console.

This problem is quite bad for me when doing the following on the
command-line (for a more complicated program):
./program 2>&1 | tee some-file.log
Because stdout is not getting flushed, the stdout and stderr get
intermingled strangely.

However, disabling buffering on stdout works around the problem:
stdbuf --output=0 ./program 2>&1 | tee some-file.log

Please tell me if you think there's a bug in my code. If it's a bug
in Boost.Iostreams (or I'm expecting the wrong behaviour), I would
appreciate any ideas for workarounds (I tried cout.setf(unitbuf), and
that doesn't seem to do the trick).

Here's the full text of my code:

------------------
// Test case for flushing a filtering_ostream based on the
// boost_iostreams_filtering_ostream.cpp attached to ticket #4950:
// https://svn.boost.org/trac/boost/ticket/4590
// https://svn.boost.org/trac/boost/attachment/ticket/4590/boost_iostreams_filtering_ostream.cpp
// changed to use "cout" as the sink.
//
// Flushing a filtering_ostream using the flush() global function does not work
// in Boost 1.43. I suspect it also does not work in Boost 1.44.
//
// Using GCC-4.3.4 on Gentoo Linux.
//
#include <cassert>
#include <string>
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/operations.hpp>
#include <boost/iostreams/filtering_stream.hpp>

#include <iostream>

// Included for "sleep()" call below.
#include <unistd.h>

namespace io = boost::iostreams;

// Simple output filter forwarding just forwarding the put chars to
// the sink.
struct transparent_output_filter {
typedef char char_type;
typedef io::output_filter_tag category;

template <typename Sink>
bool put(Sink& snk, char c)
{
return io::put(snk, c);
}
};

int main(int argc, char *argv[])
{
using namespace std;

io::filtering_stream<io::output> out;

// Transparent filter just forward the characters to the sink.
//
// Note: I observe this behaviour with and without this line.
out.push(transparent_output_filter());

// Sink appends characters to "cout".
out.push(cout);

// Write test string to filtering_ostream.
out << "Hello World!";

// On my system, this will flush the buffer iff I'm on an
// interactive console. "\n" and endl have the same effect. I believe
// that my shell sets "stdout" to be line-buffered if it's interactive.
// out << "\n";

bool wasFlushed = false;
// The flush does *not* work in Boost 1.43.
wasFlushed = io::flush(out);

// This assertion does not go off, though.
assert(wasFlushed);

// This also doesn't work.
wasFlushed = out.flush();
assert(wasFlushed);

// This also doesn't work.
out << std::flush;

// Demonstrate that none of the above flush calls had any effect on "cout".
sleep(10);

// Now we finally get the characters on the console.
cout << flush;

// Demonstrate that the direct flush call works when called directly on
// "cout".
sleep(10);

return 0;
}
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Reply all
Reply to author
Forward
0 new messages