diff --git a/boost/process/posix/initializers.hpp b/boost/process/posix/initializers.hpp index 78295c1..a3d089d 100644 --- a/boost/process/posix/initializers.hpp +++ b/boost/process/posix/initializers.hpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/boost/process/posix/initializers/sequence.hpp b/boost/process/posix/initializers/sequence.hpp new file mode 100644 index 0000000..afe5236 --- /dev/null +++ b/boost/process/posix/initializers/sequence.hpp @@ -0,0 +1,106 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_SEQUENCE_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_SEQUENCE_HPP + +#include +#include +#include +#include +#include +#include + +// Define initializer_base methods to Boost.TypeErasure. The convenience macro +// must be used in the global namespace. +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(posix)(initializers)(has_on_fork_setup), + on_fork_setup, 1) +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(posix)(initializers)(has_on_fork_error), + on_fork_error, 1) +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(posix)(initializers)(has_on_fork_success), + on_fork_success, 1) +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(posix)(initializers)(has_on_exec_setup), + on_exec_setup, 1) +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(posix)(initializers)(has_on_exec_error), + on_exec_error, 1) + +namespace boost { namespace process { namespace posix { namespace initializers { + +// any_initializer should be able to store any subclass of initializer_base. +// We use Boost.TypeErasure because initializer_base is not itself +// polymorphic. This constrains the methods to accept specifically executor& +// rather than a template argument, but that should only be a problem for a +// user-coded initializer that expects an executor subclass. If such an +// initializer is stored in any_initializer, you might have to static_cast the +// argument to your executor type. +typedef + boost::type_erasure::any< + boost::mpl::vector< + boost::type_erasure::copy_constructible<>, + has_on_fork_setup , + has_on_fork_error , + has_on_fork_success, + has_on_exec_setup , + has_on_exec_error , + boost::type_erasure::relaxed> > + any_initializer; + +// sequence_wrapper_ adapts any copyable runtime container acceptable to +// boost::range::for_each() -- e.g. std::vector -- for use as +// an execute() initializer. +template +struct sequence_wrapper_: public initializer_base +{ + sequence_wrapper_(const Sequence& c): sequence_(c) {} + + Sequence sequence_; + + template + void on_fork_setup(PosixExecutor& e) const + { + boost::range::for_each(sequence_, typename PosixExecutor::call_on_fork_setup(e)); + } + + template + void on_fork_error(PosixExecutor& e) const + { + boost::range::for_each(sequence_, typename PosixExecutor::call_on_fork_error(e)); + } + + template + void on_fork_success(PosixExecutor& e) const + { + boost::range::for_each(sequence_, typename PosixExecutor::call_on_fork_success(e)); + } + + template + void on_exec_setup(PosixExecutor& e) const + { + boost::range::for_each(sequence_, typename PosixExecutor::call_on_exec_setup(e)); + } + + template + void on_exec_error(PosixExecutor& e) const + { + boost::range::for_each(sequence_, typename PosixExecutor::call_on_exec_error(e)); + } +}; + +// sequence() is a convenience function to construct a sequence_wrapper_ +// without having to state T. +template +sequence_wrapper_ +sequence(const Sequence& c) +{ + return sequence_wrapper_(c); +} + +}}}} + +#endif diff --git a/boost/process/windows/initializers.hpp b/boost/process/windows/initializers.hpp index 2d7098c..a99a6e2 100644 --- a/boost/process/windows/initializers.hpp +++ b/boost/process/windows/initializers.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/boost/process/windows/initializers/sequence.hpp b/boost/process/windows/initializers/sequence.hpp new file mode 100644 index 0000000..213418b --- /dev/null +++ b/boost/process/windows/initializers/sequence.hpp @@ -0,0 +1,88 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SEQUENCE_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SEQUENCE_HPP + +#include +#include +#include +#include +#include +#include + +// Define initializer_base methods to Boost.TypeErasure. The convenience macro +// must be used in the global namespace. +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(windows)(initializers)(has_on_CreateProcess_setup), + on_CreateProcess_setup, 1) +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(windows)(initializers)(has_on_CreateProcess_error), + on_CreateProcess_error, 1) +BOOST_TYPE_ERASURE_MEMBER((boost)(process)(windows)(initializers)(has_on_CreateProcess_success), + on_CreateProcess_success, 1) + +namespace boost { namespace process { namespace windows { namespace initializers { + +// any_initializer should be able to store any subclass of initializer_base. +// We use Boost.TypeErasure because initializer_base is not itself +// polymorphic. This constrains the methods to accept specifically executor& +// rather than a template argument, but that should only be a problem for a +// user-coded initializer that expects an executor subclass. If such an +// initializer is stored in any_initializer, you might have to static_cast the +// argument to your executor type. +typedef + boost::type_erasure::any< + boost::mpl::vector< + boost::type_erasure::copy_constructible<>, + has_on_CreateProcess_setup , + has_on_CreateProcess_error , + has_on_CreateProcess_success, + boost::type_erasure::relaxed> > + any_initializer; + +// sequence_wrapper_ adapts any copyable runtime container acceptable to +// boost::range::for_each() -- e.g. std::vector -- for use as +// an execute() initializer. +template +struct sequence_wrapper_: public initializer_base +{ + sequence_wrapper_(const Sequence& c): sequence_(c) {} + + Sequence sequence_; + + template + void on_CreateProcess_setup(WindowsExecutor& e) const + { + boost::range::for_each(sequence_, typename WindowsExecutor::call_on_CreateProcess_setup(e)); + } + + template + void on_CreateProcess_error(WindowsExecutor& e) const + { + boost::range::for_each(sequence_, typename WindowsExecutor::call_on_CreateProcess_error(e)); + } + + template + void on_CreateProcess_success(WindowsExecutor& e) const + { + boost::range::for_each(sequence_, typename WindowsExecutor::call_on_CreateProcess_success(e)); + } +}; + +// sequence() is a convenience function to construct a sequence_wrapper_ +// without having to state T. +template +sequence_wrapper_ +sequence(const Sequence& c) +{ + return sequence_wrapper_(c); +} + +}}}} + +#endif