[gjs: 1/6] jsapi-util: add GjsAutoPointer to simply generate c++ smart pointers
- From: Marco Trevisan <marcotrevi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/6] jsapi-util: add GjsAutoPointer to simply generate c++ smart pointers
- Date: Sun, 14 Oct 2018 03:50:06 +0000 (UTC)
commit dab3c7d06b7e80ec778bf5a326e2588c8553a09c
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Wed Oct 10 03:11:38 2018 +0200
jsapi-util: add GjsAutoPointer to simply generate c++ smart pointers
A wrapper on std::unique_ptr that adds facility functions to unref and in case
take ownership of pointers handling the memory management in a smart way.
Keep just few specializations for specific objects
gi/object.cpp | 4 +-
gjs/jsapi-util.h | 137 ++++++++++++++++++++++++-------------------------------
2 files changed, 61 insertions(+), 80 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index 3626c2d6..1c3b7c33 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -286,7 +286,7 @@ GParamSpec* ObjectPrototype::find_param_spec_from_id(JSContext* cx,
GjsAutoChar gname = gjs_hyphen_from_camel(js_prop_name.get());
GjsAutoTypeClass<GObjectClass> gobj_class(m_gtype);
GParamSpec* pspec = g_object_class_find_property(gobj_class, gname);
- GjsAutoParam param_spec(pspec, GjsAutoParam::TakeOwnership());
+ GjsAutoParam param_spec(pspec, GjsAutoTakeOwnership());
if (!param_spec) {
_gjs_proxy_throw_nonexistent_field(cx, m_gtype, js_prop_name.get());
@@ -2386,7 +2386,7 @@ static bool find_vfunc_info(JSContext* context, GType implementor_gtype,
is_interface = g_base_info_get_type(ancestor_info) == GI_INFO_TYPE_INTERFACE;
- GjsAutoTypeClass<void> implementor_class(implementor_gtype);
+ GjsAutoTypeClass<GTypeClass> implementor_class(implementor_gtype);
if (is_interface) {
GTypeInstance *implementor_iface_class;
implementor_iface_class = (GTypeInstance*) g_type_interface_peek(implementor_class,
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index bfd1d079..b9f9053d 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -39,74 +39,66 @@
#define GJS_ALWAYS_INLINE
#endif
-class GjsAutoChar : public std::unique_ptr<char, decltype(&g_free)> {
-public:
- GjsAutoChar(char *str = nullptr) : unique_ptr(str, g_free) {}
-
- operator const char *() const {
- return get();
+struct GjsAutoTakeOwnership {};
+
+template <typename T, typename F,
+ void (*free_func)(F*) = nullptr, F* (*ref_func)(F*) = nullptr>
+struct GjsAutoPointer : std::unique_ptr<T, decltype(free_func)> {
+ GjsAutoPointer(T* ptr = nullptr) // NOLINT(runtime/explicit)
+ : GjsAutoPointer::unique_ptr(ptr, *free_func) {}
+ GjsAutoPointer(T* ptr, const GjsAutoTakeOwnership&)
+ : GjsAutoPointer(nullptr) {
+ auto ref = ref_func; // use if constexpr ... once we're on C++17
+ this->reset(ptr && ref ? reinterpret_cast<T*>(ref(ptr)) : ptr);
}
- void operator= (char *str) {
- reset(str);
- }
+ operator T*() const { return this->get(); }
+ T& operator[](size_t i) const { return static_cast<T*>(*this)[i]; }
- void operator= (const char *str) {
- reset(g_strdup(str));
+ T* copy() const { return reinterpret_cast<T*>(ref_func(this->get())); }
+
+ template <typename C>
+ C* as() const {
+ return const_cast<C*>(reinterpret_cast<const C*>(this->get()));
}
};
-template <typename T>
-class GjsAutoUnref : public std::unique_ptr<T, decltype(&g_object_unref)> {
-public:
- GjsAutoUnref(T *ptr = nullptr) : GjsAutoUnref::unique_ptr(ptr, g_object_unref) {}
-
- operator T *() const {
- return GjsAutoUnref::unique_ptr::get();
- }
+struct GjsAutoCharFuncs {
+ static char* dup(char* str) { return g_strdup(str); }
+ static void free(char* str) { g_free(str); }
};
+using GjsAutoChar =
+ GjsAutoPointer<char, char, GjsAutoCharFuncs::free, GjsAutoCharFuncs::dup>;
+
+template <typename T>
+using GjsAutoUnref = GjsAutoPointer<T, void, g_object_unref, g_object_ref>;
-template<typename T = GTypeClass>
-class GjsAutoTypeClass : public std::unique_ptr<T, decltype(&g_type_class_unref)> {
-public:
- GjsAutoTypeClass(gpointer ptr = nullptr)
- : GjsAutoTypeClass::unique_ptr(static_cast<T*>(ptr), g_type_class_unref) {}
+template <typename T = GTypeClass>
+struct GjsAutoTypeClass : GjsAutoPointer<T, void, &g_type_class_unref> {
+ GjsAutoTypeClass(gpointer ptr = nullptr) // NOLINT(runtime/explicit)
+ : GjsAutoPointer<T, void, g_type_class_unref>(static_cast<T*>(ptr)) {}
explicit GjsAutoTypeClass(GType gtype)
: GjsAutoTypeClass(g_type_class_ref(gtype)) {}
-
- operator T *() const { return GjsAutoTypeClass::unique_ptr::get(); }
-
- template<typename C>
- C *as() const { return reinterpret_cast<C*>(operator T *()); }
};
// Use this class for owning a GIBaseInfo* of indeterminate type. Any type (e.g.
// GIFunctionInfo*, GIObjectInfo*) will fit. If you know that the info is of a
// certain type (e.g. you are storing the return value of a function that
// returns GIFunctionInfo*,) use one of the derived classes below.
-class GjsAutoBaseInfo
- : public std::unique_ptr<GIBaseInfo, decltype(&g_base_info_unref)> {
- public:
- GjsAutoBaseInfo(GIBaseInfo* ptr = nullptr)
- : GjsAutoBaseInfo::unique_ptr(ptr, g_base_info_unref) {}
-
- operator GIBaseInfo*() const { return get(); }
-
- const char* name(void) const { return g_base_info_get_name(get()); }
- const char* ns(void) const { return g_base_info_get_namespace(get()); }
- GIInfoType type(void) const { return g_base_info_get_type(get()); }
+struct GjsAutoBaseInfo : GjsAutoPointer<GIBaseInfo, GIBaseInfo,
+ g_base_info_unref, g_base_info_ref> {
+ GjsAutoBaseInfo(GIBaseInfo* ptr = nullptr) // NOLINT(runtime/explicit)
+ : GjsAutoPointer(ptr) {}
+
+ const char* name() const { return g_base_info_get_name(*this); }
+ const char* ns() const { return g_base_info_get_namespace(*this); }
+ GIInfoType type() const { return g_base_info_get_type(*this); }
};
// Use GjsAutoInfo, preferably its typedefs below, when you know for sure that
// the info is either of a certain type or null.
template <GIInfoType TAG>
-class GjsAutoInfo : public GjsAutoBaseInfo {
- void validate(void) const {
- if (*this)
- g_assert(g_base_info_get_type(get()) == TAG);
- }
-
- public:
+struct GjsAutoInfo : GjsAutoBaseInfo {
// Normally one-argument constructors should be explicit, but we are trying
// to conform to the interface of std::unique_ptr here.
GjsAutoInfo(GIBaseInfo* ptr = nullptr) // NOLINT(runtime/explicit)
@@ -115,12 +107,18 @@ class GjsAutoInfo : public GjsAutoBaseInfo {
}
void reset(GIBaseInfo* other = nullptr) {
- GjsAutoInfo::unique_ptr::reset(other);
+ GjsAutoBaseInfo::reset(other);
validate();
}
// You should not need this method, because you already know the answer.
- GIInfoType type(void) = delete;
+ GIInfoType type() = delete;
+
+ private:
+ void validate() const {
+ if (GIBaseInfo* base = *this)
+ g_assert(g_base_info_get_type(base) == TAG);
+ }
};
using GjsAutoEnumInfo = GjsAutoInfo<GI_INFO_TYPE_ENUM>;
@@ -135,56 +133,39 @@ using GjsAutoVFuncInfo = GjsAutoInfo<GI_INFO_TYPE_VFUNC>;
// GICallableInfo can be one of several tags, so we have to have a separate
// class, and use GI_IS_CALLABLE_INFO() to validate.
-class GjsAutoCallableInfo : public GjsAutoBaseInfo {
- void validate(void) const {
- if (*this)
- g_assert(GI_IS_CALLABLE_INFO(get()));
- }
-
- public:
+struct GjsAutoCallableInfo : GjsAutoBaseInfo {
GjsAutoCallableInfo(GIBaseInfo* ptr = nullptr) // NOLINT(runtime/explicit)
: GjsAutoBaseInfo(ptr) {
validate();
}
void reset(GIBaseInfo* other = nullptr) {
- GjsAutoCallableInfo::unique_ptr::reset(other);
+ GjsAutoBaseInfo::reset(other);
validate();
}
+
+ private:
+ void validate() const {
+ if (GIBaseInfo* base = *this)
+ g_assert(GI_IS_CALLABLE_INFO(base));
+ }
};
/* For use of GjsAutoInfo<TAG> in GC hash maps */
namespace JS {
template <GIInfoType TAG>
struct GCPolicy<GjsAutoInfo<TAG>> : public IgnoreGCPolicy<GjsAutoInfo<TAG>> {};
-}
-
-class GjsAutoParam
- : public std::unique_ptr<GParamSpec, decltype(&g_param_spec_unref)> {
- public:
- struct TakeOwnership {};
-
- GjsAutoParam(GParamSpec* ptr = nullptr)
- : unique_ptr(ptr, g_param_spec_unref) {}
-
- GjsAutoParam(GParamSpec* ptr, const TakeOwnership&)
- : GjsAutoParam(ptr ? g_param_spec_ref(ptr) : nullptr) {}
+} // namespace JS
- operator GParamSpec*() const { return get(); }
-};
+using GjsAutoParam = GjsAutoPointer<GParamSpec, GParamSpec, g_param_spec_unref,
+ g_param_spec_ref>;
/* For use of GjsAutoParam in GC hash maps */
namespace JS {
-template<>
+template <>
struct GCPolicy<GjsAutoParam> : public IgnoreGCPolicy<GjsAutoParam> {};
} // namespace JS
-struct GjsJSFreeArgs {
- void operator() (char *str) {
- JS_free(nullptr, str);
- }
-};
-
G_BEGIN_DECLS
#define GJS_UTIL_ERROR gjs_util_error_quark ()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]