Boost logo

Boost :

From: Pavel Vozenilek (pavel_vozenilek_at_[hidden])
Date: 2004-09-09 12:27:39

"Jonathan Turkanis" wrote:

> Here's a suggestion for a concept which might be reusable
> in this way (view with fixed-width font):
> Concept: Resettable
> Valid Expressions | Return Type | Semantics
> --------------------------------------------------------------------
> t.reset(discard) | bool | resets t to the state it had
> | | upon construction, discarding
> | | cached data if discard is true.
> | | Returns true for success.
Counterexample: the radio link pipeline has
member counting # of passed bytes, member that keeps
ouput rate in sync with current air conditions.

If you want discard data in pipeline, you would reset all
these settings as side-effect.

I have feeling there should be two concepts:
- reset(bool discard)
- discard()

> So when I define the convenience base
> classes, I want to make the i/o category refine openable,
> closable and resettable, and provide default no-op implementations.

> Now, if the user only implements reset, I'd like boost::io::open and
> boost::io::close to call reset.
> ... variant with dummy instance + member function compare
> ... variant with CRTP
I do not have clear picture: when io::open() is called the
real type of filter is not known?

> > - it is not really sure flush would flush: for example filter removing
> > certain word may wait intil words get finished. What is flush()
> > semantic of theirs?
> This is an important point. When I originally implemented Flushable,
> was just a 'suggestion' to flush buffers. So users could never be sure
> wasn't any cached data remaining. I did it this way because for many
> as you mentioned, you can't force a complete flush without violating data
> But this whimpy version of flush turned out not to be very useful, which
> partly why I eliminated it.
> If I restore the concept, I will probably have flush return true only if
> cached data could be safely sent downstream. This means that
> sometimes flushing a filtering_ostream will fail, and in those cases
> you won't be able to insert or remove filters while i/o is in progress.
Maybe bool flush(bool force = false).

E.g. close() should probably call flush(true) to avoid data loss.

If an filter decides individually its current data just cannot
be flushed it could ignore the 'force' flag.

The flush() returns true if flush was complete. User then may
discard the rest of data sitting in caches.

> > > > - halt temporarily/restart (for output streams only?).
> > > > This action may be propagated downstream since some
> > > > filters may have busy sub-threads of their own
> > >
> > > I'm not sure I understand.
> > >
> > Equivalent to putting null sink on the top of pipeline
> > (and maybe after each part of pipeline, if the part acts
> > asynchonously).
> >
> > Not sure now it it is worth the troubles.
> Neither am I ;-). Maybe if you can think of an important use case ...
Only contrived: someone has reference to one and only one
member of pipeline, not to initial data source or end data sink.
This one may want to halt temporarily the flow but doesn't want
any dependencies on the rest of application.

E.g. module who keeps TCP/IP throughput limit and manages
multiple opened sockets. User registers socket_streams
and they could all be halted/restarted by the module.

(Here the halt means stop reading/sending, not null-sink
equivalent. The make-it-null-sink looks as yet another thing.)

> > > > - generate string description of what is in stream chain
> > > > (like stream::dump() for debugging)
> > >
> > > The character sequences, or the filter/resource sequence?
> > >
> > The latter. E.g. for to print debug into on console.
> This is a good idea for a debug-mode feature, but I think it only
> really makes sense if I implement flushable and allow filters to
> be swapped in and out during i/o. Otherwise, it should be pretty
> obvious which filters are in a chain just by looking the sequence
> of pushes.
And good idea for maintenace programmer.

Few notes from reading sources:

1. scope_guard.hpp: maybe this file could be moved into
    boost/detail and used by multi_index + iostreams until
   something gets boostified.

2. utility/select_by_size.hpp: would it be possible to use
    PP local iteration here to make it bit simpler?

3. io/zlib.hpp:

# pragma warning(push)
# pragma warning(disable:4251 4231 4660) // Dependencies not

could be rather

# pragma warning(push)
# pragma warning(disable:4251 4231 4660) // Dependencies not

4. the

#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once

should be added everywhere.
I do not see it in sources I have here, maybe its old version.

5. io/io_traits.hpp:




6. docs "Function Template close": the link to the header is broken.

In this page: somesting like UML's sequnce or collaboration
diagram could be added.

(I am visual type so I always ask for pictures and code examples.)

7. windows_posix_config.hpp: I find the macros
   BOOST_WINDOWS/BOOST_POSIX too general for iostreams.
   Either they should be in Boost.Config or something as
   BOOST_IO_WINDOWS should be used.

  It may also fail on exotics as AS400.

8. Maybe the library files could be more structured.
    Right now its directories contain 32, 24, 11 and 9 files
    and it may be confusing to orient in it.

   There may be subdirectories as utils/, filters/,
    filters/compression/ etc.

9. Maybe assert() could be replaced with BOOST_ASSERT().

10. disable_warnings.hpp: maybe this and other similar files could
      be merged into iostream_config.hpp.

     (Others: enable_stream.hpp.)

11. details/assert_convertible.hpp:

       The macro here doesn't feel as useful too much.
       Straight BOOST_STATIC_ASSERT(is_convertible....)
       would take the same space and would convey more information
       and immediatelly.

12. detail/access_control.hpp: this feel as as it could be in boost/utility/
      or in boost/detail/.

     An example(s) could be provided in the header.

13. detail/buffer.hpp: should have
      #include <boost/noncopyable.hpp>

     Commenting nitpick: maybe instead of

// Template name: buffer
// Description: Character buffer.
// Template paramters:
// Ch - The character type.
// Alloc - The Allocator type.
template< typename Ch,
          typename Alloc = std::allocator<Ch> >
class basic_buffer : private noncopyable {

could be

// what it is used for....
template< typename Ch,
          typename Alloc = std::allocator<Ch> >
class basic_buffer : private noncopyable {

Too many comments here are obvious and this makes
reader easy to skip them all.

OTOH it should be explained why there's basic_buffer
and buffer and why its functionality isn't merged into one
coherent class. This is far from obvious.

E.g. the design allows swap(basic_buffer, buffer).

It should be explained why std::vector or boost::array
isn't enough.

Maybe these class(es) could be factored out into boost/details/
or standalone mini-library.

14. detail/config.hpp: the trick with


I have feeling it should be removed. Compilers who cannot
handle even scope guard are not worth to support.
Or the scope_guard for these could be dummy.

Number of macros in iostreams library would be
better reduced.

macro: it should be explained in code comment what it means.
Maybe something like it could be moved into Boost.Config
or maybe something like this is already in Boost.Config.

BOOST_IO_DECL: this should be in Boost.Config
as BOOST_DECLSPEC. Other libraries (regex) have
their own macros and it is all one big mess.

15. converting_chain.hpp: how brackets are positioned
     would be better unified. Here I see the
    if (xxxxxxxxx)
   and elsewhere Kernigham notation
   and it makes me wonder whether whether it has some
   hidden meaning.

   Comments in code would be welocomed here.

16. double_object.hpp:

       typo in source "simalr"

       Wouldn't it make sense to have this in compressed_pair library?

17. forwarding.hpp: the macro
      is used on exactly one place. Maybe it could be defined/used/undefined
      here to make overall structure simpler.

18. io/detail/streambufs/ : there are temporary files
      indirect_streambuf.hpp.bak.hpp and indirect_streambuf.~hpp.

19. details/chain.hpp:

    #if defined(BOOST_MSVC) && _MSC_VER == 1300
        virtual ~chain_base() { } // If omitted, some tests fail on VC7.0.

doesn't this change semantics of the class?

Ans ASCII class diagram could be here.

20. detail/iterator_traits.hpp: looking on specializations:
      would it make sense to have unsigned char/signed char
      versions as well?

    (There are more places with explicit instantions that would
     need possible update).

21. test lzo.cpp refers to non-existing boost/io/lzo.hpp.

22. io/file.hpp: what is exactly reason to have pimpl in
      basic_file_resource class?

      I do not see headers that don't need to be included,
      I do not see dynamic swicthing of pimpls, I do not see
      eager or lazy optimizations. I see only overhead and complexity.

23. io/memmap_file.hpp: why is pimpl in mapped_file_resource class?

24. io/regex_filter.hpp, function do_filter() contains:

    void do_filter(const vector_type& src, vector_type& dest)
            iterator first(&src[0], &src[0] + src.size(), re_, flags_);

     Is the &src[0] safe if vec is empty? I don't know if standard
     allows it, it just caught my eyes.


Boost list run by bdawes at, gregod at, cpdaniel at, john at