COROIO: coroio/pipe/pipe.hpp Source File
COROIO
Loading...
Searching...
No Matches
pipe.hpp
1#pragma once
2
4
5namespace NNet {
6
7#ifndef _WIN32
8
32class TPipe {
33public:
43 template<typename TPoller>
44 TPipe(TPoller& poller, const std::string& exe, const std::vector<std::string>& args, bool stderrToStdout = false)
45 : PipeLow(exe, args, stderrToStdout)
46 , Poller(&poller)
47 {
48 PipeLow.Fork();
49
50 ReadHandle = std::make_unique<TPipeFileHandle<TPoller>>(PipeLow.ReadFd, poller);
51 WriteHandle = std::make_unique<TPipeFileHandle<TPoller>>(PipeLow.WriteFd, poller);
52 if (!stderrToStdout) {
53 ErrHandle = std::make_unique<TPipeFileHandle<TPoller>>(PipeLow.ErrFd, poller);
54 }
55 }
56
58 int Pid() const { return PipeLow.ChildPid; }
59
61 void CloseRead() {
62 ReadHandle.reset();
63 }
64
66 void CloseWrite() {
67 WriteHandle.reset();
68 }
69
71 void CloseErr() {
72 ErrHandle.reset();
73 }
74
86 int Wait();
87
102
109 TFuture<ssize_t> ReadSome(void* buffer, size_t size);
110
117 TFuture<ssize_t> ReadSomeErr(void* buffer, size_t size);
118
125 TFuture<ssize_t> WriteSome(const void* buffer, size_t size);
126
127private:
128 struct TPipeLow {
129 TPipeLow(const std::string& exe, const std::vector<std::string>& args, bool mergeErr);
130 ~TPipeLow();
131
132 void Fork();
133
134 std::string Exe;
135 std::vector<std::string> Args;
136
137 // Descriptors are owned by TPipeFileHandle, do not close them!
138 int ReadFd = -1;
139 int WriteFd = -1;
140 int ErrFd = -1;
141 int ChildPid = -1;
142 bool StderrToStdout = false;
143 };
144
145 struct ITypelessFileHandle {
146 virtual ~ITypelessFileHandle() = default;
147 virtual TFuture<ssize_t> ReadSome(void* buffer, size_t size) = 0;
148 virtual TFuture<ssize_t> WriteSome(const void* buffer, size_t size) = 0;
149 };
150
151 template<typename TPoller>
152 struct TPipeFileHandle final : public ITypelessFileHandle {
153 TPipeFileHandle(int fd, TPoller& poller)
154 : Handle(fd, poller)
155 { }
156
157 TFuture<ssize_t> ReadSome(void* buffer, size_t size) override {
158 co_return co_await Handle.ReadSome(buffer, size);
159 }
160 TFuture<ssize_t> WriteSome(const void* buffer, size_t size) override {
161 co_return co_await Handle.WriteSome(buffer, size);
162 }
163
164 typename TPoller::TFileHandle Handle;
165 };
166
167 TPipeLow PipeLow;
168 TPollerBase* Poller;
169 std::unique_ptr<ITypelessFileHandle> ReadHandle;
170 std::unique_ptr<ITypelessFileHandle> WriteHandle;
171 std::unique_ptr<ITypelessFileHandle> ErrHandle;
172};
173
174#endif // _WIN32
175
176} // namespace NNet {
int Wait()
Waits for the child process to exit and returns its exit status.
Definition pipe.cpp:193
void CloseRead()
Closes the read end of the child's stdout pipe.
Definition pipe.hpp:61
TPipe(TPoller &poller, const std::string &exe, const std::vector< std::string > &args, bool stderrToStdout=false)
Spawns exe with args and wires up async I/O handles.
Definition pipe.hpp:44
void CloseWrite()
Closes the write end of the child's stdin pipe, sending EOF to the child.
Definition pipe.hpp:66
TFuture< ssize_t > ReadSome(void *buffer, size_t size)
Reads up to size bytes from the child's stdout.
Definition pipe.cpp:177
TFuture< ssize_t > WriteSome(const void *buffer, size_t size)
Writes up to size bytes to the child's stdin.
Definition pipe.cpp:189
TFuture< ssize_t > ReadSomeErr(void *buffer, size_t size)
Reads up to size bytes from the child's stderr.
Definition pipe.cpp:181
void CloseErr()
Closes the read end of the child's stderr pipe.
Definition pipe.hpp:71
int Pid() const
Returns the child's process ID.
Definition pipe.hpp:58
TFuture< int > AsyncWait()
Waits for the child process to exit without blocking the event loop.
Definition pipe.cpp:208
Implementation of a promise/future system for coroutines.
Owned coroutine handle that carries a result of type T.
Definition corochain.hpp:185