From 3618cf71f320e2bfcc5766271ea121c4f238b708 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 23 Nov 2015 17:20:10 -0500 Subject: [PATCH 1/5] Add sequence() initializer to pass a runtime container of initializers. sequence() returns an initializer adapter that forwards initializer method calls to each contained initializer in turn. Also defines any_initializer as the element type for the container of interest. std::vector initializers; initializers.push_back(run_exe("myprog")); ... execute(sequence(initializers)); --- boost/process/posix/initializers.hpp | 1 + boost/process/posix/initializers/sequence.hpp | 101 ++++++++++++++++++ boost/process/windows/initializers.hpp | 1 + .../process/windows/initializers/sequence.hpp | 97 +++++++++++++++++ 4 files changed, 200 insertions(+) create mode 100644 boost/process/posix/initializers/sequence.hpp create mode 100644 boost/process/windows/initializers/sequence.hpp 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..c6f3d57 --- /dev/null +++ b/boost/process/posix/initializers/sequence.hpp @@ -0,0 +1,101 @@ +// 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. Unfortunately the +// convenience macro must be used in the global namespace. +BOOST_TYPE_ERASURE_MEMBER((has_on_fork_setup), on_fork_setup, 1) +BOOST_TYPE_ERASURE_MEMBER((has_on_fork_error), on_fork_error, 1) +BOOST_TYPE_ERASURE_MEMBER((has_on_fork_success), on_fork_success, 1) +BOOST_TYPE_ERASURE_MEMBER((has_on_exec_setup), on_exec_setup, 1) +BOOST_TYPE_ERASURE_MEMBER((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..0493c19 --- /dev/null +++ b/boost/process/windows/initializers/sequence.hpp @@ -0,0 +1,97 @@ +// 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. Unfortunately the +// convenience macro must be used in the global namespace. +BOOST_TYPE_ERASURE_MEMBER((has_on_CreateProcess_setup), on_CreateProcess_setup, 1) +BOOST_TYPE_ERASURE_MEMBER((has_on_CreateProcess_error), on_CreateProcess_error, 1) +BOOST_TYPE_ERASURE_MEMBER((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)); + } + + template + void on_exec_setup(WindowsExecutor& e) const + { + boost::range::for_each(sequence_, typename WindowsExecutor::call_on_exec_setup(e)); + } + + template + void on_exec_error(WindowsExecutor& e) const + { + boost::range::for_each(sequence_, typename WindowsExecutor::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 From cee81065b19560c932a7935d9b2d5f3e8f9d5f50 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 23 Nov 2015 17:32:20 -0500 Subject: [PATCH 2/5] Of course windows::executor has no on_exec_{setup,error}() methods. --- boost/process/windows/initializers/sequence.hpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/boost/process/windows/initializers/sequence.hpp b/boost/process/windows/initializers/sequence.hpp index 0493c19..6642272 100644 --- a/boost/process/windows/initializers/sequence.hpp +++ b/boost/process/windows/initializers/sequence.hpp @@ -69,18 +69,6 @@ struct sequence_wrapper_: public initializer_base { boost::range::for_each(sequence_, typename WindowsExecutor::call_on_CreateProcess_success(e)); } - - template - void on_exec_setup(WindowsExecutor& e) const - { - boost::range::for_each(sequence_, typename WindowsExecutor::call_on_exec_setup(e)); - } - - template - void on_exec_error(WindowsExecutor& e) const - { - boost::range::for_each(sequence_, typename WindowsExecutor::call_on_exec_error(e)); - } }; // sequence() is a convenience function to construct a sequence_wrapper_ From 2eff3440a814f67a93a434591c93caaa4b97710b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 24 Nov 2015 13:01:05 -0500 Subject: [PATCH 3/5] Place Boost.TypeErasure helpers in proper namespace. --- boost/process/posix/initializers/sequence.hpp | 19 ++++++++++++------- .../process/windows/initializers/sequence.hpp | 13 ++++++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/boost/process/posix/initializers/sequence.hpp b/boost/process/posix/initializers/sequence.hpp index c6f3d57..afe5236 100644 --- a/boost/process/posix/initializers/sequence.hpp +++ b/boost/process/posix/initializers/sequence.hpp @@ -17,13 +17,18 @@ #include #include -// Define initializer_base methods to Boost.TypeErasure. Unfortunately the -// convenience macro must be used in the global namespace. -BOOST_TYPE_ERASURE_MEMBER((has_on_fork_setup), on_fork_setup, 1) -BOOST_TYPE_ERASURE_MEMBER((has_on_fork_error), on_fork_error, 1) -BOOST_TYPE_ERASURE_MEMBER((has_on_fork_success), on_fork_success, 1) -BOOST_TYPE_ERASURE_MEMBER((has_on_exec_setup), on_exec_setup, 1) -BOOST_TYPE_ERASURE_MEMBER((has_on_exec_error), on_exec_error, 1) +// 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 { diff --git a/boost/process/windows/initializers/sequence.hpp b/boost/process/windows/initializers/sequence.hpp index 6642272..213418b 100644 --- a/boost/process/windows/initializers/sequence.hpp +++ b/boost/process/windows/initializers/sequence.hpp @@ -17,11 +17,14 @@ #include #include -// Define initializer_base methods to Boost.TypeErasure. Unfortunately the -// convenience macro must be used in the global namespace. -BOOST_TYPE_ERASURE_MEMBER((has_on_CreateProcess_setup), on_CreateProcess_setup, 1) -BOOST_TYPE_ERASURE_MEMBER((has_on_CreateProcess_error), on_CreateProcess_error, 1) -BOOST_TYPE_ERASURE_MEMBER((has_on_CreateProcess_success), on_CreateProcess_success, 1) +// 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 { From 5e5715af24318c5ee837974d96511fe536d8d192 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 25 Nov 2015 18:34:19 -0500 Subject: [PATCH 4/5] Use shorter include guard for MSVC 2013. --- boost/process/windows/initializers/sequence.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/boost/process/windows/initializers/sequence.hpp b/boost/process/windows/initializers/sequence.hpp index 213418b..cf8d6c8 100644 --- a/boost/process/windows/initializers/sequence.hpp +++ b/boost/process/windows/initializers/sequence.hpp @@ -7,8 +7,12 @@ // 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 +// Apparently BOOST_PROCESS_WINDOWS_INITIALIZERS_SEQUENCE_HPP is too long for +// VS 2013?! If we use that symbol, it claims it's ALWAYS defined (collision +// with previous BOOST_PROCESS_WINDOWS_INITIALIZERS_something?) and skips the +// body of this file! Use an abbreviated symbol instead. +#ifndef BOOST_PROCESS_WIN_INIT_SEQ_HPP +#define BOOST_PROCESS_WIN_INIT_SEQ_HPP #include #include From d1914353c3f956e4bd23488609c07afe51a46d99 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 25 Nov 2015 19:23:38 -0500 Subject: [PATCH 5/5] Fix include guard back to convention. The problem was elsewhere. --- boost/process/windows/initializers/sequence.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/boost/process/windows/initializers/sequence.hpp b/boost/process/windows/initializers/sequence.hpp index cf8d6c8..213418b 100644 --- a/boost/process/windows/initializers/sequence.hpp +++ b/boost/process/windows/initializers/sequence.hpp @@ -7,12 +7,8 @@ // 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) -// Apparently BOOST_PROCESS_WINDOWS_INITIALIZERS_SEQUENCE_HPP is too long for -// VS 2013?! If we use that symbol, it claims it's ALWAYS defined (collision -// with previous BOOST_PROCESS_WINDOWS_INITIALIZERS_something?) and skips the -// body of this file! Use an abbreviated symbol instead. -#ifndef BOOST_PROCESS_WIN_INIT_SEQ_HPP -#define BOOST_PROCESS_WIN_INIT_SEQ_HPP +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SEQUENCE_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SEQUENCE_HPP #include #include