Boost logo

Boost :

Subject: Re: [boost] [process] Arguments and Context concepts
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2011-01-23 15:59:37


----- Original Message -----
From: "Boris Schaeling" <boris_at_[hidden]>
To: <boost_at_[hidden]>
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_at_[hidden]> 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


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