Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtualise initializers #2

Open
hotgloupi opened this issue Mar 12, 2015 · 2 comments
Open

Virtualise initializers #2

hotgloupi opened this issue Mar 12, 2015 · 2 comments

Comments

@hotgloupi
Copy link

First of all, thanks for the good work here, the API is very clean, and yet extensible and practical, which is a good thing when trying to abstract something so different across OSes.

However, I don't fully understand why the code is so much static. Why did you choose to use compile time polymorphism (i.e. templates) instead of runtime polymorphism (i.e. vtables) ? IMHO the overhead of spawning a process makes the cost of a vtable access ridiculous.

My problem, somewhat related to the previous question, is how to create a set of initializers, and then spawn a process. I would like to do something like:

std::vector<Initializer> initializers;
if (some_condition)
    initializers.push_back(some_initializer);
auto child = boost::process::executor()(args, initializers);

In order to create the type Initializer, I would have to do complicated things:

template<typename Executor>
struct InitializerBase
{
      virtual void on_fork_setup(Executor& e) = 0;
     // ... other methods here
};

template<typename Executor, typename ConcreteInitializer>
struct InitializerWrapper : InitializerBase<Executor>
{
    ConcreteInitializer _initializer;
    template<typename... Args
    explicit InitializerWrapper(Args&&... args)
        : _initializer(std::forward<Args>(args)...)
    {}
    void on_fork_setup(Executor& e) override { _initializer.on_fork_setup(e); }
     // ... other methods here
};

template<typename Executor>
struct _Initializer
{
    typedef Executor executor_type;
    std::unique_ptr<InitializerBase> _initializer;
    void on_fork_setup(Executor& e) { _initializer.on_fork_setup(e); }
   // ... other methods here
}

#ifdef POSIX_SOMETHING
typedef _Initializer<PosixExecutor> Initializer;
#else
// something else
#endif

template<typename ConcreteInitializer, typename... Args>
Initializer make_initializer(Args&&... args)
{
  return Initializer(new InitializerWrapper<typename Initializer::executor_type, ConcreteInitializer>(
     std::forward<Args>(args)...);
}

(I omitted the boilerplate code for constructors and destructors)

That's pretty much re-virtualizing your code ... Do you know a better way ?

@BorisSchaeling
Copy link
Owner

First thank you for your feedback on the API! Credit goes to Jeff Flinn who proposed the current API back in 2011.

Regarding static code: I think it's just that no one had a requirement so far to detect at run-time which initializers to use. As people knew their requirements at compile-time, they wanted to use static code. However I can see how a small initializer hierarchy with a base class could be useful (especially as performance indeed doesn't really matter).

As I'm not working on the library anymore (at least there is nothing planned for now), I'm afraid I can't offer any help. But you are very much invited to fork and change the library!

@nat-goodspeed
Copy link

Please see #8 for a solution using Boost.TypeErasure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants