Boost logo

Boost :

Subject: Re: [boost] [gsoc] Boost.Process done
From: Boris Schaeling (boris_at_[hidden])
Date: 2010-09-05 10:05:36


As there has been a lot of feedback I started to update the library. There
is now a new version available at
<http://www.highscore.de/boost/gsoc2010/process.zip> (and of course in
Subversion at <http://svn.boost.org/svn/boost/sandbox/SOC/2010/process/>).

What has been changed?

* The context class now uses delegates based on boost::function to
configure standard streams. There is no class hierarchy anymore for stream
behavior classes. Nothing needs to be created on the heap either (and
consequently boost::shared_ptr is gone). Context objects can be reused now
to create multiple child processes.

* The delegates in the context class expect this signature:
std::pair<handle, handle> (bool). There is a parameter of type bool passed
to indicate whether an input or an output stream is configured. Now it's
not required anymore to pass a parameter like input_stream or
output_stream yourself.

* All stream behaviors have been defined as function objects. While it
would be possible to create standalone functions for some stream behaviors
(like behavior::close which would return a pair of empty handles) for
consistency I defined function objects only.

* behavior::named_pipe now requires the developer to set the name of the
pipe (and does not automatically generate a unique name anymore).

* behavior::async_pipe is a new stream behavior which uses the minimum
required pipe type on a platform to support asynchronous I/O. It's a
typedef for (anonmyous) pipe on POSIX and a function object based on
behavior::named_pipe on Windows (automatically generating a unique name
with UuidCreateSequential()).

I'd appreciate if you could comment on the changes. Especially have a look
at:

* this signature: std::pair<handle, handle> (bool). Shall we use
std::pair<handle, handle> to return two handles for the child and parent
process or a struct with member variables called parent_end and child_end?
Shall we use a bool to indicate whether an input or output stream is
configured or something else like an enumeration? I think it all depends
on how many developers want to define new stream behaviors and if it's
worth to make the signature a bit more self-explanatory?

* the implementation of async_pipe on Windows. Are return values of
Windows functions checked correctly? Is the return value of
UuidCreateSequential() and UuidToStringA() the error code or must
GetLastError() be called? Is it OK if we require developers to link
against rpcrt4.lib on Windows because async_pipe uses
UuidCreateSequential() now?

* the example at
<http://svn.boost.org/svn/boost/sandbox/SOC/2010/process/libs/process/example/redirect_to.cpp>.
It uses a user-defined behavior class to redirect the child's standard
error stream to the standard output stream. As the behavior of the
standard error stream must somehow access the handle of the standard
output stream I create the pipe myself before I set the stream behaviors.
As the pipe must be used for the standard output stream though I define a
forward function which I can bind to the respective delegate. Anyway,
please have a look at the example and think about whether it makes sense
or if there is anything to simplify. :-)

What still has to be done?

* The context class still has a default constructor only which initializes
the stream behaviors to inherit standard streams. This is a problem for
Windows GUI applications as they don't have standard streams (or at least
they are closed). While the Named Constructor Idiom has been proposed what
exactly should the done? Should the default constructor be private and
developers must explicitly use a factory function to create a context
object? Shall the factory function initialize all standard streams with
the same behavior? Shall we provide a factory function which expects three
parameters to initialize the standard streams? What's convenient and
flexible and not too confusing?

* I didn't get rid yet of boost::filesystem::filesystem_error,
boost::algorithm::ends_with and boost::algorithm::iends_with in
operations.hpp. I read Ilya's posting and understand that he is worried
about including too much. I checked Boost.Filesystem's header files and
saw that filesystem/exception.hpp is empty and the exception classes have
been moved to filesystem/path.hpp. I don't know the reason but wonder
whether this shouldn't be changed then in Boost.Filesystem. If a Boost
library can't include a header file from another Boost library because the
header file is too big the header file should be split?
Boost.StringAlgorithms is better in this regard (and I included only
boost/algorithm/string/predicate.hpp and not everything from
Boost.StringAlgorithms; of course this header file includes other header
files from Boost.StringAlgorithms again...). Anyway, if anyone wants to
reimplement find_executable_in_path() and executable_to_progname() (both
in operations.hpp) I'm fine with it. I'm honestly not that motivated to
reinvent the wheel and hope I can spend my time doing something more
productive.

* The documentation must be updated (which I'll do when everyone agrees
that the changes make sense).

Boris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk