Topic: Forwarding streambuf problems


Author: f_clerc@effix.fr (Fabrice Clerc)
Date: 1996/08/26
Raw View

I'm currently trying to write a "forwarding streambuf" and encounter
annoying portability problems.  Tested on four different platforms, the
code sample you'll find below behaves in four different ways.

I believe there are two issues:

1- the streambuf's sync method is not always called when the endl
   manipulator is used.
2- ostream::~ostream seems to access (and sync) the streambuf.

Each platform gives a different combination of 1 and 2 (see below).

Is there something wrong with the code?
Why 1?  Is there a workaround for it (I have one for 2)?
What does the most recent draft standard say about these issues
(and about streambuf access in ostream's ctor)?

Thanks

---
Fabrice Clerc - mailto:f_clerc@effix.fr - Effix SA


---------------------------------------------------

#include <iostream.h>

class A: public streambuf {

  public:

    A(streambuf& sb):sb_(sb) {

      setp(0,0);
      setg(0,0,0);
    }

    virtual int sync() {

      cerr<<"A::sync"<<endl;
      return sb_.sync();
    }

    virtual int overflow(int c) {

      return (c==EOF) ? !EOF : sb_.sputc(c);
    }

    virtual int underflow() {

      return EOF;
    }

  private:

    streambuf& sb_;
};

class B: public ostream {

  public:

    // oops: memory leak (it's ok, the "real" code does not have it)
    B(ostream& os):ostream(new A(*os.rdbuf())) {}
};

int main() {

  B b(cout);

  b<<"123"<<endl;

  cerr<<"done"<<endl;

  return 0;
}

/*
Solaris/CC4.01
123
A::sync
done
A::sync

HP-UX/CC??
123
done
A::sync

NT/VC++4.0
123
A::sync
done

AIX/xlC??
123
done
*/


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1996/08/27
Raw View
In article <3232cbc6.369037047@zeland> f_clerc@effix.fr (Fabrice Clerc)
writes:

|> I'm currently trying to write a "forwarding streambuf" and encounter
|> annoying portability problems.  Tested on four different platforms, the
|> code sample you'll find below behaves in four different ways.

|> I believe there are two issues:

|> 1- the streambuf's sync method is not always called when the endl
|>    manipulator is used.

This would be an error in the compiler.  The current draft says that
rdbuf()->pubsync() must be called.  Earlier documentation of the
reference implementation (Cfront, in my case, the Sun version) says that
any characters stored into the associated streambuf will be flushed.  I
don't know what else this could mean but to call rdbuf()->sync().

|> 2- ostream::~ostream seems to access (and sync) the streambuf.

Curiously enough, this is what I would have expected.  The working
papers say otherwise, however, and the documentation from Sun doesn't
say one way or another.  I can see arguments for not doing it (in
ostream), however.  I also see that I don't do this in my own code.

|> Each platform gives a different combination of 1 and 2 (see below).

|> Is there something wrong with the code?
|> Why 1?  Is there a workaround for it (I have one for 2)?
|> What does the most recent draft standard say about these issues
|> (and about streambuf access in ostream's ctor)?

The recent draft is clear: endl must cause sync to be called, the
destructor may not.

In general, the additional sync in the destructor should not be a
problem, except maybe for slowing things down.  The missing sync in endl
is a serious problem, however.  I would complain mightily to the
implementor.  The only work-around I can think of is to write your own
version of endl, and use that.

FWIW: I've always called "unbuffered( 1 )" in the streambuf constructor.
I want all buffering, etc. to take place in the final streambuf.  (This
is very important if you are mixing output through the forwarding
streambuf and the final streambuf, as I sometimes am.)  I also pass the
setbuf function up to the final streambuf, as this is the only streambuf
which should be doing any buffering.  Finally, the destructor for the
forwarding streambuf should ensure that any characters that haven't yet
been forwarded are sent to the final streambuf.
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils,    tudes et r   alisations en logiciel orient    objet --
                -- A la recherche d'une activit    dans une region francophone



[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]