Loading...
Searching...
No Matches
GObjectMemory.h
/*
* Copyright (C) 2013-2017 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
* Pete Woods <pete.woods@canonical.com>
*/
#ifndef LOMIRI_UTIL_GOBJECTMEMORY_H
#define LOMIRI_UTIL_GOBJECTMEMORY_H
#include <memory>
#include <stdexcept>
#include <glib-object.h>
#include <lomiri/util/ResourcePtr.h>
namespace lomiri
{
namespace util
{
namespace
{
inline static void check_floating_gobject(gpointer t)
{
if (G_IS_OBJECT(t) && g_object_is_floating(G_OBJECT(t)))
{
throw std::invalid_argument("cannot manage floating GObject reference - call g_object_ref_sink(o) first");
}
}
}
struct GObjectDeleter
{
void operator()(gpointer ptr) noexcept
{
if (G_IS_OBJECT(ptr))
{
g_object_unref(ptr);
}
}
};
template<typename T> using GObjectSPtr = std::shared_ptr<T>;
template<typename T> using GObjectUPtr = std::unique_ptr<T, GObjectDeleter>;
namespace internal
{
template<typename SP>
class GObjectAssigner
{
public:
typedef typename SP::element_type ElementType;
GObjectAssigner(SP& smart_ptr) noexcept:
smart_ptr_(smart_ptr)
{
}
GObjectAssigner(const GObjectAssigner& other) = delete;
GObjectAssigner(GObjectAssigner&& other) noexcept:
ptr_(other.ptr_), smart_ptr_(other.smart_ptr_)
{
other.ptr_ = nullptr;
}
~GObjectAssigner() noexcept
{
smart_ptr_ = SP(ptr_, GObjectDeleter());
}
GObjectAssigner& operator=(const GObjectAssigner& other) = delete;
operator ElementType**() noexcept
{
return &ptr_;
}
private:
ElementType* ptr_ = nullptr;
SP& smart_ptr_;
};
template <typename T>
struct GObjectSignalUnsubscriber
{
void operator()(gulong handle) noexcept
{
if (handle != 0 && G_IS_OBJECT(obj_.get()))
{
g_signal_handler_disconnect(obj_.get(), handle);
}
}
GObjectSPtr<T> obj_;
};
}
template<typename T>
inline GObjectUPtr<T> unique_gobject(T* ptr)
{
check_floating_gobject(ptr);
GObjectDeleter d;
return GObjectUPtr<T>(ptr, d);
}
template<typename T>
inline GObjectSPtr<T> share_gobject(T* ptr)
{
check_floating_gobject(ptr);
GObjectDeleter d;
return GObjectSPtr<T>(ptr, d);
}
template<typename T, typename ... Args>
inline GObjectUPtr<T> make_gobject(GType object_type, const gchar *first_property_name, Args&&... args) noexcept
{
gpointer ptr = g_object_new(object_type, first_property_name, std::forward<Args>(args)...);
if (G_IS_OBJECT(ptr) && g_object_is_floating(ptr))
{
g_object_ref_sink(ptr);
}
return unique_gobject(G_TYPE_CHECK_INSTANCE_CAST(ptr, object_type, T));
}
template<typename SP>
inline internal::GObjectAssigner<SP> assign_gobject(SP& smart_ptr) noexcept
{
return internal::GObjectAssigner<SP>(smart_ptr);
}
template<typename T>
using GObjectSignalConnection = ResourcePtr<gulong, internal::GObjectSignalUnsubscriber<T>>;
template <typename T>
inline GObjectSignalConnection<T> gobject_signal_connection(gulong id, const GObjectSPtr<T>& obj)
{
return GObjectSignalConnection<T>(id, internal::GObjectSignalUnsubscriber<T>{obj});
}
} // namespace until
} // namespace lomiri
#endif
lomiri::util::ResourcePtr
Class to guarantee deallocation of arbitrary resources.
Definition ResourcePtr.h:121
lomiri
Top-level namespace for all things Lomiri-related.
Definition Version.h:38
lomiri::util::GObjectDeleter
Used by the make_gobject, unique_gobject and share_gobject as the deleter.
Definition GObjectMemory.h:61