Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r65293 - in sandbox/SOC/2010/process: boost/process libs/process/example libs/process/test libs/process/test/util
From: boris_at_[hidden]
Date: 2010-09-05 10:00:29


Author: bschaeling
Date: 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
New Revision: 65293
URL: http://svn.boost.org/trac/boost/changeset/65293

Log:
Updated context class to use delegates based on boost::function (consequently updated all stream behaviors)
Changed named_pipe which requires now a name to be set by a developer
Added new stream behavior async_pipe
Text files modified:
   sandbox/SOC/2010/process/boost/process/config.hpp | 6
   sandbox/SOC/2010/process/boost/process/context.hpp | 27 +-
   sandbox/SOC/2010/process/boost/process/operations.hpp | 55 ++++---
   sandbox/SOC/2010/process/boost/process/stream_behavior.hpp | 281 ++++++++++++++-------------------------
   sandbox/SOC/2010/process/libs/process/example/async_io.cpp | 5
   sandbox/SOC/2010/process/libs/process/example/create_child_context.cpp | 6
   sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp | 21 +-
   sandbox/SOC/2010/process/libs/process/example/redirect_to.cpp | 59 +++----
   sandbox/SOC/2010/process/libs/process/test/Jamfile.jam | 4
   sandbox/SOC/2010/process/libs/process/test/arguments.cpp | 2
   sandbox/SOC/2010/process/libs/process/test/child.cpp | 125 ++++++++--------
   sandbox/SOC/2010/process/libs/process/test/handle.cpp | 7
   sandbox/SOC/2010/process/libs/process/test/util/boost.hpp | 4
   13 files changed, 265 insertions(+), 337 deletions(-)

Modified: sandbox/SOC/2010/process/boost/process/config.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/config.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/config.hpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -63,6 +63,12 @@
         boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
             boost::system::get_system_category()), \
         BOOST_PROCESS_SOURCE_LOCATION what))
+
+#define BOOST_PROCESS_THROW_ERROR(error, what) \
+ boost::throw_exception(boost::system::system_error( \
+ boost::system::error_code(error, \
+ boost::system::get_system_category()), \
+ BOOST_PROCESS_SOURCE_LOCATION what))
 /** \endcond */
 
 #endif

Modified: sandbox/SOC/2010/process/boost/process/context.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/context.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/context.hpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -28,11 +28,13 @@
 # include <windows.h>
 #endif
 
-#include <boost/process/stream_behavior.hpp>
+#include <boost/process/handle.hpp>
 #include <boost/process/environment.hpp>
 #include <boost/process/self.hpp>
-#include <boost/shared_ptr.hpp>
+#include <boost/process/stream_behavior.hpp>
+#include <boost/function.hpp>
 #include <string>
+#include <utility>
 
 namespace boost {
 namespace process {
@@ -49,17 +51,17 @@
     /**
      * Behavior of the standard input stream.
      */
- boost::shared_ptr<behavior::stream> stdin_behavior;
+ boost::function<std::pair<handle, handle> (bool)> stdin_behavior;
 
     /**
      * Behavior of the standard output stream.
      */
- boost::shared_ptr<behavior::stream> stdout_behavior;
+ boost::function<std::pair<handle, handle> (bool)> stdout_behavior;
 
     /**
      * Behavior of the standard error stream.
      */
- boost::shared_ptr<behavior::stream> stderr_behavior;
+ boost::function<std::pair<handle, handle> (bool)> stderr_behavior;
 
     /**
      * Process name.
@@ -88,16 +90,13 @@
      */
     context()
 #if defined(BOOST_POSIX_API)
- : stdin_behavior(behavior::inherit::create(STDIN_FILENO)),
- stdout_behavior(behavior::inherit::create(STDOUT_FILENO)),
- stderr_behavior(behavior::inherit::create(STDERR_FILENO)),
+ : stdin_behavior(behavior::inherit(STDIN_FILENO)),
+ stdout_behavior(behavior::inherit(STDOUT_FILENO)),
+ stderr_behavior(behavior::inherit(STDERR_FILENO)),
 #elif defined(BOOST_WINDOWS_API)
- : stdin_behavior(behavior::inherit::create(GetStdHandle(
- STD_INPUT_HANDLE))),
- stdout_behavior(behavior::inherit::create(GetStdHandle(
- STD_OUTPUT_HANDLE))),
- stderr_behavior(behavior::inherit::create(GetStdHandle(
- STD_ERROR_HANDLE))),
+ : stdin_behavior(behavior::inherit(GetStdHandle(STD_INPUT_HANDLE))),
+ stdout_behavior(behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE))),
+ stderr_behavior(behavior::inherit(GetStdHandle(STD_ERROR_HANDLE))),
 #endif
         work_dir(self::get_work_dir()),
         env(self::get_environment())

Modified: sandbox/SOC/2010/process/boost/process/operations.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/operations.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/operations.hpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -52,6 +52,7 @@
 #include <boost/assert.hpp>
 #include <string>
 #include <vector>
+#include <utility>
 
 namespace boost {
 namespace process {
@@ -163,7 +164,7 @@
 #if defined(BOOST_WINDOWS_API)
     if (exe.size() > 4 && (boost::algorithm::iends_with(exe, ".exe") ||
         boost::algorithm::iends_with(exe, ".com") ||
- boost::algorithm::iends_with(exe, ".bat")))
+ boost::algorithm::iends_with(exe, ".bat")))
         end = exe.size() - 4;
 #endif
 
@@ -186,11 +187,17 @@
 inline child create_child(const std::string &executable, Arguments args,
     Context ctx)
 {
-#if !defined(NDEBUG)
- BOOST_ASSERT(ctx.stdin_behavior.get());
- BOOST_ASSERT(ctx.stdout_behavior.get());
- BOOST_ASSERT(ctx.stderr_behavior.get());
-#endif
+ std::pair<handle, handle> stdin_pair;
+ if (ctx.stdin_behavior)
+ stdin_pair = ctx.stdin_behavior(true);
+
+ std::pair<handle, handle> stdout_pair;
+ if (ctx.stdout_behavior)
+ stdout_pair = ctx.stdout_behavior(false);
+
+ std::pair<handle, handle> stderr_pair;
+ if (ctx.stderr_behavior)
+ stderr_pair = ctx.stderr_behavior(false);
 
     std::string p_name = ctx.process_name.empty() ?
         executable_to_progname(executable) : ctx.process_name;
@@ -227,9 +234,9 @@
             _exit(127);
         }
 
- handle hstdin = ctx.stdin_behavior->get_child_end();
- handle hstdout = ctx.stdout_behavior->get_child_end();
- handle hstderr = ctx.stderr_behavior->get_child_end();
+ handle hstdin = stdin_pair.first;
+ handle hstdout = stdout_pair.first;
+ handle hstderr = stderr_pair.first;
 
         if (hstdin.valid())
         {
@@ -321,23 +328,23 @@
             delete[] envp.second[i];
         delete[] envp.second;
 
- ctx.stdin_behavior->get_child_end().close();
- ctx.stdout_behavior->get_child_end().close();
- ctx.stderr_behavior->get_child_end().close();
+ stdin_pair.first.close();
+ stdout_pair.first.close();
+ stderr_pair.first.close();
 
         return child(pid,
- ctx.stdin_behavior->get_parent_end(),
- ctx.stdout_behavior->get_parent_end(),
- ctx.stderr_behavior->get_parent_end());
+ stdin_pair.second,
+ stdout_pair.second,
+ stderr_pair.second);
     }
 #elif defined(BOOST_WINDOWS_API)
     STARTUPINFOA startup_info;
     ZeroMemory(&startup_info, sizeof(startup_info));
     startup_info.cb = sizeof(startup_info);
     startup_info.dwFlags |= STARTF_USESTDHANDLES;
- startup_info.hStdInput = ctx.stdin_behavior->get_child_end().native();
- startup_info.hStdOutput = ctx.stdout_behavior->get_child_end().native();
- startup_info.hStdError = ctx.stderr_behavior->get_child_end().native();
+ startup_info.hStdInput = stdin_pair.first.native();
+ startup_info.hStdOutput = stdout_pair.first.native();
+ startup_info.hStdError = stderr_pair.first.native();
 
     ctx.setup(startup_info);
 
@@ -360,9 +367,9 @@
         envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
         BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed");
 
- ctx.stdin_behavior->get_child_end().close();
- ctx.stdout_behavior->get_child_end().close();
- ctx.stderr_behavior->get_child_end().close();
+ stdin_pair.first.close();
+ stdout_pair.first.close();
+ stderr_pair.first.close();
 
     handle hprocess(pi.hProcess);
 
@@ -370,9 +377,9 @@
         BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
 
     return child(hprocess,
- ctx.stdin_behavior->get_parent_end(),
- ctx.stdout_behavior->get_parent_end(),
- ctx.stderr_behavior->get_parent_end());
+ stdin_pair.second,
+ stdout_pair.second,
+ stderr_pair.second);
 #endif
 }
 

Modified: sandbox/SOC/2010/process/boost/process/stream_behavior.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/stream_behavior.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/stream_behavior.hpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -28,109 +28,63 @@
 # include <unistd.h>
 #elif defined(BOOST_WINDOWS_API)
 # include <windows.h>
+# include <rpc.h>
 #endif
 
 #include <boost/process/handle.hpp>
-#include <boost/uuid/uuid.hpp>
-#include <boost/uuid/random_generator.hpp>
-#include <boost/uuid/uuid_io.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/make_shared.hpp>
 #include <string>
 #include <algorithm>
+#include <utility>
 
 namespace boost {
 namespace process {
 namespace behavior {
 
 /**
- * Base class for stream behaviors.
+ * Stream behavior to close streams of a child process.
  *
- * Stream behavior classes are used to configure streams of a child process.
- * They must be derived from this class.
+ * A child process will not be able to use the stream.
  */
-class stream
+class close
 {
 public:
- /**
- * Empty virtual destructor.
- */
- virtual ~stream()
- {
- }
-
- /**
- * Factory function to create a stream behavior object.
- *
- * Returns a shared pointer to the stream behavior object as this is
- * what a context object expects. The shared pointer guarantees that
- * the object is cleaned up.
- */
- static boost::shared_ptr<stream> create()
- {
- return boost::make_shared<stream>();
- }
-
- /**
- * Returns the child's end of the stream.
- */
- virtual handle get_child_end()
- {
- return handle();
- }
-
- /**
- * Returns the parent's end of the stream.
- */
- virtual handle get_parent_end()
+ std::pair<handle, handle> operator()(bool) const
     {
- return handle();
+ return std::make_pair(handle(), handle());
     }
 };
 
 /**
- * Stream behavior to close streams of a child process.
- *
- * A child process will not be able to use the stream.
- */
-typedef stream close;
-
-/**
  * Stream behavior to make a child process inherit streams.
  *
  * A child process will use the very same stream of its parent process.
  */
-class inherit : public stream
+class inherit
 {
 public:
- inherit(handle::native_type child_end)
+ inherit(handle::native_type h)
+ : h_(h)
+ {
+ }
+
+ std::pair<handle, handle> operator()(bool) const
     {
 #if defined(BOOST_POSIX_API)
- child_end_ = dup(child_end);
- if (!child_end_.valid())
+ int h = dup(h_);
+ if (h == -1)
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("dup(2) failed");
 #elif defined(BOOST_WINDOWS_API)
         HANDLE h;
- if (!DuplicateHandle(GetCurrentProcess(), child_end,
- GetCurrentProcess(), &h, 0, TRUE, DUPLICATE_SAME_ACCESS))
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("DuplicateHandle() failed");
- child_end_ = h;
+ if (!DuplicateHandle(GetCurrentProcess(), h_, GetCurrentProcess(),
+ &h, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
+ "SetHandleInformation() failed");
 #endif
- }
-
- static boost::shared_ptr<inherit> create(handle::native_type child_end)
- {
- return boost::make_shared<inherit>(child_end);
- }
-
- handle get_child_end()
- {
- return child_end_;
+ return std::make_pair(h, handle());
     }
 
 private:
- handle child_end_;
+ handle::native_type h_;
 };
 
 /**
@@ -138,12 +92,10 @@
  *
  * A child process will be able to communicate with its parent process.
  */
-class pipe : public stream
+class pipe
 {
 public:
- enum stream_type { input_stream, output_stream };
-
- pipe(stream_type stream)
+ std::pair<handle, handle> operator()(bool in) const
     {
         handle::native_type ends[2];
 #if defined(BOOST_POSIX_API)
@@ -158,34 +110,16 @@
         if (!CreatePipe(&ends[0], &ends[1], &sa, 0))
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
 #endif
- child_end_ = ends[(stream == input_stream) ? 0 : 1];
- parent_end_ = ends[(stream == input_stream) ? 1 : 0];
+ handle child_end = ends[in ? 0 : 1];
+ handle parent_end = ends[in ? 1 : 0];
 #if defined(BOOST_WINDOWS_API)
- if (!SetHandleInformation(child_end_.native(), HANDLE_FLAG_INHERIT,
+ if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
             HANDLE_FLAG_INHERIT))
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
                 "SetHandleInformation() failed");
 #endif
+ return std::make_pair(child_end, parent_end);
     }
-
- static boost::shared_ptr<behavior::pipe> create(stream_type stream)
- {
- return boost::make_shared<pipe>(stream);
- }
-
- handle get_child_end()
- {
- return child_end_;
- }
-
- handle get_parent_end()
- {
- return parent_end_;
- }
-
-private:
- handle child_end_;
- handle parent_end_;
 };
 
 /**
@@ -195,98 +129,101 @@
  * On Windows this stream behavior must be used for asynchronous I/O (as only
  * named pipes support asynchronous I/O on Windows).
  */
-class named_pipe : public stream
+class named_pipe
 {
 public:
- enum stream_type { input_stream, output_stream };
+ named_pipe(const std::string &name)
+ : name_(name)
+ {
+ }
 
- named_pipe(stream_type stream, std::string *name = 0)
+ std::pair<handle, handle> operator()(bool in) const
     {
 #if defined(BOOST_POSIX_API)
- std::string s;
- if (name && !name->empty())
- s = *name;
- else
- {
- boost::uuids::random_generator gen;
- boost::uuids::uuid u = gen();
- s = "/tmp/boost_process_" + boost::lexical_cast<std::string>(u);
- if (name)
- *name = s;
- }
-
- if (mkfifo(s.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
+ if (mkfifo(name_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed");
- child_end_ = open(s.c_str(), O_RDONLY | O_NONBLOCK);
- if (!child_end_.valid())
+ handle child_end = open(name_.c_str(), O_RDONLY | O_NONBLOCK);
+ if (!child_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
- int opts = fcntl(child_end_.native(), F_GETFL);
+ int opts = fcntl(child_end.native(), F_GETFL);
         if (opts == -1)
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
         opts ^= O_NONBLOCK;
- if (fcntl(child_end_.native(), F_SETFL, opts) == -1)
+ if (fcntl(child_end.native(), F_SETFL, opts) == -1)
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
- parent_end_ = open(s.c_str(), O_WRONLY);
- if (!parent_end_.valid())
+ handle parent_end = open(name_.c_str(), O_WRONLY);
+ if (!parent_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
 #elif defined(BOOST_WINDOWS_API)
- std::string s;
- if (name && !name->empty())
- s = *name;
- else
- {
- boost::uuids::random_generator gen;
- boost::uuids::uuid u = gen();
- s = "\\\\.\\pipe\\boost_process_" +
- boost::lexical_cast<std::string>(u);
- if (name)
- *name = s;
- }
-
         SECURITY_ATTRIBUTES sa;
         ZeroMemory(&sa, sizeof(sa));
         sa.nLength = sizeof(sa);
         sa.lpSecurityDescriptor = NULL;
         sa.bInheritHandle = TRUE;
- child_end_ = CreateNamedPipeA(s.c_str(), PIPE_ACCESS_INBOUND |
+ handle child_end = CreateNamedPipeA(name_.c_str(), PIPE_ACCESS_INBOUND |
             FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
- if (!child_end_.valid())
+ if (!child_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed");
- parent_end_ = CreateFileA(s.c_str(), GENERIC_WRITE, 0, NULL,
+ handle parent_end = CreateFileA(name_.c_str(), GENERIC_WRITE, 0, NULL,
             OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (!parent_end_.valid())
+ if (!parent_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
 #endif
- if (stream == output_stream)
- std::swap(child_end_, parent_end_);
+ if (!in)
+ std::swap(child_end, parent_end);
 #if defined(BOOST_WINDOWS_API)
- if (!SetHandleInformation(child_end_.native(), HANDLE_FLAG_INHERIT,
+ if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
             HANDLE_FLAG_INHERIT))
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
                 "SetHandleInformation() failed");
 #endif
+ return std::make_pair(child_end, parent_end);
     }
 
- static boost::shared_ptr<named_pipe> create(stream_type stream,
- std::string *name = 0)
- {
- return boost::make_shared<named_pipe>(stream, name);
- }
-
- handle get_child_end()
- {
- return child_end_;
- }
+private:
+ std::string name_;
+};
 
- handle get_parent_end()
+/**
+ * Stream behavior to redirect streams with a pipe which supports asynchronous
+ * I/O.
+ *
+ * As platforms require different types of pipes for asynchronous I/O this
+ * stream behavior is provided for convenience. It uses the minimum required
+ * pipe type on a platform in order to be able to use asynchronous I/O.
+ */
+#if defined(BOOST_POSIX_API)
+typedef pipe async_pipe;
+#elif defined(BOOST_WINDOWS_API)
+class async_pipe
+{
+public:
+ std::pair<handle, handle> operator()(bool in) const
     {
- return parent_end_;
+ UUID uuid;
+ RPC_STATUS s = UuidCreateSequential(&uuid);
+ if (s != RPC_S_OK && s != RPC_S_UUID_LOCAL_ONLY)
+ BOOST_PROCESS_THROW_ERROR(s, "UuidCreateSequential() failed");
+ unsigned char *c;
+ s = UuidToStringA(&uuid, &c);
+ if (s != RPC_S_OK)
+ BOOST_PROCESS_THROW_ERROR(s, "UuidToString() failed");
+ std::string name;
+ try
+ {
+ name = reinterpret_cast<char*>(c);
+ }
+ catch (...)
+ {
+ RpcStringFreeA(&c);
+ throw;
+ }
+ RpcStringFreeA(&c);
+ named_pipe p("\\\\.\\pipe\\boost_process_" + name);
+ return p(in);
     }
-
-private:
- handle child_end_;
- handle parent_end_;
 };
+#endif
 
 /**
  * Stream behavior to mute streams.
@@ -294,45 +231,29 @@
  * A child process will be able to use streams. But data written to an
  * output stream is discarded and data read from an input stream is 0.
  */
-class null : public stream
+class null
 {
 public:
- enum stream_type { input_stream, output_stream };
-
- null(stream_type stream)
+ std::pair<handle, handle> operator()(bool in) const
     {
 #if defined(BOOST_POSIX_API)
- std::string filename = (stream == input_stream) ? "/dev/zero" :
- "/dev/null";
- int flag = (stream == input_stream) ? O_RDONLY : O_WRONLY;
- child_end_ = open(filename.c_str(), flag);
- if (!child_end_.valid())
+ std::string filename = in ? "/dev/zero" : "/dev/null";
+ int flag = in ? O_RDONLY : O_WRONLY;
+ handle child_end = open(filename.c_str(), flag);
+ if (!child_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
 #elif defined(BOOST_WINDOWS_API)
- DWORD access = (stream == input_stream) ? GENERIC_READ : GENERIC_WRITE;
- child_end_ = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING,
+ DWORD access = in ? GENERIC_READ : GENERIC_WRITE;
+ handle child_end = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING,
             FILE_ATTRIBUTE_NORMAL, NULL);
- if (!child_end_.valid())
+ if (!child_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
- if (!SetHandleInformation(child_end_.native(), HANDLE_FLAG_INHERIT,
+ if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
             HANDLE_FLAG_INHERIT))
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
- "SetHandleInformation() failed");
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetHandleInformation() failed");
 #endif
+ return std::make_pair(child_end, handle());
     }
-
- static boost::shared_ptr<null> create(stream_type stream)
- {
- return boost::make_shared<null>(stream);
- }
-
- handle get_child_end()
- {
- return child_end_;
- }
-
-private:
- handle child_end_;
 };
 
 }

Modified: sandbox/SOC/2010/process/libs/process/example/async_io.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/async_io.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/async_io.cpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -11,8 +11,8 @@
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
-#include <boost/process/all.hpp>
 #include <boost/asio.hpp>
+#include <boost/process/all.hpp>
 #include <boost/array.hpp>
 #include <string>
 #include <vector>
@@ -30,8 +30,7 @@
     std::string exe = boost::process::find_executable_in_path("hostname");
     std::vector<std::string> args;
     boost::process::context ctx;
- ctx.stdout_behavior = boost::process::behavior::named_pipe::create(
- boost::process::behavior::named_pipe::output_stream);
+ ctx.stdout_behavior = boost::process::behavior::async_pipe();
     boost::process::child c = boost::process::create_child(exe, args, ctx);
     boost::process::pistream &is = c.get_stdout();
     boost::process::handle h = is.handle();

Modified: sandbox/SOC/2010/process/libs/process/example/create_child_context.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/create_child_context.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/create_child_context.cpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -36,8 +36,7 @@
     std::string exe = boost::process::find_executable_in_path("hostname");
     std::vector<std::string> args;
     boost::process::context ctx;
- ctx.stdout_behavior = boost::process::behavior::null::create(
- boost::process::behavior::null::output_stream);
+ ctx.stdout_behavior = boost::process::behavior::null();
     boost::process::create_child(exe, args, ctx);
 //]
 }
@@ -48,8 +47,7 @@
     std::string exe = boost::process::find_executable_in_path("hostname");
     std::vector<std::string> args;
     boost::process::context ctx;
- ctx.stdout_behavior = boost::process::behavior::pipe::create(
- boost::process::behavior::pipe::output_stream);
+ ctx.stdout_behavior = boost::process::behavior::pipe();
     boost::process::child c = boost::process::create_child(exe, args, ctx);
     boost::process::pistream &is = c.get_stdout();
     std::cout << is.rdbuf() << std::flush;

Modified: sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -18,28 +18,29 @@
 #include <boost/assign/list_of.hpp>
 #include <string>
 #include <vector>
+#include <utility>
 #include <iostream>
 #include <unistd.h>
 
 //[file_descriptors_context
-boost::process::behavior::pipe address(
- boost::process::behavior::pipe::output_stream);
-boost::process::behavior::pipe pid(
- boost::process::behavior::pipe::output_stream);
+std::pair<boost::process::handle, boost::process::handle> address =
+ boost::process::behavior::pipe()(false);
+std::pair<boost::process::handle, boost::process::handle> pid =
+ boost::process::behavior::pipe()(false);
 
 class context : public boost::process::context
 {
 public:
     void setup(std::vector<bool> &closeflags)
     {
- if (dup2(address.get_child_end().native(), 3) == -1)
+ if (dup2(address.first.native(), 3) == -1)
         {
             write(STDERR_FILENO, "dup2() failed\n", 14);
             _exit(127);
         }
         closeflags[3] = false;
 
- if (dup2(pid.get_child_end().native(), 4) == -1)
+ if (dup2(pid.first.native(), 4) == -1)
         {
             write(STDERR_FILENO, "dup2() failed\n", 14);
             _exit(127);
@@ -57,11 +58,11 @@
         ("--session")("--print-address=3")("--print-pid=4");
     context ctx;
     boost::process::create_child(exe, args, ctx);
- address.get_child_end().close();
- pid.get_child_end().close();
- boost::process::pistream isaddress(address.get_parent_end());
+ address.first.close();
+ pid.first.close();
+ boost::process::pistream isaddress(address.second);
     std::cout << isaddress.rdbuf() << std::endl;
- boost::process::pistream ispid(pid.get_parent_end());
+ boost::process::pistream ispid(pid.second);
     std::cout << ispid.rdbuf() << std::endl;
 //]
 }

Modified: sandbox/SOC/2010/process/libs/process/example/redirect_to.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/redirect_to.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/redirect_to.cpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -21,47 +21,37 @@
 # error "Unsupported platform."
 #endif
 
-#include <boost/shared_ptr.hpp>
-#include <boost/make_shared.hpp>
+#include <boost/bind.hpp>
 #include <iostream>
+#include <utility>
 #include <stdexcept>
 
 //[redirect_to_stream
-class redirect_to : public boost::process::behavior::stream
+std::pair<boost::process::handle, boost::process::handle> redirect_to(
+ boost::process::handle h)
 {
-public:
- redirect_to(boost::process::handle child_end)
- {
 #if defined(BOOST_POSIX_API)
- child_end_ = dup(child_end.native());
- if (!child_end_.valid())
- throw std::runtime_error("dup(2) failed");
+ h = dup(h.native());
+ if (!h.valid())
+ throw std::runtime_error("dup(2) failed");
 #elif defined(BOOST_WINDOWS_API)
- HANDLE h;
- if (!DuplicateHandle(GetCurrentProcess(), child_end.native(),
- GetCurrentProcess(), &h, 0, TRUE, DUPLICATE_SAME_ACCESS))
- throw std::runtime_error("DuplicateHandle() failed");
- child_end_ = h;
+ HANDLE h2;
+ if (!DuplicateHandle(GetCurrentProcess(), h.native(),
+ GetCurrentProcess(), &h2, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ throw std::runtime_error("DuplicateHandle() failed");
+ h = h2;
 #endif
- }
-
- static boost::shared_ptr<redirect_to> create(
- boost::process::handle stream_end)
- {
- return boost::make_shared<redirect_to>(redirect_to(stream_end));
- }
-
- boost::process::handle get_child_end()
- {
- return child_end_;
- }
-
-private:
- boost::process::handle child_end_;
-};
+ return std::make_pair(h, boost::process::handle());
+}
 //]
 
 //[redirect_to_main
+std::pair<boost::process::handle, boost::process::handle> forward(
+ std::pair<boost::process::handle, boost::process::handle> p)
+{
+ return p;
+}
+
 int main()
 {
     std::string executable = boost::process::find_executable_in_path(
@@ -69,11 +59,12 @@
 
     std::vector<std::string> args;
 
+ std::pair<boost::process::handle, boost::process::handle> p =
+ boost::process::behavior::pipe()(false);
+
     boost::process::context ctx;
- ctx.stdout_behavior = boost::process::behavior::pipe::create(
- boost::process::behavior::pipe::output_stream);
- ctx.stderr_behavior = redirect_to::create(
- ctx.stdout_behavior->get_child_end());
+ ctx.stdout_behavior = boost::bind(forward, p);
+ ctx.stderr_behavior = boost::bind(redirect_to, p.first);
 
     boost::process::child c = boost::process::create_child(
         executable, args, ctx);

Modified: sandbox/SOC/2010/process/libs/process/test/Jamfile.jam
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/Jamfile.jam (original)
+++ sandbox/SOC/2010/process/libs/process/test/Jamfile.jam 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -24,6 +24,8 @@
 exe helpers : util/helpers.cpp bfs ;
 explicit helpers ;
 
+lib rpcrt4 : : <name>rpcrt4 ;
+
 using testing ;
 
 for local i in [ glob inclusion/*.cpp ]
@@ -37,7 +39,7 @@
 run systembuf.cpp bfs ;
 
 run arguments.cpp bfs : : helpers : <dependency>helpers ;
-run child.cpp bfs : : helpers : <dependency>helpers ;
+run child.cpp bfs : : helpers : <dependency>helpers <target-os>windows:<library>rpcrt4 ;
 run executable.cpp bfs : : helpers : <dependency>helpers ;
 run process.cpp bfs : : helpers : <dependency>helpers ;
 run status.cpp bfs : : helpers : <dependency>helpers ;

Modified: sandbox/SOC/2010/process/libs/process/test/arguments.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/arguments.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/test/arguments.cpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -37,7 +37,7 @@
     args.push_back(word);
 
     bp::context ctx;
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
     bp::pistream &is = c.get_stdout();

Modified: sandbox/SOC/2010/process/libs/process/test/child.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/child.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/test/child.cpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -40,7 +40,7 @@
     args.push_back("is-closed-stdin");
 
     bp::context ctx;
- ctx.stdin_behavior = bpb::close::create();
+ ctx.stdin_behavior = bpb::close();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -61,7 +61,7 @@
     args.push_back("is-closed-stdout");
 
     bp::context ctx1;
- ctx1.stdout_behavior = bpb::close::create();
+ ctx1.stdout_behavior = bpb::close();
 
     bp::child c1 = bp::create_child(get_helpers_path(), args, ctx1);
 
@@ -74,7 +74,7 @@
 #endif
 
     bp::context ctx2;
- ctx2.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx2.stdout_behavior = bpb::pipe();
 
     bp::child c2 = bp::create_child(get_helpers_path(), args, ctx2);
 
@@ -95,7 +95,7 @@
     args.push_back("is-closed-stderr");
 
     bp::context ctx1;
- ctx1.stderr_behavior = bpb::close::create();
+ ctx1.stderr_behavior = bpb::close();
 
     bp::child c1 = bp::create_child(get_helpers_path(), args, ctx1);
 
@@ -108,7 +108,7 @@
 #endif
 
     bp::context ctx2;
- ctx2.stderr_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx2.stderr_behavior = bpb::pipe();
 
     bp::child c2 = bp::create_child(get_helpers_path(), args, ctx2);
 
@@ -129,8 +129,8 @@
     args.push_back("stdin-to-stdout");
 
     bp::context ctx;
- ctx.stdin_behavior = bpb::pipe::create(bpb::pipe::input_stream);
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdin_behavior = bpb::pipe();
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -160,7 +160,7 @@
     args.push_back("message-stdout");
 
     bp::context ctx;
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -185,7 +185,7 @@
     args.push_back("message-stderr");
 
     bp::context ctx;
- ctx.stderr_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stderr_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -210,8 +210,8 @@
     args.push_back("message-to-two-streams");
 
     bp::context ctx;
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
- ctx.stderr_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
+ ctx.stderr_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -236,37 +236,26 @@
 #endif
 }
 
-class redirect_to : public bpb::stream
+std::pair<bp::handle, bp::handle> redirect_to(bp::handle h)
 {
-public:
- redirect_to(bp::handle child_end)
- {
 #if defined(BOOST_POSIX_API)
- child_end_ = dup(child_end.native());
- if (!child_end_.valid())
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("dup(2) failed");
-#elif defined(BOOST_WINDOWS_API)
- HANDLE h;
- if (!DuplicateHandle(GetCurrentProcess(), child_end.native(),
- GetCurrentProcess(), &h, 0, TRUE, DUPLICATE_SAME_ACCESS))
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("DuplicateHandle() failed");
- child_end_ = h;
+ h = dup(h.native());
+ if (!h.valid())
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("dup(2) failed");
+#elif defined(BOOST_WINDOWS_API)
+ HANDLE h2;
+ if (!DuplicateHandle(GetCurrentProcess(), h.native(),
+ GetCurrentProcess(), &h2, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("DuplicateHandle() failed");
+ h = h2;
 #endif
- }
-
- static boost::shared_ptr<redirect_to> create(bp::handle stream_end)
- {
- return boost::make_shared<redirect_to>(redirect_to(stream_end));
- }
-
- bp::handle get_child_end()
- {
- return child_end_;
- }
+ return std::make_pair(h, bp::handle());
+}
 
-private:
- bp::handle child_end_;
-};
+std::pair<bp::handle, bp::handle> forward(std::pair<bp::handle, bp::handle> p)
+{
+ return p;
+}
 
 BOOST_AUTO_TEST_CASE(test_redirect_err_to_out)
 {
@@ -274,10 +263,11 @@
     args.push_back("echo-stdout-stderr");
     args.push_back("message-to-two-streams");
 
+ std::pair<bp::handle, bp::handle> p = bpb::pipe()(false);
+
     bp::context ctx;
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
- ctx.stderr_behavior = redirect_to::create(
- ctx.stdout_behavior->get_child_end());
+ ctx.stdout_behavior = boost::bind(forward, p);
+ ctx.stderr_behavior = boost::bind(redirect_to, p.first);
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -309,7 +299,7 @@
     bp::context ctx;
     BOOST_CHECK(bfs::equivalent(ctx.work_dir, bfs::current_path().string()));
 
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -343,7 +333,7 @@
     {
         bp::context ctx;
         ctx.work_dir = wdir.string();
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
 
         bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -378,7 +368,7 @@
     args.push_back("query-env");
     args.push_back(var);
 
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -498,10 +488,8 @@
     args.push_back("async-");
 
     bp::context ctx;
- ctx.stdin_behavior = bp::behavior::named_pipe::create(
- bp::behavior::named_pipe::input_stream);
- ctx.stdout_behavior = bp::behavior::named_pipe::create(
- bp::behavior::named_pipe::output_stream);
+ ctx.stdin_behavior = bpb::async_pipe();
+ ctx.stdout_behavior = bpb::async_pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
     bp::postream &os = c.get_stdin();
@@ -536,7 +524,7 @@
 #endif
 
     bp::context ctx;
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::shell(cmd, ctx);
 
@@ -562,7 +550,7 @@
     args.push_back("is-nul-stdin");
 
     bp::context ctx;
- ctx.stdin_behavior = bpb::null::create(bpb::null::input_stream);
+ ctx.stdin_behavior = bpb::null();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -583,7 +571,7 @@
     args.push_back("is-nul-stdout");
 
     bp::context ctx;
- ctx.stdout_behavior = bpb::null::create(bpb::null::output_stream);
+ ctx.stdout_behavior = bpb::null();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -604,7 +592,7 @@
     args.push_back("is-nul-stderr");
 
     bp::context ctx;
- ctx.stderr_behavior = bpb::null::create(bpb::null::output_stream);
+ ctx.stderr_behavior = bpb::null();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -622,13 +610,13 @@
 {
 public:
     context()
- : p(bpb::pipe::output_stream)
+ : p(bpb::pipe()(false))
     {
     }
 
     void setup(std::vector<bool> &closeflags)
     {
- if (dup2(p.get_child_end().native(), 10) == -1)
+ if (dup2(p.first.native(), 10) == -1)
         {
             write(STDERR_FILENO, "dup2() failed\n", 14);
             _exit(127);
@@ -636,7 +624,7 @@
         closeflags[10] = false;
     }
 
- bpb::pipe p;
+ std::pair<bp::handle, bp::handle> p;
 };
 
 BOOST_AUTO_TEST_CASE(test_posix)
@@ -652,7 +640,7 @@
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
     std::string word;
- bp::pistream is(ctx.p.get_parent_end());
+ bp::pistream is(ctx.p.second);
     is >> word;
     BOOST_CHECK_EQUAL(word, "test");
 
@@ -710,8 +698,9 @@
     raii_dup2 raii_stderr(STDERR_FILENO, 102);
     close(STDERR_FILENO);
 
- ctx.stderr_behavior = bpb::pipe::create(bpb::pipe::output_stream);
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdin_behavior = bpb::null();
+ ctx.stderr_behavior = bpb::pipe();
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -760,7 +749,7 @@
     args.push_back("windows-print-startupinfo");
 
     context ctx;
- ctx.stdout_behavior = bpb::pipe::create(bpb::pipe::output_stream);
+ ctx.stdout_behavior = bpb::pipe();
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 
@@ -786,6 +775,18 @@
     BOOST_CHECK_EQUAL(s, EXIT_SUCCESS);
 }
 
+std::string create_unique_pipe_name()
+{
+ bu::random_generator gen;
+ bu::uuid u = gen();
+#if defined(BOOST_POSIX_API)
+ std::string name = "/tmp/boost_process_test_";
+#elif defined(BOOST_WINDOWS_API)
+ std::string name = "\\\\.\\pipe\\boost_process_test_";
+#endif
+ return name + boost::lexical_cast<std::string>(u);
+}
+
 BOOST_AUTO_TEST_CASE(test_sync_io_with_named_pipe)
 {
     check_helpers();
@@ -794,10 +795,8 @@
     args.push_back("stdin-to-stdout");
 
     bp::context ctx;
- ctx.stdin_behavior = bpb::named_pipe::create(
- bpb::named_pipe::input_stream);
- ctx.stdout_behavior = bpb::named_pipe::create(
- bpb::named_pipe::output_stream);
+ ctx.stdin_behavior = bpb::named_pipe(create_unique_pipe_name());
+ ctx.stdout_behavior = bpb::named_pipe(create_unique_pipe_name());
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx);
 

Modified: sandbox/SOC/2010/process/libs/process/test/handle.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/handle.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/test/handle.cpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -24,13 +24,14 @@
 
 #define BOOST_TEST_MAIN
 #include "util/boost.hpp"
+#include <utility>
 
 BOOST_AUTO_TEST_CASE(test_handle_readwrite)
 {
- bpb::pipe p(bpb::pipe::input_stream);
+ std::pair<bp::handle, bp::handle> p = bpb::pipe()(true);
 
- bp::handle read_end = p.get_child_end();
- bp::handle write_end = p.get_parent_end();
+ bp::handle read_end = p.first;
+ bp::handle write_end = p.second;
 
     bp::handle read_end2 = read_end;
     bp::handle write_end2 = write_end;

Modified: sandbox/SOC/2010/process/libs/process/test/util/boost.hpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/util/boost.hpp (original)
+++ sandbox/SOC/2010/process/libs/process/test/util/boost.hpp 2010-09-05 10:00:27 EDT (Sun, 05 Sep 2010)
@@ -22,6 +22,9 @@
 #include <boost/bind.hpp>
 #include <boost/ref.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/random_generator.hpp>
+#include <boost/uuid/uuid_io.hpp>
 
 namespace bp = boost::process;
 namespace bpb = boost::process::behavior;
@@ -30,5 +33,6 @@
 namespace butf = boost::unit_test::framework;
 namespace bfs = boost::filesystem;
 namespace ba = boost::asio;
+namespace bu = boost::uuids;
 
 #endif


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk