Add make_unique_wrapper()
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 28 Apr 2022 15:28:15 +0000 (11:28 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 13 Jun 2022 20:34:46 +0000 (16:34 -0400)
make_unique_wrapper is intended to facilitate the use of std::unique_ptr
to wrap C-style APIs that don't provide RAII resource management facilities.

Usage example:

   // API
   struct my_c_struct {
           // ...
   };

   struct my_c_struct *create_my_c_struct(void);
   void destroy_my_c_struct(struct my_c_struct *value);

   // Creating a unique_ptr to my_c_struct.
   auto safe_c_struct =
           lttng::make_unique_wrapper<my_c_struct, destroy_my_c_struct>(
                   create_my_c_struct());

Note that this facility is intended for use in the scope of a function.
If you need to return this unique_ptr instance, you should consider writting
a proper, idiomatic, wrapper.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I429fc6f62896efb04af95fc26143096043206265

src/common/Makefile.am
src/common/make-unique-wrapper.hpp [new file with mode: 0644]

index b0191dd472aa9aae5f22e337864e73545b1e08c9..928f8d30b0b97fe535a81950ad68b7216fa640f9 100644 (file)
@@ -87,6 +87,7 @@ libcommon_lgpl_la_SOURCES = \
        kernel-probe.cpp \
        location.cpp \
        log-level-rule.cpp \
+       make-unique-wrapper.hpp \
        mi-lttng.cpp mi-lttng.hpp \
        notification.cpp \
        payload.cpp payload.hpp \
diff --git a/src/common/make-unique-wrapper.hpp b/src/common/make-unique-wrapper.hpp
new file mode 100644 (file)
index 0000000..50d1916
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_MAKE_UNIQUE_WRAPPER_H
+#define LTTNG_MAKE_UNIQUE_WRAPPER_H
+
+#include <common/macros.hpp>
+
+#include <memory>
+
+namespace lttng {
+
+/*
+ * make_unique_wrapper is intended to facilitate the use of std::unique_ptr
+ * to wrap C-style APIs that don't provide RAII resource management facilities.
+ *
+ * Usage example:
+ *
+ *    // API
+ *    struct my_c_struct {
+ *            // ...
+ *    };
+ *
+ *    struct my_c_struct *create_my_c_struct(void);
+ *    void destroy_my_c_struct(struct my_c_struct *value);
+ *
+ *    // Creating a unique_ptr to my_c_struct.
+ *    auto safe_c_struct =
+ *            lttng::make_unique_wrapper<my_c_struct, destroy_my_c_struct>(
+ *                    create_my_c_struct());
+ *
+ * Note that this facility is intended for use in the scope of a function.
+ * If you need to return this unique_ptr instance, you should consider writting
+ * a proper, idiomatic, wrapper.
+ */
+
+namespace details
+{
+template <typename WrappedType, void (*DeleterFunction)(WrappedType *)>
+struct create_unique_class {
+       struct deleter {
+               void operator()(WrappedType *instance) const
+               {
+                       DeleterFunction(instance);
+               }
+       };
+
+       std::unique_ptr<WrappedType, deleter> operator()(WrappedType *instance) const
+       {
+               return std::unique_ptr<WrappedType, deleter>(instance);
+       }
+};
+} /* namespace details */
+
+/*
+ * 'free' is a utility function for use with make_unique_wrapper. It makes it easier to
+ * wrap raw pointers that have to be deleted with `free`. Using libc's 'free' as
+ * a make_unique_wrapper template argument will result in an error as 'WrappedType *' will
+ * not match free's 'void *' argument.
+ */
+template <class Type>
+void free(Type *ptr)
+{
+       std::free(ptr);
+}
+
+template <typename WrappedType, void (*DeleterFunc)(WrappedType *)>
+std::unique_ptr<WrappedType, typename details::create_unique_class<WrappedType, DeleterFunc>::deleter>
+make_unique_wrapper(WrappedType *instance)
+{
+       const details::create_unique_class<WrappedType, DeleterFunc> unique_deleter;
+
+       return unique_deleter(instance);
+}
+
+} /* namespace lttng */
+
+#endif /* LTTNG_MAKE_UNIQUE_WRAPPER_H */
This page took 0.028023 seconds and 5 git commands to generate.