Dear Boris, dear Klemens,
On 06 Nov 2016, at 20:59, Boris Schäling
wrote: There were not only incremental improvements though but also tangible results: We always wanted to support asynchronous I/O in [Boost.]Process. This included waiting asynchronously for a child process to exit. So we worked on a new I/O service object to support asynchronous waiting on Windows. The I/O service object was added to Boost.Asio in 2012 (known as boost::asio::windows::object_handle).
A huge step forward was the introduction of executors and initializers - an idea from Jeff Flinn in 2011. All [Boost.]Process versions since then are based on executors and initializers. His idea changed the design of [Boost.]Process quite a lot as it provides a generic solution to the problem of how to make [Boost.]Process extensible. It is important to understand Jeff's idea and the problem it solves as any other C++ process management library has to solve the very same problem to be at least as good in that aspect.
It turns out that when creating a child process an infinite number of configuration options can be set. The Windows and Linux functions being called when a child process is created accept only a limited number of arguments. If however, for example, the root directory of a child process on Linux should be changed, the function chroot() has to be called. The configuration option "root directory" is set through an additional function call. It's easy to create a C++ process management library which just supports a few cross-platform configuration options. It's much more difficult to create a C++ process management library which allows a library user to customize the process of creating child processes any way he likes. Jeff's idea was to use objects as named parameters. If [Boost.]Process provides a function which accepts any objects (or actually any types), library users can create their own named parameters and pass them to that function. They could for example create a named parameter which changes the root directory for a child process.
Jeff's idea isn't necessarily the only solution to how to provide an extensible interface. And of course one could argue that this is a negligible problem a process management library doesn't need to solve. For [Boost.]Process extensibility has always been one of the major goals though. We want to avoid that developers start using [Boost.]Process only to find out later that they can't do what they need to do because the library isn't extensible enough. Ideally any alternative process management library states if and how it solves this problem.
Here are some of the other not so obvious goals of [Boost.]Process:
* It should be entirely clear to a library user how resources are managed (which resources could leak when and how, and how the library helps a user to avoid leaking resources; and I'm not talking about resources you could manage with a smart pointer or alike).
* It should be possible to do asynchronous I/O (this includes reading, writing and waiting for child processes to exit).
* Similar concepts found across operating systems should be represented by one concept (for example, standard streams), different concepts should be represented by different concepts (for example, signals on Linux and object handles on Windows - these are the OS services used for asynchronous waiting).
I'm not going to discuss these goals and the current solutions in detail (this email is already too long; I will talk about resource management in [Boost.]Process at Meeting C++ in case anyone wants to know more).
thank you for this summary of the design principles and goals. I would like to see this added to the Design Rationale in the documentation for [boost.]process. Laying out design principles and goals is very useful: - They are easier to grasp than the implementation. - They allow reviewers to check whether they agree with the principles and goals. - Reviewers can check, whether the implementation actually follows the principles. Best regards, Hans