aboutsummaryrefslogtreecommitdiffstats
path: root/liblfjail/guard.hh
diff options
context:
space:
mode:
authorLexi Winter <lexi@hemlock.eden.le-fay.org>2025-06-13 10:31:25 +0100
committerLexi Winter <lexi@hemlock.eden.le-fay.org>2025-06-13 10:31:25 +0100
commit722c03e547a1370857878ea7db27be6111aae8b1 (patch)
tree22544bc828275516f6068c9b048cc829672653bf /liblfjail/guard.hh
parent1202c450ce3bea3a2fa0c8ba369dcc40c2f8626b (diff)
downloadlfjail-722c03e547a1370857878ea7db27be6111aae8b1.tar.gz
lfjail-722c03e547a1370857878ea7db27be6111aae8b1.tar.bz2
move utilities to liblfjail
Diffstat (limited to 'liblfjail/guard.hh')
-rw-r--r--liblfjail/guard.hh47
1 files changed, 47 insertions, 0 deletions
diff --git a/liblfjail/guard.hh b/liblfjail/guard.hh
new file mode 100644
index 0000000..49d15d2
--- /dev/null
+++ b/liblfjail/guard.hh
@@ -0,0 +1,47 @@
+/*
+ * This source code is released into the public domain.
+ */
+
+#ifndef LFJAIL_GUARD_HH
+#define LFJAIL_GUARD_HH
+
+namespace lfjail {
+
+/*
+ * guard: invoke a callable when this object is destroyed; this is similar to
+ * scope_exit from the library fundamentals TS, which LLVM doesn't implement.
+ */
+template<std::invocable F>
+struct guard final {
+ // Initialise the guard with a callable we will invoke later.
+ guard(F func) : _func(std::move(func)) {}
+
+ /*
+ * We are being destroyed, so call the callable.
+ * If the callable throws, std::terminate() will be called.
+ */
+ ~guard() {
+ if (_func)
+ std::invoke(*_func);
+ }
+
+ // Release the guard. This turns the destructor into a no-op.
+ void release() noexcept {
+ _func.reset();
+ }
+
+ // Not default-constructible or copyable.
+ guard() = delete;
+ guard(guard const &) = delete;
+ guard(guard &&) noexcept = delete;
+ guard &operator=(guard const &) = delete;
+ guard &operator=(guard &&) noexcept = delete;
+
+private:
+ // The callable to be invoked when we are destroyed.
+ std::optional<F> _func;
+};
+
+} // namespace lfjail
+
+#endif // !LFJAIL_GUARD_HH