diff options
author | crupest <crupest@outlook.com> | 2024-10-06 13:57:39 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2024-10-06 13:57:39 +0800 |
commit | dfe62dcf8bcefc523b466e127c3edc4dc2756629 (patch) | |
tree | 1c751a14ba0da07ca2ff805633f97568060aa4c9 /include/cru/base/platform/unix | |
parent | f51eb955e188858272230a990565931e7403f23b (diff) | |
download | cru-dfe62dcf8bcefc523b466e127c3edc4dc2756629.tar.gz cru-dfe62dcf8bcefc523b466e127c3edc4dc2756629.tar.bz2 cru-dfe62dcf8bcefc523b466e127c3edc4dc2756629.zip |
Rename common to base.
Diffstat (limited to 'include/cru/base/platform/unix')
-rw-r--r-- | include/cru/base/platform/unix/PosixSpawnSubProcess.h | 50 | ||||
-rw-r--r-- | include/cru/base/platform/unix/UnixFileStream.h | 39 | ||||
-rw-r--r-- | include/cru/base/platform/unix/UnixPipe.h | 70 |
3 files changed, 159 insertions, 0 deletions
diff --git a/include/cru/base/platform/unix/PosixSpawnSubProcess.h b/include/cru/base/platform/unix/PosixSpawnSubProcess.h new file mode 100644 index 00000000..ee4e912a --- /dev/null +++ b/include/cru/base/platform/unix/PosixSpawnSubProcess.h @@ -0,0 +1,50 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifndef CRU_PLATFORM_UNIX +#error "This file can only be included on unix." +#endif + +#include "../../Base.h" +#include "../../SubProcess.h" +#include "../../io/AutoReadStream.h" + +#include "UnixFileStream.h" +#include "UnixPipe.h" + +#include <spawn.h> + +namespace cru::platform::unix { +class PosixSpawnSubProcessImpl : public Object, + public virtual IPlatformSubProcessImpl { + CRU_DEFINE_CLASS_LOG_TAG(u"PosixSpawnSubProcess") + + public: + explicit PosixSpawnSubProcessImpl(); + ~PosixSpawnSubProcessImpl(); + + void PlatformCreateProcess(const SubProcessStartInfo& start_info) override; + SubProcessExitResult PlatformWaitForProcess() override; + void PlatformKillProcess() override; + + io::Stream* GetStdinStream() override; + io::Stream* GetStdoutStream() override; + io::Stream* GetStderrStream() override; + + private: + pid_t pid_; + int exit_code_; + + UnixPipe stdin_pipe_; + UnixPipe stdout_pipe_; + UnixPipe stderr_pipe_; + + std::unique_ptr<UnixFileStream> stdin_stream_; + std::unique_ptr<UnixFileStream> stdout_stream_; + std::unique_ptr<UnixFileStream> stderr_stream_; + + std::unique_ptr<io::AutoReadStream> stdout_buffer_stream_; + std::unique_ptr<io::AutoReadStream> stderr_buffer_stream_; +}; +} // namespace cru::platform::unix diff --git a/include/cru/base/platform/unix/UnixFileStream.h b/include/cru/base/platform/unix/UnixFileStream.h new file mode 100644 index 00000000..8021f21a --- /dev/null +++ b/include/cru/base/platform/unix/UnixFileStream.h @@ -0,0 +1,39 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifndef CRU_PLATFORM_UNIX +#error "This file can only be included on unix." +#endif + +#include "../../io/Stream.h" + +namespace cru::platform::unix { +class UnixFileStream : public io::Stream { + private: + static constexpr auto kLogTag = u"cru::platform::unix::UnixFileStream"; + + public: + UnixFileStream(const char* path, int oflag, mode_t mode = 0660); + UnixFileStream(int fd, bool can_seek, bool can_read, bool can_write, + bool auto_close); + ~UnixFileStream() override; + + public: + CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE + + int GetFileDescriptor() const { return file_descriptor_; } + + protected: + Index DoSeek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; + + private: + void DoClose(); + + private: + int file_descriptor_; // -1 for no file descriptor + bool auto_close_; +}; +} // namespace cru::platform::unix diff --git a/include/cru/base/platform/unix/UnixPipe.h b/include/cru/base/platform/unix/UnixPipe.h new file mode 100644 index 00000000..cf35fb11 --- /dev/null +++ b/include/cru/base/platform/unix/UnixPipe.h @@ -0,0 +1,70 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifndef CRU_PLATFORM_UNIX +#error "This file can only be included on unix." +#endif + +#include "../../Base.h" +#include "../../Bitmask.h" + +namespace cru::platform::unix { +namespace details { +struct UnixPipeFlagTag; +} +using UnixPipeFlag = Bitmask<details::UnixPipeFlagTag>; +struct UnixPipeFlags { + constexpr static auto NonBlock = UnixPipeFlag::FromOffset(1); +}; + +/** + * @brief an unix pipe, commonly for communication of parent process and child + * process. + * + * There are two types of pipes sorted by its usage. For stdin, parent process + * SEND data to child process. For stdout and stderr, parent process RECEIVE + * data from child process. Each pipe has two ends, one for read and the other + * for write. But for send and receive, they are reversed. It is a little + * confused to consider which end should be used by parent and which end should + * be used by child. So this class help you make it clear. You specify SEND or + * RECEIVE, and this class give you a parent used end and a child used end. + * + * This class will only close the end used by parent when it is destructed. It + * is the user's duty to close the one used by child. + */ +class UnixPipe : public Object { + private: + constexpr static auto kLogTag = u"cru::platform::unix::UnixPipe"; + + public: + enum class Usage { + Send, + Receive, + }; + + explicit UnixPipe(Usage usage, bool auto_close, UnixPipeFlag flags = {}); + + CRU_DELETE_COPY(UnixPipe) + CRU_DELETE_MOVE(UnixPipe) + + ~UnixPipe(); + + /** + * @brief aka, the one used by parent process. + */ + int GetSelfFileDescriptor(); + + /** + * @brief aka, the one used by child process. + */ + int GetOtherFileDescriptor(); + + private: + Usage usage_; + bool auto_close_; + UnixPipeFlag flags_; + int read_fd_; + int write_fd_; +}; +} // namespace cru::platform::unix |