Topic: What does the standard say about file descriptors


Author: Dietmar Kuehl <dietmar.kuehl@claas-solutions.de>
Date: 1999/10/15
Raw View
Hi,
In article <THsN3.890$854.36433@burlma1-snr2>,
  Barry Margolin <barmar@bbnplanet.com> wrote:
> In article <7u5949$2kc$1@nnrp1.deja.com>,
> Dietmar Kuehl  <dietmar.kuehl@claas-solutions.de> wrote:
> >This stuff is not tested and only intended to give an expression what
> >is
> >necessary to create a new stream buffer. A real implementation with
> >support for seeking (not necessary for pipes...), buffering, etc. is
> >somewhat more involved. Also, to enhance the performance, a real
> >implementation might access stdio internals. Of course, this is then
> >again not portable...
>
> For this reason, wouldn't it be a good idea to define stdiobuf as a
> standard class?

This is probably a good idea but there are many other things which would
also be a good idea. Also, are several conflicts which might easily
result in a definition which is either too restrictive to be a real
option or would result in bad efficiency. For example, you mentioned
that people might want to switch between using the 'FILE*' with stdio
and iostream methods. It is already a real problem to specify the
semantics of this, not to mention the implications on the
implementation: Either 'FILE*' and 'stdiobuf' use a common buffer which
would impose certain restrictions on the implementation or the stuff
cannot be implemented efficiently because 'stdiobuf' would have to be
unbuffered. On the other hand, the user knows precisely what the
classes are supposed to do.

I wouldn't mind a 'stdiobuf' class but I'm also not that much interested
to push it. I'm planning to submit an implementation to
<http://www.boost.org/>. Since this stuff can be implemented quite
efficiently if the used 'FILE*' is not used otherwise (or the user can
accept strange effects due to buffering in two places) I don't think
that this stuff really has to go into the standard and if people think
differently, the Boost implementation would be a starting point for a
proposal.

Actually, I envision a very different approach to I/O in C and C++
anyway: 'FILE' could be a base class of 'basic_streambuf<char>' where
'basic_streambuf<char>' is the only class derived from 'FILE'. In this
case, a 'basic_streambuf<char>*' could be used everywhere a 'FILE*'
could be used and vice versa (the other way involves a little trickery
but it is doable). This would, of course, make a class like 'stdiobuf'
completely unnecessary and there would be no synchronization problems at
all. There are other advantages, too. For example, it would be easy to
extend the stdio system with new external representations (although this
could not be done in C: it would require the use of C++ what is fine
with me :-) and 'sync_with_stdio()' would be pointless.
--
<mailto:dietmar.kuehl@claas-solutions.de>
homepage: <http://www.informatik.uni-konstanz.de/~kuehl>


Sent via Deja.com http://www.deja.com/
Before you buy.


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Dietmar Kuehl <dietmar.kuehl@claas-solutions.de>
Date: 1999/10/14
Raw View
Hi,

to start by answering the question in the subject line: The standard is
silent about using file descriptors with standard streams. I haven't
checked but it is likely that the standard does not mention file
descriptors at all.

In article <qqlzoxmt4em.fsf@Ike.ERC.MsState.Edu>,
  Edward Luke <lush@erc.msstate.edu> wrote:
> I find that sometimes I need to interface iostream objects with low
> level POSIX file descriptors.  For example, I would like to have a
> ostream that connects to a pipe via POSIX popen().

... but 'popen()' is not related to file descriptors at all: It returns
a 'FILE*'! Some implementations have an extension which allows to use
a file descriptor as a constructor argument or as the argument to the
'open()' function. My implementation deliberately does not define such a
constructor: If you use it, you are using stuff outside the standard and
in this case you should better be aware of this fact. The approach to be
taken is to use a special stream buffer, eg. called 'POSIXbuf' for
obvious reasons, which can be constructed from a file descriptor and
which might also add other useful functionality which is specific to the
POSIX file handling, eg. locking, mmap(2)ing, access to file attributes,
etc. Such a stream buffer is, of course, highly platform specific but
reasonably easy to implement (I have an implementation which I want to
submit to <http://www.boost.org/> but I haven't yet decided on all the
involved features...).

Now to 'popen()': This is a fairly easy one. The interface to 'FILE*' is
standardized and thus it is possible and actually quite easy to
implement a simple stream buffer on top of 'FILE*'. Here is one for
starters:

  class stdiobuf: public std::streambuf {
  public:
    typedef std::char_traits<char> traits_type;
    typedef traits_type::int_type  int_type;

    stdiobuf(FILE* file): m_file(file) {}

  protected:
    int_type overflow(int_type c) {
      if (!traits_type::eq_int_type(c, traits_type::eof()))
        return std::fputc(c, m_file);
      return c;
    }
    int_type underflow() {
      int_type c = std::fgetc(m_file);
      if (!traits_type::eq_int_Type(c, traits_type::eof()))
      {
        m_buffer = c;
        setg(&m_buffer, &m_buffer, &m_buffer + 1);
      }
      return c;
    }

  private:
    FILE* m_file;
    char  m_buffer;
  };

This stuff is not tested and only intended to give an expression what is
necessary to create a new stream buffer. A real implementation with
support for seeking (not necessary for pipes...), buffering, etc. is
somewhat more involved. Also, to enhance the performance, a real
implementation might access stdio internals. Of course, this is then
again not portable...

>  I realize that this
> operation can be system specific, however I would like it to be as
> portable as possible (as in portable to all POSIX systems).  Do I have
> to abandon streams to accomplish this, or is there a `standard'
> approach or even a `suggested' approach?

If you need to write to or read from a stream which is not supported by
the standard C++ library, you can just create a new one. This is
somewhat different to the C library where there is no way to extend the
I/O mechanism. In C++ you can create various stream using very different
"external representations".
--
<mailto:dietmar.kuehl@claas-solutions.de>
homepage: <http://www.informatik.uni-konstanz.de/~kuehl>


Sent via Deja.com http://www.deja.com/
Before you buy.


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/10/14
Raw View
Edward Luke <lush@erc.msstate.edu> writes:
> Do I have to abandon streams to accomplish this, or is there a
> `standard' approach or even a `suggested' approach?

The standard and suggested approach is to derive a streambuf
which will read or write in whatever manner you choose. See
27.5.2.4.


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Matt Frantz <mhf@micron.com>
Date: 1999/10/14
Raw View
Edward Luke wrote:

> I find that sometimes I need to interface iostream objects with low
> level POSIX file descriptors.  For example, I would like to have a
> ostream that connects to a pipe via POSIX popen().  I realize that this
> operation can be system specific, however I would like it to be as
> portable as possible (as in portable to all POSIX systems).  Do I have
> to abandon streams to accomplish this, or is there a `standard'
> approach or even a `suggested' approach?
>
> - Ed

Writing a subclass of std::streambuf is a technique that enjoys widespread
support.  Even more general would be a subclass template of
std::basic_streambuf.

#include <streambuf>
template<class charT, class traits = char_traits<charT> >
class my_streambuf : public basic_streambuf< charT, traits > {
...
}


Regards,
Matt



[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Barry Margolin <barmar@bbnplanet.com>
Date: 1999/10/15
Raw View
In article <7u5949$2kc$1@nnrp1.deja.com>,
Dietmar Kuehl  <dietmar.kuehl@claas-solutions.de> wrote:
>This stuff is not tested and only intended to give an expression what is
>necessary to create a new stream buffer. A real implementation with
>support for seeking (not necessary for pipes...), buffering, etc. is
>somewhat more involved. Also, to enhance the performance, a real
>implementation might access stdio internals. Of course, this is then
>again not portable...

For this reason, wouldn't it be a good idea to define stdiobuf as a
standard class?  It's likely that C++ programs will have frequent need to
interact with C libraries that return FILE*, much like popen(), and it
would be nice to have a standard way to convert them to C++ iostreams.

There should be caveats about switching back and forth between using the C
and C++ interfaces on the same stream, due to each potentially doing their
own buffering, and perhaps a member function to synchronize them prior to
switching between th interfaces.

--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Barry Margolin <barmar@bbnplanet.com>
Date: 1999/10/15
Raw View
In article <qqlzoxmt4em.fsf@Ike.ERC.MsState.Edu>,
Edward Luke  <lush@erc.msstate.edu> wrote:
>I find that sometimes I need to interface iostream objects with low
>level POSIX file descriptors.  For example, I would like to have a
>ostream that connects to a pipe via POSIX popen().

popen() doesn't return a file descriptor, it returns a stdio FILE*.  You
can use stdio from C++.

--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Edward Luke <lush@erc.msstate.edu>
Date: 1999/10/14
Raw View


I find that sometimes I need to interface iostream objects with low
level POSIX file descriptors.  For example, I would like to have a
ostream that connects to a pipe via POSIX popen().  I realize that this
operation can be system specific, however I would like it to be as
portable as possible (as in portable to all POSIX systems).  Do I have
to abandon streams to accomplish this, or is there a `standard'
approach or even a `suggested' approach?

- Ed

___________________________________________________________________
Ed Luke                                        lush@erc.msstate.edu
NSF Engineering Research Center for Computational Field Simulations
Mississippi State University       http://www.erc.msstate.edu/~lush


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]