-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e674fc6
commit dc1664a
Showing
8 changed files
with
422 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// | ||
// Copyright (c) 2023 Klemens Morgenstern ([email protected]) | ||
// | ||
// 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_ASYNC_IO_POPEN_HPP | ||
#define BOOST_ASYNC_IO_POPEN_HPP | ||
|
||
#include <boost/async/config.hpp> | ||
#include <boost/async/io/process.hpp> | ||
#include <boost/process/v2/popen.hpp> | ||
#include <boost/async/io/stream.hpp> | ||
|
||
namespace boost::async::io | ||
{ | ||
|
||
struct popen : stream | ||
{ | ||
using wait_result = system::result<int>; | ||
using handle_type = typename boost::process::v2::basic_process<executor>::handle_type; | ||
using native_handle_type = typename boost::process::v2::basic_process<executor>::native_handle_type; | ||
|
||
BOOST_ASYNC_DECL popen(boost::process::v2::filesystem::path executable, | ||
std::initializer_list<core::string_view> args, | ||
process_initializer initializer = {}); | ||
|
||
|
||
BOOST_ASYNC_DECL popen(boost::process::v2::filesystem::path executable, | ||
std::span<core::string_view> args, | ||
process_initializer initializer = {}); | ||
|
||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> interrupt(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> request_exit(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> suspend(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> resume(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> terminate(); | ||
[[nodiscard]] BOOST_ASYNC_DECL handle_type detach(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<bool> running(); | ||
|
||
|
||
[[nodiscard]] pid_type id() const; | ||
|
||
[[nodiscard]] system::result<void> close() override; | ||
[[nodiscard]] system::result<void> cancel() override; | ||
[[nodiscard]] bool is_open() const override; | ||
|
||
private: | ||
void async_read_some_impl_(buffers::mutable_buffer_subspan buffer, async::completion_handler<system::error_code, std::size_t> h)override; | ||
void async_write_some_impl_(buffers::const_buffer_subspan buffer, async::completion_handler<system::error_code, std::size_t> h) override; | ||
public: | ||
[[nodiscard]] process::wait_op_ wait() { return process::wait_op_{popen_}; } | ||
process::wait_op_ operator co_await () { return wait(); } | ||
private: | ||
boost::process::v2::basic_popen<executor> popen_; | ||
}; | ||
|
||
|
||
} | ||
|
||
#endif //BOOST_ASYNC_IO_POPEN_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// | ||
// Copyright (c) 2023 Klemens Morgenstern ([email protected]) | ||
// | ||
// 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_ASYNC_IO_PROCESS_HPP | ||
#define BOOST_ASYNC_IO_PROCESS_HPP | ||
|
||
#include <boost/async/config.hpp> | ||
#include <boost/async/op.hpp> | ||
|
||
#include <boost/process/v2/process.hpp> | ||
#include <boost/process/v2/stdio.hpp> | ||
#include <boost/process/v2/start_dir.hpp> | ||
#include <boost/process/v2/environment.hpp> | ||
#include <boost/core/detail/string_view.hpp> | ||
#include <boost/system/result.hpp> | ||
|
||
#include <initializer_list> | ||
|
||
namespace boost::async::io | ||
{ | ||
|
||
using boost::process::v2::pid_type; | ||
|
||
struct process_initializer | ||
{ | ||
process::v2::process_stdio stdio; | ||
process::v2::process_start_dir start_dir{process::v2::filesystem::current_path()}; | ||
process::v2::process_environment env{process::v2::environment::current()}; | ||
}; | ||
|
||
struct process | ||
{ | ||
using wait_result = system::result<int>; | ||
using handle_type = typename boost::process::v2::basic_process<executor>::handle_type; | ||
using native_handle_type = typename boost::process::v2::basic_process<executor>::native_handle_type; | ||
|
||
BOOST_ASYNC_DECL process(boost::process::v2::filesystem::path executable, | ||
std::initializer_list<core::string_view> args, | ||
process_initializer initializer = {}); | ||
|
||
|
||
BOOST_ASYNC_DECL process(boost::process::v2::filesystem::path executable, | ||
std::span<core::string_view> args, | ||
process_initializer initializer = {}); | ||
|
||
BOOST_ASYNC_DECL process(pid_type pid); | ||
BOOST_ASYNC_DECL process(pid_type pid, native_handle_type native_handle); | ||
|
||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> interrupt(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> request_exit(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> suspend(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> resume(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<void> terminate(); | ||
[[nodiscard]] BOOST_ASYNC_DECL handle_type detach(); | ||
[[nodiscard]] BOOST_ASYNC_DECL system::result<bool> running(); | ||
|
||
|
||
[[nodiscard]] pid_type id() const; | ||
|
||
private: | ||
struct wait_op_ : detail::deferred_op_resource_base | ||
{ | ||
constexpr static bool await_ready() { return false; } | ||
|
||
BOOST_ASYNC_DECL void init_op(completion_handler<system::error_code, int> handler); | ||
|
||
template<typename Promise> | ||
bool await_suspend(std::coroutine_handle<Promise> h) | ||
{ | ||
try | ||
{ | ||
init_op(completion_handler<system::error_code, int>{h, result_, get_resource(h)}); | ||
return true; | ||
} | ||
catch(...) | ||
{ | ||
error = std::current_exception(); | ||
return false; | ||
} | ||
} | ||
|
||
[[nodiscard]] wait_result await_resume() | ||
{ | ||
if (error) | ||
std::rethrow_exception(std::exchange(error, nullptr)); | ||
auto [ec, sig] = result_.value_or(std::make_tuple(system::error_code{}, 0)); | ||
if (ec) | ||
return ec; | ||
else | ||
return sig; | ||
} | ||
wait_op_(boost::process::v2::basic_process<executor> & process) : process_(process) {} | ||
private: | ||
boost::process::v2::basic_process<executor> & process_; | ||
std::exception_ptr error; | ||
std::optional<std::tuple<system::error_code, int>> result_; | ||
char buffer[256]; | ||
std::optional<container::pmr::monotonic_buffer_resource> resource; | ||
}; | ||
public: | ||
[[nodiscard]] wait_op_ wait() { return wait_op_{process_}; } | ||
wait_op_ operator co_await () { return wait(); } | ||
private: | ||
boost::process::v2::basic_process<executor> process_; | ||
friend struct popen; | ||
}; | ||
|
||
|
||
} | ||
|
||
#endif //BOOST_ASYNC_IO_PROCESS_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// | ||
// Copyright (c) 2023 Klemens Morgenstern ([email protected]) | ||
// | ||
// 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) | ||
// | ||
|
||
#include <boost/async/io/popen.hpp> | ||
|
||
namespace boost::async::io | ||
{ | ||
|
||
popen::popen(boost::process::v2::filesystem::path executable, | ||
std::initializer_list<core::string_view> args, | ||
process_initializer initializer) | ||
: popen_(this_thread::get_executor(), | ||
executable, | ||
args, | ||
initializer.stdio, | ||
initializer.start_dir, | ||
initializer.env) {} | ||
|
||
|
||
popen::popen(boost::process::v2::filesystem::path executable, | ||
std::span<core::string_view> args, | ||
process_initializer initializer) | ||
: popen_(this_thread::get_executor(), | ||
executable, | ||
args, | ||
initializer.stdio, | ||
initializer.start_dir, | ||
initializer.env) {} | ||
|
||
pid_type popen::id() const {return popen_.id();} | ||
|
||
system::result<void> popen::interrupt() | ||
{ | ||
system::error_code ec; | ||
popen_.interrupt(ec); | ||
return ec ? ec : system::result<void>(); | ||
} | ||
system::result<void> popen::request_exit() | ||
{ | ||
system::error_code ec; | ||
popen_.request_exit(ec); | ||
return ec ? ec : system::result<void>(); | ||
} | ||
system::result<void> popen::suspend() | ||
{ | ||
system::error_code ec; | ||
popen_.suspend(ec); | ||
return ec ? ec : system::result<void>(); | ||
} | ||
system::result<void> popen::resume() | ||
{ | ||
system::error_code ec; | ||
popen_.resume(ec); | ||
return ec ? ec : system::result<void>(); | ||
} | ||
system::result<void> popen::terminate() | ||
{ | ||
system::error_code ec; | ||
popen_.terminate(ec); | ||
return ec ? ec : system::result<void>(); | ||
} | ||
popen::handle_type popen::detach() | ||
{ | ||
return popen_.detach(); | ||
} | ||
system::result<bool> popen::running() | ||
{ | ||
system::error_code ec; | ||
auto res = popen_.running(ec); | ||
return ec ? ec : system::result<bool>(res); | ||
} | ||
|
||
system::result<void> popen::close() | ||
{ | ||
return this->terminate(); | ||
} | ||
|
||
system::result<void> popen::cancel() | ||
{ | ||
system::error_code ec; | ||
popen_.get_stdin().cancel(ec); | ||
if (ec) | ||
return ec; | ||
popen_.get_stdout().cancel(ec); | ||
if (ec) | ||
return ec; | ||
return {}; | ||
} | ||
|
||
bool popen::is_open() const | ||
{ | ||
return this->popen_.is_open(); | ||
} | ||
|
||
void popen::async_read_some_impl_(buffers::mutable_buffer_subspan buffer, async::completion_handler<system::error_code, std::size_t> h) | ||
{ | ||
popen_.async_read_some(buffer, std::move(h)); | ||
} | ||
void popen::async_write_some_impl_(buffers::const_buffer_subspan buffer, async::completion_handler<system::error_code, std::size_t> h) | ||
{ | ||
popen_.async_write_some(buffer, std::move(h)); | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.