Subject: Re: [Boost-bugs] [Boost C++ Libraries] #4590: Flushing a filtering_ostream stopped working in Boost 1.44
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2010-09-24 18:04:11
#4590: Flushing a filtering_ostream stopped working in Boost 1.44
-------------------------------+--------------------------------------------
Reporter: t0rt1e@⦠| Owner: turkanis
Type: Bugs | Status: new
Milestone: To Be Determined | Component: iostreams
Version: Boost 1.44.0 | Severity: Problem
Resolution: | Keywords:
-------------------------------+--------------------------------------------
Comment (by Mike Tryhorn <miketryhorn@â¦>):
Dear all,
I recently upgraded from Boost 1.43.0 to 1.44.0 and have experienced the
same problem. My personal debug logging library relies upon the proper
functioning of the flush (and sync) mechanism in boost::iostreams to
produce transactional, orderly message output. Unfortunately, in the
latest boost version this flush mechanism is non-functional.
However, I've made an investigation of this problem by putting versions
1.43.0 and 1.44.0 side-by-side. I am relieved to say that I have tracked
the problem, and have a simple solution.
I have confirmed that this problem was introduced by the bugfix for #2356,
which changed the following code in
boost/iostreams/detail/adapter/concept_adapter.hpp:
{{{#!div style="font-size: 85%"
Boost v1.43.0
{{{#!C++
bool flush( BOOST_IOSTREAMS_BASIC_STREAMBUF(char_type,
BOOST_IOSTREAMS_CHAR_TRAITS(char_type))* sb )
{
bool result = any_impl::flush(t_, sb);
if (sb && sb->BOOST_IOSTREAMS_PUBSYNC() == -1)
result = false;
return result;
}
}}}
}}}
{{{#!div style="font-size: 85%"
Boost v1.44.0
{{{#!C++
template<typename Device>
bool flush( Device* dev )
{
return any_impl::flush(t_, dev);
}
}}}
}}}
(See changeset: https://svn.boost.org/trac/boost/changeset/63034.)
For some reason, the 'PUBSYNC' operation was removed. I suspect that it
was merely mistaken as being unnecessary, however it is the mechanism by
which the filtering_ostream's chain is flushed in its entirety.
To give some context: indirect_streambuf (the stream buffer used by
filtering_ostream), being a std::streambuf, has a required 'sync' method:
{{{#!div style="font-size: 85%"
boost::iostreams::indirect_detail::indirect_streambuf::sync
{{{#!C++
template<typename T, typename Tr, typename Alloc, typename Mode>
int indirect_streambuf<T, Tr, Alloc, Mode>::sync()
{
try { // sync() is no-throw.
sync_impl();
obj().flush(next_);
return 0;
} catch (...) { return -1; }
}
}}}
}}}
Where 'obj()' returns a 'concept_adapter<T>&'. This 'sync' method's
implementation has not changed between versions 1.43.0 and 1.44.0.
This sync method is called by ostream::flush, and relies upon the
expectation that any 'flush' will indeed itself perform a 'sync' operation
(the aforementioned 'PUBSYNC').
{{{#!div style="font-size: 85%"
See: http://www.cplusplus.com/reference/iostream/ostream/flush/ [[br]]
And: http://www.cplusplus.com/reference/iostream/streambuf/pubsync/
}}}
However, as 'PUBSYNC' has been removed from concept_adaptor<T>::sync, only
the first device or filter in the filtering_ostream's chain will ever be
flushed. This means that for any filtering_ostream which a chain of
length 2 or more, the stream's output will only reach its destination when
a buffer overflows, or the stream is released.
So, I hope that by now the solution is self-evident:
{{{#!div style="font-size: 85%"
Proposal for Boost 1.45.0
{{{#!C++
template<typename Device>
bool flush( Device* dev )
{
bool result = any_impl::flush(t_, dev);
if (dev && dev->BOOST_IOSTREAMS_PUBSYNC() == -1)
result = false;
return result;
}
}}}
}}}
I've tested this solution with the test code provided both in this bug
report (attachment:
boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp), and #2356
(attachment: test.cpp).
I'm not myself a boost contributor (this is my first contribution), so if
you believe it to be correct, could someone please submit this change to
SVN?
Correction diff file to follow.
Many thanks.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/4590#comment:4> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:04 UTC