[vlc-devel] [PATCH v4] include: add C++ wrapper for C shared resources
Romain Vimont
rom1v at videolabs.io
Fri Oct 5 17:18:45 CEST 2018
Add a helper to create RAII wrappers for C shared resources, which
automatically call the Hold() and Release() functions associated to the
raw pointer.
Just declare a new shared resource wrapper type:
using InputItemPtr = vlc_shared_data_ptr_type(input_item_t,
input_item_Hold,
input_item_Release);
Then use this new type directly:
input_item_t *ptr = /* ... */;
InputItemPtr item(ptr);
QString name = item->psz_name;
InputItemPtr other = item; /* hold automatically */
---
Changes from v3:
- make the default constructor implicit
- add missing release in move-assignment operator
- do not hold in reset (the caller transfers its ownership)
include/vlc_cxx_helpers.hpp | 111 ++++++++++++++++++++++++++++++++++++
1 file changed, 111 insertions(+)
diff --git a/include/vlc_cxx_helpers.hpp b/include/vlc_cxx_helpers.hpp
index 832a964e53..8340c48f78 100644
--- a/include/vlc_cxx_helpers.hpp
+++ b/include/vlc_cxx_helpers.hpp
@@ -122,6 +122,117 @@ inline std::unique_ptr<T[], void (*)(void*)> wrap_carray( T* ptr ) noexcept
} // anonymous namespace
+///
+/// Wraps a C shared resource having associated Hold() and Release() functions
+//
+/// This is a RAII wrapper for C shared resources (which are manually managed by
+/// calling explicitly their Hold() and Release() functions).
+///
+/// The Hold() and Release() functions must accept exactly one parameter having
+/// type T* (the raw pointer type). Their return type is irrelevant.
+///
+/// To create a new shared resource wrapper type for my_type_t, simply declare:
+///
+/// using MyTypePtr =
+/// vlc_shared_data_ptr_type(my_type_t, my_type_Hold, my_type_Release);
+///
+/// Then use it to wrap a raw C pointer:
+///
+/// my_type_t *raw_ptr = /* ... */;
+/// MyTypePtr ptr(raw_ptr);
+
+// In C++17, the template declaration could be replaced by:
+// template<typename T, auto HOLD, auto RELEASE>
+template <typename T, typename H, typename R, H HOLD, R RELEASE>
+class vlc_shared_data_ptr {
+ T *ptr = nullptr;
+
+public:
+ /* default implicit constructor */
+ vlc_shared_data_ptr() = default;
+
+ explicit vlc_shared_data_ptr(T *ptr)
+ : ptr(ptr)
+ {
+ if (ptr)
+ HOLD(ptr);
+ }
+
+ vlc_shared_data_ptr(const vlc_shared_data_ptr &other)
+ : vlc_shared_data_ptr(other.ptr) {}
+
+ vlc_shared_data_ptr(vlc_shared_data_ptr &&other) noexcept
+ : ptr(other.ptr)
+ {
+ other.ptr = nullptr;
+ }
+
+ ~vlc_shared_data_ptr()
+ {
+ if (ptr)
+ RELEASE(ptr);
+ }
+
+ vlc_shared_data_ptr &operator=(const vlc_shared_data_ptr &other)
+ {
+ if (other.ptr)
+ HOLD(other.ptr);
+ reset(other.ptr);
+ return *this;
+ }
+
+ vlc_shared_data_ptr &operator=(vlc_shared_data_ptr &&other) noexcept
+ {
+ if (ptr)
+ RELEASE(ptr);
+ ptr = other.ptr;
+ other.ptr = nullptr;
+ return *this;
+ }
+
+ bool operator==(const vlc_shared_data_ptr &other) const
+ {
+ return ptr == other.ptr;
+ }
+
+ bool operator!=(const vlc_shared_data_ptr &other) const
+ {
+ return !(*this == other);
+ }
+
+ operator bool() const
+ {
+ return ptr;
+ }
+
+ T &operator*() const
+ {
+ return *ptr;
+ }
+
+ T *operator->() const
+ {
+ return ptr;
+ }
+
+ T *get() const
+ {
+ return ptr;
+ }
+
+ void reset(T *newptr)
+ {
+ if (ptr)
+ RELEASE(ptr);
+ ptr = newptr;
+ }
+};
+
+// useful due to the unnecessarily complex template declaration before C++17
+#define vlc_shared_data_ptr_type(type, hold, release) \
+ vlc_shared_data_ptr<type, decltype(&hold), decltype(&release), \
+ &hold, &release>
+
#ifdef VLC_THREADS_H_
namespace threads
--
2.19.0
More information about the vlc-devel
mailing list