boost-process
boost-process copied to clipboard
Virtualise initializers
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 ?
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!
Please see https://github.com/BorisSchaeling/boost-process/pull/8 for a solution using Boost.TypeErasure.