aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.posix/process.ccm
diff options
context:
space:
mode:
Diffstat (limited to 'nihil.posix/process.ccm')
-rw-r--r--nihil.posix/process.ccm91
1 files changed, 91 insertions, 0 deletions
diff --git a/nihil.posix/process.ccm b/nihil.posix/process.ccm
new file mode 100644
index 0000000..425deac
--- /dev/null
+++ b/nihil.posix/process.ccm
@@ -0,0 +1,91 @@
+/*
+ * This source code is released into the public domain.
+ */
+
+module;
+
+#include <expected>
+#include <optional>
+#include <system_error>
+#include <utility>
+
+#include <sys/types.h>
+
+export module nihil.posix:process;
+
+import nihil.error;
+
+namespace nihil {
+
+/*
+ * wait_result: the exit status of a process.
+ */
+export struct wait_result final {
+ // Return true if the process exited normally with an exit code of
+ // zero, otherwise false.
+ [[nodiscard]] auto okay(this wait_result const &self) -> bool;
+ [[nodiscard]] explicit operator bool(this wait_result const &self);
+
+ // Return the exit status, if any.
+ [[nodiscard]] auto status(this wait_result const &self)
+ -> std::optional<int>;
+
+ // Return the exit signal, if any.
+ [[nodiscard]] auto signal(this wait_result const &self)
+ -> std::optional<int>;
+
+private:
+ friend struct process;
+
+ int _status;
+
+ // Construct a new wait_result from the output of waitpid().
+ wait_result(int status);
+};
+
+/*
+ * process: represents a process we created, which can be waited for.
+ */
+export struct process final {
+ process() = delete;
+
+ /*
+ * Create a new process from a pid, which must be a child of the
+ * current process.
+ */
+ process(::pid_t pid);
+
+ // When destroyed, we automatically wait for the process to
+ // avoid creating zombie processes.
+ ~process();
+
+ // Movable.
+ process(process &&) noexcept;
+ auto operator=(this process &, process &&) noexcept -> process &;
+
+ // Not copyable.
+ process(process const &) = delete;
+ auto operator=(this process &, process const &) -> process & = delete;
+
+ // Get the child's process id.
+ [[nodiscard]] auto pid(this process const &self) noexcept -> ::pid_t;
+
+ /*
+ * Wait for this process to exit (by calling waitpid()) and return
+ * its exit status. This destroys the process state, leaving this
+ * object in a moved-from state.
+ */
+ [[nodiscard]] auto wait(this process &&self)
+ -> std::expected<wait_result, error>;
+
+ /*
+ * Release this process so we won't try to wait for it when
+ * destroying this object.
+ */
+ [[nodiscard]] auto release(this process &&self) -> ::pid_t;
+
+private:
+ ::pid_t m_pid;
+};
+
+} // namespace nihil