aboutsummaryrefslogtreecommitdiff
path: root/src/zenutil/process/asyncpipereader.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenutil/process/asyncpipereader.h')
-rw-r--r--src/zenutil/process/asyncpipereader.h62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/zenutil/process/asyncpipereader.h b/src/zenutil/process/asyncpipereader.h
new file mode 100644
index 000000000..ad2ff8455
--- /dev/null
+++ b/src/zenutil/process/asyncpipereader.h
@@ -0,0 +1,62 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/process.h>
+#include <zencore/zencore.h>
+
+#include <functional>
+#include <memory>
+#include <string_view>
+
+namespace asio {
+class io_context;
+}
+
+namespace zen {
+
+/// Create an overlapped pipe pair suitable for async I/O on Windows.
+///
+/// Unlike CreateStdoutPipe() (which creates anonymous non-overlapped pipes),
+/// this creates a named pipe with FILE_FLAG_OVERLAPPED on the read end, so it
+/// can be used with asio::windows::stream_handle for fully async reads.
+/// The write end is inheritable and suitable for child process redirection.
+///
+/// On non-Windows platforms this simply delegates to CreateStdoutPipe().
+bool CreateOverlappedStdoutPipe(StdoutPipeHandles& OutPipe);
+
+/// Async pipe reader for capturing child process stdout/stderr.
+///
+/// Takes ownership of a pipe's read end and reads asynchronously:
+/// Linux/macOS: non-blocking fd + asio::posix::stream_descriptor
+/// Windows: overlapped named pipe + asio::windows::stream_handle
+///
+/// On Windows the pipe must have been created with CreateOverlappedStdoutPipe()
+/// for async I/O to work. Pipes from CreateStdoutPipe() will fail.
+///
+/// DataCallback is invoked for each chunk read (on the io_context).
+/// EofCallback is invoked when the pipe closes (child exited or pipe broken).
+class AsyncPipeReader
+{
+public:
+ explicit AsyncPipeReader(asio::io_context& IoContext);
+ ~AsyncPipeReader();
+
+ AsyncPipeReader(const AsyncPipeReader&) = delete;
+ AsyncPipeReader& operator=(const AsyncPipeReader&) = delete;
+
+ /// Take ownership of the pipe read-end and start async reading.
+ /// The write end is closed immediately (caller should have already launched
+ /// the child process). DataCallback receives raw chunks. EofCallback fires
+ /// once when the pipe reaches EOF.
+ void Start(StdoutPipeHandles&& Pipe, std::function<void(std::string_view Data)> DataCallback, std::function<void()> EofCallback);
+
+ /// Stop reading and close the pipe. Callbacks will not fire after this returns.
+ void Stop();
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> m_Impl;
+};
+
+} // namespace zen