From 8802d23ba9c07d32d0da22213d8e76ed102d553f Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Thu, 28 Apr 2022 11:28:15 -0400 Subject: [PATCH] Add make_unique_wrapper() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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( 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 Change-Id: I429fc6f62896efb04af95fc26143096043206265 --- src/common/Makefile.am | 1 + src/common/make-unique-wrapper.hpp | 82 ++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/common/make-unique-wrapper.hpp diff --git a/src/common/Makefile.am b/src/common/Makefile.am index b0191dd47..928f8d30b 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -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 index 000000000..50d1916f2 --- /dev/null +++ b/src/common/make-unique-wrapper.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_MAKE_UNIQUE_WRAPPER_H +#define LTTNG_MAKE_UNIQUE_WRAPPER_H + +#include + +#include + +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( + * 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 +struct create_unique_class { + struct deleter { + void operator()(WrappedType *instance) const + { + DeleterFunction(instance); + } + }; + + std::unique_ptr operator()(WrappedType *instance) const + { + return std::unique_ptr(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 +void free(Type *ptr) +{ + std::free(ptr); +} + +template +std::unique_ptr::deleter> +make_unique_wrapper(WrappedType *instance) +{ + const details::create_unique_class unique_deleter; + + return unique_deleter(instance); +} + +} /* namespace lttng */ + +#endif /* LTTNG_MAKE_UNIQUE_WRAPPER_H */ -- 2.34.1