[process] Arguments and Context concepts

Hi, Where can I find the concept behind the template parameters Arguments and Context in template<typename Arguments, typename Context> child create_child(const std::string & executable, Arguments args, Context ctx); Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/process-Arguments-and-Context-concepts-tp... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Wed, 19 Jan 2011 14:58:21 +0100, Vicente Botet <vicente.botet@wanadoo.fr> wrote: Hi Vicente,
Where can I find the concept behind the template parameters Arguments and Context in
template<typename Arguments, typename Context> child create_child(const std::string & executable, Arguments args, Context ctx);
it should be possible to use any container for Arguments as long as its elements are std::strings. The flexibility regarding Context is more theoretical (you basically have to copy boost::process::context and can't leave anything out). In early versions of the library one of the goals was to support multiple string types. In practice nothing but std::string ever worked. There were once also multiple context classes when the library shipped platform-specific classes for POSIX and Windows. As of today create_child() heavily depends on boost::process::context though. HTH, Boris

----- Original Message ----- From: "Boris Schaeling" <boris@highscore.de> To: <boost@lists.boost.org> Sent: Wednesday, January 19, 2011 11:59 PM Subject: Re: [boost] [process] Arguments and Context concepts
On Wed, 19 Jan 2011 14:58:21 +0100, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
Hi Vicente,
Where can I find the concept behind the template parameters Arguments and Context in
template<typename Arguments, typename Context> child create_child(const std::string & executable, Arguments args, Context ctx);
it should be possible to use any container for Arguments as long as its elements are std::strings. The flexibility regarding Context is more theoretical (you basically have to copy boost::process::context and can't leave anything out).
In early versions of the library one of the goals was to support multiple string types. In practice nothing but std::string ever worked. There were once also multiple context classes when the library shipped platform-specific classes for POSIX and Windows. As of today create_child() heavily depends on boost::process::context though.
We could have multiple implementations of the same concept and have just one in a specific platform. In this case we have always the same class and having a template parameter is not realy useful. If the requirements are too close to the current context implementation, which is the advantage to pass Context as template parameter then? What about adding this overloading? template <typename Context> child create_child(const std::string &executable, const Context & ctx); You should need enable_if and some way to recognize if the parameter is a Context or some Arguments to disambiguate, but it should be possible, and this avoids to have an additional args variable when no args at all are needed. BTW, are you copying the parameters Arguments and Context now? Why not pass by reference? A see the change to the working directory as a really specific case. I would pass it as an argument to the process creation and let the child process make itself the change to the working directory. Could you tell us why did you need to added it? An alternative to multiple overloading could be to use the essence pattern of a child process creation and pass to the function a single parametter: child create_child(const creation_essence & ); and make the cchild reation essence a class that force the mandatory parameters at construction time. class creation_essence { public: creation_essence(const std::string &absolute_path_to_executable); creation_essence(const std::string &process_name, const std::string &path); void add_arg(const std::string &); void set_env(const std::string &,const std::string &); void set_working_dir(const std::string &); ... Other more efficient overloads could also be added (using const char* for example); // observers needed by the back end ... }; So intead of the example in the doc std::string exe = boost::process::find_executable_in_path("hostname"); std::vector<std::string> args; boost::process::context ctx; ctx.process_name = "hostname"; ctx.work_dir = "C:\\"; ctx.env.insert(std::make_pair("new_variable", "value")); boost::process::create_child(exe, args, ctx); we could have creation_essence prm(boost::process::find_executable_in_path("hostname"); prm.set_process_name("hostname"); prm.set_working_dir("C:\\"); prm.add_env("new_variable", "value"); boost::process::create_child(prm); or creation_essence prm("hostname", ""); prm.set_working_dir("C:\\"); prm.set_env("new_variable", "value"); boost::process::create_child(prm); This interface should be more close to what a DSL could need and the implementation could be more platform driven. Boost.Parameter could also be cosidered. HTH, Vicente

On Thu, 20 Jan 2011 08:21:43 +0100, vicente.botet <vicente.botet@wanadoo.fr> wrote:
[...]We could have multiple implementations of the same concept and have just one in a specific platform. In this case we have always the same class and having a template parameter is not realy useful. If the requirements are too close to the current context implementation, which is the advantage to pass Context as template parameter then?
Indeed, it's questionable if there is an advantage at all. I guess we left the template parameter just in case someone wants to use another type for reasons unknown to us.
What about adding this overloading?
template <typename Context> child create_child(const std::string &executable, const Context & ctx);
You should need enable_if and some way to recognize if the parameter is a Context or some Arguments to disambiguate, but it should be possible, and this avoids to have an additional args variable when no args at all are needed.
Yes, makes sense!
BTW, are you copying the parameters Arguments and Context now? Why not pass by reference?
One goal was to create multiple child processes with the same parameters. While the Arguments parameter is still changed by create_child() I see that Context isn't anymore (probably a side effect of another change to the context class when we redesigned the way streams are configured).
A see the change to the working directory as a really specific case. I would pass it as an argument to the process creation and let the child process make itself the change to the working directory. Could you tell us why did you need to added it?
Well, you might not have access to the source code for example and can't make the child process change the working directory. A more important reason is though that I'd describe Boost.Process as a library trying to support as many high-level cross-platform concepts as possible. I guess that's the current goal after we gave up other ideas like trying to support as many platform-specific features as possible (that was when we had POSIX and Windows classes which could have grown endlessly and would still never have been complete; now we have extension points to provide the flexibility of using platform-specific features).
An alternative to multiple overloading could be to use the essence pattern of a child process creation and pass to the function a single parametter:
child create_child(const creation_essence & );
In my opinion our current context class is rather small that this isn't required (it was much worse before when we had POSIX and Windows context classes). I think something like this would help if the context class grew again. This again depends on high-level cross-platform concepts we might be able to identify to describe a process context. But if you look at things like uid on POSIX or SECURITY_ATTRIBUTES on Windows it's rather difficult to imagine how high-level cross-platform concepts could look like to support these things in Boost.Process. It looks like context is already pretty much complete. Boris
[...]

----- Original Message ----- From: "Boris Schaeling" <boris@highscore.de> To: <boost@lists.boost.org> Sent: Friday, January 21, 2011 12:01 AM Subject: Re: [boost] [process] Arguments and Context concepts
On Thu, 20 Jan 2011 08:21:43 +0100, vicente.botet <vicente.botet@wanadoo.fr> wrote:
[...]We could have multiple implementations of the same concept and have just one in a specific platform. In this case we have always the same class and having a template parameter is not realy useful. If the requirements are too close to the current context implementation, which is the advantage to pass Context as template parameter then?
Indeed, it's questionable if there is an advantage at all. I guess we left the template parameter just in case someone wants to use another type for reasons unknown to us.
Could you document the requirments i nthe reference section?
What about adding this overloading?
template <typename Context> child create_child(const std::string &executable, const Context & ctx);
You should need enable_if and some way to recognize if the parameter is a Context or some Arguments to disambiguate, but it should be possible, and this avoids to have an additional args variable when no args at all are needed.
Yes, makes sense!
Great.
BTW, are you copying the parameters Arguments and Context now? Why not pass by reference?
One goal was to create multiple child processes with the same parameters. While the Arguments parameter is still changed by create_child() I see that Context isn't anymore (probably a side effect of another change to the context class when we redesigned the way streams are configured).
Then you could pass Context by cont& without any change on user code. You could commeback to pass by value if you need to modify it.
A see the change to the working directory as a really specific case. I would pass it as an argument to the process creation and let the child process make itself the change to the working directory. Could you tell us why did you need to added it?
Well, you might not have access to the source code for example and can't make the child process change the working directory.
This is too specific to be included in a Process library.
A more important reason is though that I'd describe Boost.Process as a library trying to support as many high-level cross-platform concepts as possible. I guess that's the current goal after we gave up other ideas like trying to support as many platform-specific features as possible (that was when we had POSIX and Windows classes which could have grown endlessly and would still never have been complete; now we have extension points to provide the flexibility of using platform-specific features).
I don't find the answer to my question here.
An alternative to multiple overloading could be to use the essence pattern of a child process creation and pass to the function a single parametter:
child create_child(const creation_essence & );
In my opinion our current context class is rather small that this isn't required (it was much worse before when we had POSIX and Windows context classes). I think something like this would help if the context class grew again. This again depends on high-level cross-platform concepts we might be able to identify to describe a process context. But if you look at things like uid on POSIX or SECURITY_ATTRIBUTES on Windows it's rather difficult to imagine how high-level cross-platform concepts could look like to support these things in Boost.Process. It looks like context is already pretty much complete.
The same interface arguments applies to the Context concept independently of whether you use an essence argument. If you require a more high level interface for the Context concept, you will be able to implement it as efficiente as posible on specific platforms. The current concept behind the Context parameter has a user interface that is not enough abstract. The use of specific fields depending on std::string forbids any possible optimisation. Best, Vicente

On Fri, 21 Jan 2011 08:21:56 +0100, vicente.botet <vicente.botet@wanadoo.fr> wrote:
[...]Could you document the requirments i nthe reference section?
Ok, I can try. I'm afraid I have to copy&paste the documentation of the context class. :-)
[...]Then you could pass Context by cont& without any change on user code. You could commeback to pass by value if you need to modify it.
I agree and will change it.
[...]
Well, you might not have access to the source code for example and can't make the child process change the working directory.
This is too specific to be included in a Process library.
I find this a very subjective argument. If we leave everything out someone finds too specific there is probably nothing left. :-)
A more important reason is though that I'd describe Boost.Process as a library trying to support as many high-level cross-platform concepts as possible. I guess that's the current goal after we gave up other ideas like trying to support as many platform-specific features as possible (that was when we had POSIX and Windows classes which could have grown endlessly and would still never have been complete; now we have extension points to provide the flexibility of using platform-specific features).
I don't find the answer to my question here.
The answer is that Boost.Process tries to support high-level features which can be supported on all platforms. This is my attempt to make decision making on what should be included in the library less subjective. For example I got a request to make it possible to pass the WNOHANG parameter to boost::process::wait() on POSIX systems to make the function non-blocking. I rejected the request on the ground that the WNOHANG parameter is not cross-platform. If we support this in the library users will have to use preprocessor macros. But then they can simply call system functions directly and don't need to use Boost.Process at all. While WNOHANG is too platform-specific the idea of making boost::process::wait() non-blocking should work on all platforms though. It won't be WNOHANG but something else (like for example a boolean parameter) to indicate that boost::process::wait() should not block.
[...]The same interface arguments applies to the Context concept independently of whether you use an essence argument. If you require a more high level interface for the Context concept, you will be able to implement it as efficiente as posible on specific platforms. The current concept behind the Context parameter has a user interface that is not enough abstract. The use of specific fields depending on std::string forbids any possible optimisation.
Can you show me some sample code which you think will allow us to benefit from the abstraction you talk about? I agree that the context class is not very abstract. But with only five member variables it's rather simple and immediately usable for anyone. I'm a bit worried that abstraction makes something that simple unnecessarily complicated? Boris

Boris Schaeling wrote:
On Fri, 21 Jan 2011 08:21:56 +0100, vicente.botet <vicente.botet@wanadoo.fr> wrote: ...
[...]
Well, you might not have access to the source code for example and can't make the child process change the working directory.
This is too specific to be included in a Process library.
I find this a very subjective argument. If we leave everything out someone finds too specific there is probably nothing left. :-)
A more tangible argument is that the working directory must be set to the location of the to-be-exec'd executable for Mac OSX to properly launch a child process. It would be difficult to have the calling application change the directory and change it back as currently the posix fork/exec paradigm is not synchronous. Jeff

----- Original Message ----- From: "Jeff Flinn" <TriumphSprint2000@hotmail.com> To: <boost@lists.boost.org> Sent: Sunday, January 23, 2011 4:29 PM Subject: Re: [boost] [process] Arguments and Context concepts
Boris Schaeling wrote:
On Fri, 21 Jan 2011 08:21:56 +0100, vicente.botet <vicente.botet@wanadoo.fr> wrote: ...
[...]
Well, you might not have access to the source code for example and can't make the child process change the working directory.
This is too specific to be included in a Process library.
I find this a very subjective argument. If we leave everything out someone finds too specific there is probably nothing left. :-)
A more tangible argument is that the working directory must be set to the location of the to-be-exec'd executable for Mac OSX to properly launch a child process. It would be difficult to have the calling application change the directory and change it back as currently the posix fork/exec paradigm is not synchronous.
Boost.Process don't needs a specific work_dir to be able to do it. Shouldn't Boost.Process do it transparently without the user been forced to change the work_dir on the Context.? Best, Vicente

----- Original Message ----- From: "Boris Schaeling" <boris@highscore.de> To: <boost@lists.boost.org> Sent: Sunday, January 23, 2011 3:32 PM Subject: Re: [boost] [process] Arguments and Context concepts
On Fri, 21 Jan 2011 08:21:56 +0100, vicente.botet <vicente.botet@wanadoo.fr> wrote:
[...]The same interface arguments applies to the Context concept independently of whether you use an essence argument. If you require a more high level interface for the Context concept, you will be able to implement it as efficiente as posible on specific platforms. The current concept behind the Context parameter has a user interface that is not enough abstract. The use of specific fields depending on std::string forbids any possible optimisation.
Can you show me some sample code which you think will allow us to benefit from the abstraction you talk about? I agree that the context class is not very abstract. But with only five member variables it's rather simple and immediately usable for anyone. I'm a bit worried that abstraction makes something that simple unnecessarily complicated?
The problem I see is that you are using std::string in the public data types of the fields, which avoids to have an efficient implementation and requiring containers that have nothing to be with the ones needed by the underlying platform interface. The current function to create follows this prototype: template<typename Arguments, typename Context> child create_child(const std::string & executable, Arguments args, Context ctx); Arguments must be a container of std::string, and the process_name will be inserted at the begining of the container if given explicitly on the Context. Context has 3 fields that depend on std::string std::string process_name; std::string work_dir; environment env;env field must have as type an associative container mapping std::string to std::string. I would move the process_name data to the Arguments concept. For what I have see on the implementation there are two main way to pass arguments at process creation: C-like: using const char** args Windows: Using a const char* command line following a specific grammar I would try to abstract both strategies in something like template <std::size_t N=0> struct arguments { arguments(); arguments(const char* process_name); ~arguments(); const char* get_process_name() const; void set_process_name(const char* process_name); void add(const char* arg); const char* set_command_line(); const char* get_command_line(); std::size_t argc() const; const char** args() const; private: std::size_t argc_; const char* args_[N+1]; const char* command_line_; bool args_must_be_released_; bool command_line_must_be_released_; }; Users that use to work on C-like systems could use the add() function. arguments <2> args("pn"); args.add("-l"); args.add("-r"); create_child(find_executable_in_path("pn"), args); Windows users will prefer the set_command_line function. arguments <2> args(); args.set_command_line("pn -l -r"); For these two use cases, the preceding class can be implemented in a way that is as effcient as possible avoiding copies, allocations, releases. User that write portable programms would need to choose between one of the two ways to pass the arguments. Of course the programm could use some conditional compilation that could use the most efficient. If the user uses the add inteface on Windows, the implementation will be as efficient as now. If the user uses the set_command_line on c-like systems, the class need to tokenize the arguments. Copies, allocation and releases will be needed in these cases as it is done now. The same applies to the Environment Concept. Whether we have multiple overload, we use an essence pattern or Boost.Parameter can be decided later. What we need are two concepts for Arguments and Environment that can be implemented as efficiently as we would do when using the platform specific interfaces. Maybe I'm trying to optimize before measuring, but ... is just how I would do it. Take whatever you consider can improve your library. Best, Vicente

On Sun, 23 Jan 2011 21:59:37 +0100, vicente.botet <vicente.botet@wanadoo.fr> wrote:
[...]For these two use cases, the preceding class can be implemented in a way that is as effcient as possible avoiding copies, allocations, releases.
Thanks, now I understand better! As I don't feel so strongly about it we can ask others for their opinion when the review of the library starts? I have already some items on my list where I'd like reviewers to look at - this could be another one. Boris
[...]
participants (4)
-
Boris Schaeling
-
Jeff Flinn
-
Vicente Botet
-
vicente.botet