Re: [Boost-bugs] [Boost C++ Libraries] #4590: Flushing a filtering_ostream stopped working in Boost 1.44

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