[glibmm/glibmm-2-62] Gio::SocketControlMessage: Add add_deserialize_func()
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glibmm/glibmm-2-62] Gio::SocketControlMessage: Add add_deserialize_func()
- Date: Mon, 16 Sep 2019 17:09:11 +0000 (UTC)
commit c5f39c61c2fb7b66ad4db1d53c275e0262310e3f
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date: Mon Sep 16 19:05:59 2019 +0200
Gio::SocketControlMessage: Add add_deserialize_func()
The deserialize vfunc in GLib is a class virtual function (not associated
with an instance). Such functions don't exist in C++. But it must be wrapped
in one way or another. g_socket_control_message_deserialize() assumes that
all subclasses of GSocketControlMessage override this vfunc. A user-program
can crash, if any subclass does not.
This patch adds API by adding code from the master branch. Fixes #52
gio/src/socketcontrolmessage.ccg | 41 +++++++++++++++++++++++++++--------
gio/src/socketcontrolmessage.hg | 47 +++++++++++++++++++++++++++++++++-------
2 files changed, 71 insertions(+), 17 deletions(-)
---
diff --git a/gio/src/socketcontrolmessage.ccg b/gio/src/socketcontrolmessage.ccg
index 06e40011..ff98610c 100644
--- a/gio/src/socketcontrolmessage.ccg
+++ b/gio/src/socketcontrolmessage.ccg
@@ -17,13 +17,35 @@
#include <gio/gio.h>
#include <glibmm/exceptionhandler.h>
-namespace
+namespace Gio
{
+// static
+std::set<SocketControlMessage::DeserializeFunc> SocketControlMessage::m_deserialize_funcs;
-GSocketControlMessage* deserialize_vfunc_callback(
- int /* level */, int /* type */, gsize /* size */, gpointer /* data */)
+GSocketControlMessage* SocketControlMessage_Class::deserialize_vfunc_callback(
+ int level, int type, gsize size, gpointer data)
{
- // Do nothing.
+ // Loop through all registered deserialize functions.
+ // Accept the returned message from the first function that has been able to
+ // deserialize the message. g_socket_control_message_deserialize() loops
+ // through all subclasses of GSocketControlMessage in this way.
+ for (auto deserialize_func : CppObjectType::m_deserialize_funcs)
+ {
+ try // Trap C++ exceptions which would normally be lost because this is a C callback.
+ {
+ // Call the function which has been registered with add_deserialize_func().
+ Glib::RefPtr<SocketControlMessage> msg = deserialize_func(level, type, size, data);
+ if (msg)
+ {
+ msg->reference(); // Give the caller a reference.
+ return msg->gobj();
+ }
+ }
+ catch (...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ }
// Don't call the original underlying C function (GSocketControlMessage.deserialize()).
// Let g_socket_control_message_deserialize() do that as a last resort,
@@ -31,10 +53,11 @@ GSocketControlMessage* deserialize_vfunc_callback(
return nullptr;
}
-} // anonymous namespace
-
-namespace Gio
+// static
+void SocketControlMessage::add_deserialize_func(DeserializeFunc func)
{
-//TODO: When we can add API, copy add_deserialize_func(),
-// deserialize_vfunc_callback() and m_deserialize_funcs from the master branch.
+ // std::set never contains duplicates.
+ m_deserialize_funcs.insert(func);
+}
+
} // namespace Gio
diff --git a/gio/src/socketcontrolmessage.hg b/gio/src/socketcontrolmessage.hg
index d4c39c16..1ca652a1 100644
--- a/gio/src/socketcontrolmessage.hg
+++ b/gio/src/socketcontrolmessage.hg
@@ -15,6 +15,7 @@
*/
#include <glibmm/object.h>
+#include <set>
_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)
@@ -39,8 +40,9 @@ namespace Gio
* serialize_vfunc() methods.
*
* To extend the set of control messages that can be received, subclass this
- * class and implement the deserialize method. Also, make sure your class is
- * registered with the GType typesystem before calling
+ * class and implement a DeserializeFunc function. Typically it would be a
+ * static class method. Also, make sure you register the DeserializeFunc
+ * function with a call to add_deserialize_func() before calling
* Gio::Socket::receive() to read such a message.
*
* @ingroup NetworkIO
@@ -76,15 +78,44 @@ protected:
_PUSH(SECTION_PCC_CLASS_INIT_VFUNCS)
klass->deserialize = &deserialize_vfunc_callback;
_SECTION(SECTION_PH_VFUNCS)
- //TODO: Uncomment when we can add API.
- //static GSocketControlMessage* deserialize_vfunc_callback(
- // int level, int type, gsize size, gpointer data);
+ static GSocketControlMessage* deserialize_vfunc_callback(
+ int level, int type, gsize size, gpointer data);
_POP()
#m4end
- //TODO: When we can add API, add protected DeserializeFunc,
- // add_deserialize_func() and private m_deserialize_funcs from the master branch.
- // And update the last paragraph of the class description.
+ /** Pointer to a function that can be called from deserialize() or
+ * g_socket_control_message_deserialize().
+ *
+ * For instance,
+ * @code
+ * Glib::RefPtr<SocketControlMessage> my_deserialize_func(
+ * int level, int type, gsize size, gpointer data);
+ * @endcode
+ *
+ * @param level A socket level.
+ * @param type A socket control message type for the given @a level.
+ * @param size The size of the data in bytes.
+ * @param data Pointer to the message data (element-type guint8).
+ * @return The deserialized message or an empty Glib::RefPtr.
+ * The returned message can be a subclass of %SocketControlMessage.
+ */
+ using DeserializeFunc = Glib::RefPtr<SocketControlMessage> (*)
+ (int level, int type, gsize size, gpointer data);
+
+ /** Register a deserialize function.
+ *
+ * If the same function is registered multiple times, only the first
+ * registration has an effect.
+ *
+ * In GLib, %deserialize() is a class virtual function (not associated
+ * with an instance). Such functions don't exist in C++. A function registered
+ * with %add_deserialize_func() is a kind of replacement.
+ */
+ static void add_deserialize_func(DeserializeFunc func);
+
+private:
+ // Functions registered with add_deserialize_func().
+ static std::set<DeserializeFunc> m_deserialize_funcs;
};
} // namespace Gio
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]