[vlc-devel] [PATCH] include: add C++ wrapper for C shared pointers
Romain Vimont
rom1v at videolabs.io
Tue Sep 11 15:44:12 CEST 2018
Add a helper to create RAII wrappers for C shared pointers, which
automatically call the Hold() and Release() functions associated to the
raw pointer.
Just declare a new shared pointer wrapper type:
using InputItemPtr = vlc_shared_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 */
---
include/vlc_cxx_helpers.hpp | 63 +++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/include/vlc_cxx_helpers.hpp b/include/vlc_cxx_helpers.hpp
index 832a964e53..464b71a60a 100644
--- a/include/vlc_cxx_helpers.hpp
+++ b/include/vlc_cxx_helpers.hpp
@@ -122,6 +122,69 @@ inline std::unique_ptr<T[], void (*)(void*)> wrap_carray( T* ptr ) noexcept
} // anonymous namespace
+///
+/// Wraps a C shared pointer having associated Hold() and Release() functions
+//
+/// This is a RAII wrapper for C shared pointers (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 pointer wrapper type for my_type_t, simply declare:
+///
+/// using MyTypePtr =
+/// vlc_shared_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_ptr {
+ T *ptr;
+public:
+ explicit vlc_shared_ptr(T *ptr = nullptr) : ptr(ptr) { if (ptr) HOLD(ptr); }
+ vlc_shared_ptr(const vlc_shared_ptr &o) : vlc_shared_ptr(o.ptr) {}
+ vlc_shared_ptr(vlc_shared_ptr &&o) noexcept :
+ ptr(std::exchange(o.ptr, nullptr)) {}
+ ~vlc_shared_ptr() { if (ptr) RELEASE(ptr); }
+ vlc_shared_ptr &operator=(const vlc_shared_ptr &o)
+ {
+ reset(o.ptr);
+ return *this;
+ }
+ vlc_shared_ptr &operator=(vlc_shared_ptr &&o) noexcept
+ {
+ ptr = std::exchange(o.ptr, nullptr);
+ return *this;
+ }
+ bool operator==(const vlc_shared_ptr &o) const { return ptr == o.ptr; }
+ bool operator!=(const vlc_shared_ptr &o) const { return !(*this == o); }
+ operator bool() const { return ptr; }
+ T &operator*() { return *ptr; }
+ const T &operator*() const { return *ptr; }
+ T *operator->() { return ptr; }
+ const T *operator->() const { return ptr; }
+ T *get() { return ptr; }
+ const T *get() const { return ptr; }
+ void reset(T *newptr) {
+ if (newptr)
+ /* hold before in case ptr == newptr */
+ HOLD(newptr);
+ if (ptr)
+ RELEASE(ptr);
+ ptr = newptr;
+ }
+};
+
+// useful due to the unnecessarily complex template declaration before C++17
+#define vlc_shared_ptr_type(type, hold, release) \
+ vlc_shared_ptr<type, decltype(&hold), decltype(&release), &hold, &release>
+
#ifdef VLC_THREADS_H_
namespace threads
--
2.19.0.rc2
More information about the vlc-devel
mailing list