summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/ScopeGuard.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/ScopeGuard.h')
-rw-r--r--xbmc/utils/ScopeGuard.h111
1 files changed, 111 insertions, 0 deletions
diff --git a/xbmc/utils/ScopeGuard.h b/xbmc/utils/ScopeGuard.h
new file mode 100644
index 0000000..2f731fb
--- /dev/null
+++ b/xbmc/utils/ScopeGuard.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include <functional>
+
+namespace KODI
+{
+namespace UTILS
+{
+
+/*! \class CScopeGuard
+ \brief Generic scopeguard designed to handle any type of handle
+
+ This is not necessary but recommended to cut down on some typing
+ using CSocketHandle = CScopeGuard<SOCKET, INVALID_SOCKET, closesocket>;
+
+ CSocketHandle sh(closesocket, open(thingy));
+ */
+template<typename Handle, Handle invalid, typename Deleter>
+class CScopeGuard
+{
+
+public:
+
+ CScopeGuard(std::function<Deleter> del, Handle handle = invalid)
+ : m_handle{handle}
+ , m_deleter{del}
+ { };
+
+ ~CScopeGuard() noexcept
+ {
+ reset();
+ }
+
+ operator Handle() const
+ {
+ return m_handle;
+ }
+
+ operator bool() const
+ {
+ return m_handle != invalid;
+ }
+
+ /*! \brief attach a new handle to this instance, if there's
+ already a handle it will be closed.
+
+ \param[in] handle The handle to manage
+ */
+ void attach(Handle handle)
+ {
+ reset();
+
+ m_handle = handle;
+ }
+
+ /*! \brief release the managed handle so that it won't be auto closed
+
+ \return The handle being managed by the guard
+ */
+ Handle release()
+ {
+ Handle h = m_handle;
+ m_handle = invalid;
+ return h;
+ }
+
+ /*! \brief reset the instance, closing any managed handle and setting it to invalid
+ */
+ void reset()
+ {
+ if (m_handle != invalid)
+ {
+ m_deleter(m_handle);
+ m_handle = invalid;
+ }
+ }
+
+ //Disallow default construction and copying
+ CScopeGuard() = delete;
+ CScopeGuard(const CScopeGuard& rhs) = delete;
+ CScopeGuard& operator= (const CScopeGuard& rhs) = delete;
+
+ //Allow moving
+ CScopeGuard(CScopeGuard&& rhs) noexcept
+ : m_handle{std::move(rhs.m_handle)}, m_deleter{std::move(rhs.m_deleter)}
+ {
+ // Bring moved-from object into released state so destructor will not do anything
+ rhs.release();
+ }
+ CScopeGuard& operator=(CScopeGuard&& rhs) noexcept
+ {
+ attach(rhs.release());
+ m_deleter = std::move(rhs.m_deleter);
+ return *this;
+ }
+
+private:
+ Handle m_handle;
+ std::function<Deleter> m_deleter;
+};
+
+}
+}