My Project
GObjectMemory.h
1 /*
2  * Copyright (C) 2013-2017 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License version 3 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
17  * Pete Woods <pete.woods@canonical.com>
18  */
19 
20 #ifndef LOMIRI_UTIL_GOBJECTMEMORY_H
21 #define LOMIRI_UTIL_GOBJECTMEMORY_H
22 
23 #include <memory>
24 #include <stdexcept>
25 #include <glib-object.h>
26 
27 #include <lomiri/util/ResourcePtr.h>
28 
29 namespace lomiri
30 {
31 
32 namespace util
33 {
34 
35 namespace
36 {
37 
38 inline static void check_floating_gobject(gpointer t)
39 {
40  if (G_IS_OBJECT(t) && g_object_is_floating(G_OBJECT(t)))
41  {
42  throw std::invalid_argument("cannot manage floating GObject reference - call g_object_ref_sink(o) first");
43  }
44 }
45 
46 }
47 
61 {
62  void operator()(gpointer ptr) noexcept
63  {
64  if (G_IS_OBJECT(ptr))
65  {
66  g_object_unref(ptr);
67  }
68  }
69 };
70 
71 template<typename T> using GObjectSPtr = std::shared_ptr<T>;
72 template<typename T> using GObjectUPtr = std::unique_ptr<T, GObjectDeleter>;
73 
74 namespace internal
75 {
76 
77 template<typename SP>
78 class GObjectAssigner
79 {
80 public:
81  typedef typename SP::element_type ElementType;
82 
83  GObjectAssigner(SP& smart_ptr) noexcept:
84  smart_ptr_(smart_ptr)
85  {
86  }
87 
88  GObjectAssigner(const GObjectAssigner& other) = delete;
89 
90  GObjectAssigner(GObjectAssigner&& other) noexcept:
91  ptr_(other.ptr_), smart_ptr_(other.smart_ptr_)
92  {
93  other.ptr_ = nullptr;
94  }
95 
96  ~GObjectAssigner() noexcept
97  {
98  smart_ptr_ = SP(ptr_, GObjectDeleter());
99  }
100 
101  GObjectAssigner& operator=(const GObjectAssigner& other) = delete;
102 
103  operator ElementType**() noexcept
104  {
105  return &ptr_;
106  }
107 
108 private:
109  ElementType* ptr_ = nullptr;
110 
111  SP& smart_ptr_;
112 };
113 
114 template <typename T>
115 struct GObjectSignalUnsubscriber
116 {
117  void operator()(gulong handle) noexcept
118  {
119  if (handle != 0 && G_IS_OBJECT(obj_.get()))
120  {
121  g_signal_handler_disconnect(obj_.get(), handle);
122  }
123  }
124 
125  GObjectSPtr<T> obj_;
126 };
127 
128 }
129 
142 template<typename T>
143 inline GObjectUPtr<T> unique_gobject(T* ptr)
144 {
145  check_floating_gobject(ptr);
146  GObjectDeleter d;
147  return GObjectUPtr<T>(ptr, d);
148 }
149 
162 template<typename T>
163 inline GObjectSPtr<T> share_gobject(T* ptr)
164 {
165  check_floating_gobject(ptr);
166  GObjectDeleter d;
167  return GObjectSPtr<T>(ptr, d);
168 }
169 
180 template<typename T, typename ... Args>
181 inline GObjectUPtr<T> make_gobject(GType object_type, const gchar *first_property_name, Args&&... args) noexcept
182 {
183  gpointer ptr = g_object_new(object_type, first_property_name, std::forward<Args>(args)...);
184  if (G_IS_OBJECT(ptr) && g_object_is_floating(ptr))
185  {
186  g_object_ref_sink(ptr);
187  }
188  return unique_gobject(G_TYPE_CHECK_INSTANCE_CAST(ptr, object_type, T));
189 }
190 
200 template<typename SP>
201 inline internal::GObjectAssigner<SP> assign_gobject(SP& smart_ptr) noexcept
202 {
203  return internal::GObjectAssigner<SP>(smart_ptr);
204 }
205 
206 template<typename T>
207 using GObjectSignalConnection = ResourcePtr<gulong, internal::GObjectSignalUnsubscriber<T>>;
208 
218 template <typename T>
219 inline GObjectSignalConnection<T> gobject_signal_connection(gulong id, const GObjectSPtr<T>& obj)
220 {
221  return GObjectSignalConnection<T>(id, internal::GObjectSignalUnsubscriber<T>{obj});
222 }
223 
224 } // namespace until
225 
226 } // namespace lomiri
227 
228 #endif
Top-level namespace for all things Lomiri-related.
Definition: Version.h:38
Used by the make_gobject, unique_gobject and share_gobject as the deleter.
Definition: GObjectMemory.h:61