[glib] docs: Remove commented out sections from GObject how-to
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] docs: Remove commented out sections from GObject how-to
- Date: Fri, 21 Aug 2015 14:16:21 +0000 (UTC)
commit f1287a9b2f995b8c7ec228cc3b3418670ef92695
Author: Philip Withnall <philip withnall collabora co uk>
Date: Fri Feb 20 12:54:05 2015 +0000
docs: Remove commented out sections from GObject how-to
Unused, outdated, and unsalvagable.
https://bugzilla.gnome.org/show_bug.cgi?id=744060
docs/reference/gobject/tut_howto.xml | 402 ----------------------------------
1 files changed, 0 insertions(+), 402 deletions(-)
---
diff --git a/docs/reference/gobject/tut_howto.xml b/docs/reference/gobject/tut_howto.xml
index 149f979..98f7875 100644
--- a/docs/reference/gobject/tut_howto.xml
+++ b/docs/reference/gobject/tut_howto.xml
@@ -1424,407 +1424,5 @@ maman_file_write (MamanFile *self,
parameter types.
</para>
</sect1>
-
-<!--
- this is utterly wrong and should be completely removed - or rewritten
- with a better example than writing a buffer using synchronous signals.
-
- <sect1>
- <title>How to provide more flexibility to users?</title>
-
- <para>
- The previous implementation does the job but the signal facility of
- GObject can be used to provide even more flexibility to this file
- change notification mechanism. One of the key ideas is to make the
- process of writing data to the file part of the signal emission
- process to allow users to be notified either before or after the
- data is written to the file.
- </para>
-
- <para>
- To integrate the process of writing the data to the file into the
- signal emission mechanism, we can register a default class closure
- for this signal which will be invoked during the signal emission,
- just like any other user-connected signal handler.
- </para>
-
- <para>
- The first step to implement this idea is to change the signature of
- the signal: we need to pass around the buffer to write and its size.
- To do this, we use our own marshaller which will be generated
- through GLib's glib-genmarshal tool. We thus create a file named <filename>marshall.list</filename>
which contains
- the following single line:
-<informalexample><programlisting>
-VOID:POINTER,UINT
-</programlisting></informalexample>
- and use the Makefile provided in <filename>sample/signal/Makefile</filename> to generate the file named
- <filename>maman-file-complex-marshall.c</filename>. This C file is finally included in
- <filename>maman-file-complex.c</filename>.
- </para>
-
- <para>
- Once the marshaller is present, we register the signal and its marshaller in the class_init function
- of the object <type>MamanFileComplex</type> (full source for this object is included in
- <filename>sample/signal/maman-file-complex.{h|c}</filename>):
-<informalexample><programlisting>
-GClosure *default_closure;
-GType param_types[2];
-
-default_closure = g_cclosure_new (G_CALLBACK (default_write_signal_handler),
- (gpointer)0xdeadbeaf /* user_data */,
- NULL /* destroy_data */);
-
-param_types[0] = G_TYPE_POINTER;
-param_types[1] = G_TYPE_UINT;
-klass->write_signal_id =
- g_signal_newv ("write",
- G_TYPE_FROM_CLASS (g_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
- default_closure /* class closure */,
- NULL /* accumulator */,
- NULL /* accu_data */,
- maman_file_complex_VOID__POINTER_UINT,
- G_TYPE_NONE /* return_type */,
- 2 /* n_params */,
- param_types /* param_types */);
-</programlisting></informalexample>
- The code shown above first creates the closure which contains the code to complete the file write. This
- closure is registered as the default class_closure of the newly created signal.
- </para>
-
- <para>
- Of course, you need to implement completely the code for the default closure since I just provided
- a skeleton:
-<informalexample><programlisting>
-static void
-default_write_signal_handler (GObject *obj, guint8 *buffer, guint size, gpointer user_data)
-{
- g_assert (user_data == (gpointer)0xdeadbeaf);
- /* Here, we trigger the real file write. */
- g_print ("default signal handler: 0x%x %u\n", buffer, size);
-}
-</programlisting></informalexample>
- </para>
-
- <para>
- Finally, the client code must invoke the <function>maman_file_complex_write</function> function which
- triggers the signal emission:
-<informalexample><programlisting>
-void maman_file_complex_write (MamanFileComplex *self, guint8 *buffer, guint size)
-{
- /* trigger event */
- g_signal_emit (self,
- MAMAN_FILE_COMPLEX_GET_CLASS (self)->write_signal_id,
- 0, /* details */
- buffer, size);
-}
-</programlisting></informalexample>
- </para>
-
- <para>
- The client code (as shown in <filename>sample/signal/test.c</filename> and below) can now connect
signal handlers before
- and after the file write is completed: since the default signal handler which does the write itself
runs during the
- RUN_LAST phase of the signal emission, it will run after all handlers connected with <function><link
linkend="g-signal-connect">g_signal_connect</link></function>
- and before all handlers connected with <function><link
linkend="g-signal-connect-after">g_signal_connect_after</link></function>. If you intent to write a GObject
- which emits signals, I would thus urge you to create all your signals with the G_SIGNAL_RUN_LAST such
that your users
- have a maximum of flexibility as to when to get the event. Here, we combined it with
G_SIGNAL_NO_RECURSE and
- G_SIGNAL_NO_HOOKS to ensure our users will not try to do really weird things with our GObject. I
strongly advise you
- to do the same unless you really know why (in which case you really know the inner workings of GSignal
by heart and
- you are not reading this).
- </para>
-
- <para>
-<informalexample><programlisting>
-static void complex_write_event_before (GObject *file, guint8 *buffer, guint size, gpointer user_data)
-{
- g_assert (user_data == NULL);
- g_print ("Complex Write event before: 0x%x, %u\n", buffer, size);
-}
-
-static void complex_write_event_after (GObject *file, guint8 *buffer, guint size, gpointer user_data)
-{
- g_assert (user_data == NULL);
- g_print ("Complex Write event after: 0x%x, %u\n", buffer, size);
-}
-
-static void test_file_complex (void)
-{
- guint8 buffer[100];
- GObject *file;
-
- file = g_object_new (MAMAN_FILE_COMPLEX_TYPE, NULL);
-
- g_signal_connect (G_OBJECT (file), "write",
- (GCallback)complex_write_event_before,
- NULL);
-
- g_signal_connect_after (G_OBJECT (file), "write",
- (GCallback)complex_write_event_after,
- NULL);
-
- maman_file_complex_write (MAMAN_FILE_COMPLEX (file), buffer, 50);
-
- g_object_unref (G_OBJECT (file));
-}
-</programlisting></informalexample>
- The code above generates the following output on my machine:
-<programlisting>
-Complex Write event before: 0xbfffe280, 50
-default signal handler: 0xbfffe280 50
-Complex Write event after: 0xbfffe280, 50
-</programlisting>
- </para>
-
--->
-
-<!--
- this is also utterly wrong on so many levels that I don't even want
- to enumerate them. it's also full of completely irrelevant footnotes
- about personal preferences demonstrating a severe lack of whatsoever
- clue. the whole idea of storing the signal ids inside the Class
- structure is so fundamentally flawed that I'll require a frontal
- lobotomy just to forget I've ever seen it.
-
- <sect2>
- <title>How most people do the same thing with less code</title>
-
- <para>For many historic reasons related to how the ancestor of GObject used to work in GTK+ 1.x
versions,
- there is a much <emphasis>simpler</emphasis>
- <footnote>
- <para>I personally think that this method is horribly mind-twisting: it adds a new indirection
- which unnecessarily complicates the overall code path. However, because this method is widely used
- by all of GTK+ and GObject code, readers need to understand it. The reason why this is done that
way
- in most of GTK+ is related to the fact that the ancestor of GObject did not provide any other way
to
- create a signal with a default handler than this one. Some people have tried to justify that it is
done
- that way because it is better, faster (I am extremely doubtful about the faster bit. As a matter
of fact,
- the better bit also mystifies me ;-). I have the feeling no one really knows and everyone does it
- because they copy/pasted code from code which did the same. It is probably better to leave this
- specific trivia to hacker legends domain...
- </para>
- </footnote>
- way to create a signal with a default handler than to create
- a closure by hand and to use the <function><link
linkend="g-signal-newv">g_signal_newv</link></function>.
- </para>
-
- <para>For example, <function><link linkend="g-signal-new">g_signal_new</link></function> can be used
to create a signal which uses a default
- handler which is stored in the class structure of the object. More specifically, the class structure
- contains a function pointer which is accessed during signal emission to invoke the default handler
and
- the user is expected to provide to <function><link
linkend="g-signal-new">g_signal_new</link></function> the offset from the start of the
- class structure to the function pointer.
- <footnote>
- <para>I would like to point out here that the reason why the default handler of a signal is
named everywhere
- a class_closure is probably related to the fact that it used to be really a function pointer
stored in
- the class structure.
- </para>
- </footnote>
- </para>
-
- <para>The following code shows the declaration of the <type>MamanFileSimple</type> class structure
which contains
- the <function>write</function> function pointer.
-<informalexample><programlisting>
-struct _MamanFileSimpleClass {
- GObjectClass parent;
-
- guint write_signal_id;
-
- /* signal default handlers */
- void (*write) (MamanFileSimple *self, guint8 *buffer, guint size);
-};
-</programlisting></informalexample>
- The <function>write</function> function pointer is initialized in the class_init function of the
object
- to <function>default_write_signal_handler</function>:
-<informalexample><programlisting>
-static void
-maman_file_simple_class_init (gpointer g_class,
- gpointer g_class_data)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
- MamanFileSimpleClass *klass = MAMAN_FILE_SIMPLE_CLASS (g_class);
-
- klass->write = default_write_signal_handler;
-</programlisting></informalexample>
- Finally, the signal is created with <function><link
linkend="g-signal-new">g_signal_new</link></function> in the same class_init function:
-<informalexample><programlisting>
-klass->write_signal_id =
- g_signal_new ("write",
- G_TYPE_FROM_CLASS (g_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
- G_STRUCT_OFFSET (MamanFileSimpleClass, write),
- NULL /* accumulator */,
- NULL /* accu_data */,
- maman_file_complex_VOID__POINTER_UINT,
- G_TYPE_NONE /* return_type */,
- 2 /* n_params */,
- G_TYPE_POINTER,
- G_TYPE_UINT);
-</programlisting></informalexample>
- Of note, here, is the 4th argument to the function: it is an integer calculated by the
<function><link linkend="G-STRUCT-OFFSET">G_STRUCT_OFFSET</link></function>
- macro which indicates the offset of the member <emphasis>write</emphasis> from the start of the
- <type>MamanFileSimpleClass</type> class structure.
- <footnote>
- <para>GSignal uses this offset to create a special wrapper closure
- which first retrieves the target function pointer before calling it.
- </para>
- </footnote>
- </para>
-
- <para>
- While the complete code for this type of default handler looks less cluttered as shown in
- <filename>sample/signal/maman-file-simple.{h|c}</filename>, it contains numerous subtleties.
- The main subtle point which everyone must be aware of is that the signature of the default
- handler created that way does not have a user_data argument:
- <function>default_write_signal_handler</function> is different in
- <filename>sample/signal/maman-file-complex.c</filename> and in
- <filename>sample/signal/maman-file-simple.c</filename>.
- </para>
-
- <para>If you have doubts about which method to use, I would advise you to use the second one which
- involves <function><link linkend="g-signal-new">g_signal_new</link></function> rather than
<function><link linkend="g-signal-newv">g_signal_newv</link></function>:
- it is better to write code which looks like the vast majority of other GTK+/GObject code than to
- do it your own way. However, now, you know why.
- </para>
-
- </sect2>
-
- </sect1>
--->
-
-<!--
- yet another pointless section. if we are scared of possible abuses
- from the users then we should not be mentioning it inside a tutorial
- for beginners. but, obviously, there's nothing to be afraid of - it's
- just that this section must be completely reworded.
-
- <sect1>
- <title>How users can abuse signals (and why some think it is good)</title>
-
- <para>Now that you know how to create signals to which the users can connect easily and at any point in
- the signal emission process thanks to <function><link
linkend="g-signal-connect">g_signal_connect</link></function>,
- <function><link linkend="g-signal-connect-after">g_signal_connect_after</link></function> and
G_SIGNAL_RUN_LAST, it is time to look into how your
- users can and will screw you. This is also interesting to know how you too, can screw other people.
- This will make you feel good and eleet.
- </para>
-
- <para>
- The users can:
- <itemizedlist>
- <listitem><para>stop the emission of the signal at anytime</para></listitem>
- <listitem><para>override the default handler of the signal if it is stored as a function
- pointer in the class structure (which is the preferred way to create a default signal handler,
- as discussed in the previous section).</para></listitem>
- </itemizedlist>
- </para>
-
- <para>
- In both cases, the original programmer should be as careful as possible to write code which is
- resistant to the fact that the default handler of the signal might not able to run. This is obviously
- not the case in the example used in the previous sections since the write to the file depends on
whether
- or not the default handler runs (however, this might be your goal: to allow the user to prevent the
file
- write if he wishes to).
- </para>
-
- <para>
- If all you want to do is to stop the signal emission from one of the callbacks you connected yourself,
- you can call <function><link linkend="g-signal-stop-by-name">g_signal_stop_by_name</link></function>.
Its use is very simple which is why I won't detail
- it further.
- </para>
-
- <para>
- If the signal's default handler is just a virtual function pointer, it is also possible to override
- it yourself from the class_init function of a type which derives from the parent. That way, when the
signal
- is emitted, the parent class will use the function provided by the child as a signal default handler.
- Of course, it is also possible (and recommended) to chain up from the child to the parent's default
signal
- handler to ensure the integrity of the parent object.
- </para>
-
- <para>
- Overriding a class method and chaining up was demonstrated in <xref linkend="howto-gobject-methods"/>
- which is why I won't bother to show exactly how to do it here again.
- </para>
-
- </sect1>
-
--->
-
</chapter>
-
-<!--
- <sect2>
- <title>Warning on signal creation and default closure</title>
-
- <para>
- Most of the existing code I have seen up to now (in both GTK+, GNOME libraries and
- many GTK+ and GNOME applications) using signals uses a small
- variation of the default handler pattern I have shown in the previous section.
- </para>
-
- <para>
- Usually, the <function><link linkend="g-signal-new">g_signal_new</link></function> function is
preferred over
- <function><link linkend="g-signal-newv">g_signal_newv</link></function>. When <function><link
linkend="g-signal-new">g_signal_new</link></function>
- is used, the default closure is exported as a virtual function. For example,
- <filename>gobject.h</filename> contains the declaration of <link
linkend="GObjectClass"><type>GObjectClass</type></link>
- whose notify virtual function is the default handler for the <emphasis>notify</emphasis>
- signal:
-<informalexample><programlisting>
-struct _GObjectClass
-{
- GTypeClass g_type_class;
-
- /* class methods and other stuff. */
-
- /* signals */
- void (*notify) (GObject *object,
- GParamSpec *pspec);
-};
-</programlisting></informalexample>
- </para>
-
- <para>
- <filename>gobject.c</filename>'s <function><link
linkend="g-object-do-class-init">g_object_do_class_init</link></function> function
- registers the <emphasis>notify</emphasis> signal and initializes this virtual function
- to NULL:
-<informalexample><programlisting>
-static void
-g_object_do_class_init (GObjectClass *class)
-{
-
- /* Stuff */
-
- class->notify = NULL;
-
- gobject_signals[NOTIFY] =
- g_signal_new ("notify",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
- G_STRUCT_OFFSET (GObjectClass, notify),
- NULL, NULL,
- g_cclosure_marshal_VOID__PARAM,
- G_TYPE_NONE,
- 1, G_TYPE_PARAM);
-}
-</programlisting></informalexample>
- <function><link linkend="g-signal-new">g_signal_new</link></function> creates a <link
linkend="GClosure"><type>GClosure</type></link> which dereferences the
- type's class structure to access the virtual function pointer and invoke it if it not NULL. The
- virtual function is ignored it is set to NULL.
- </para>
-
- <para>
- To understand the reason for such a complex scheme to access the signal's default handler,
- you must remember the whole reason for the use of these signals. The goal here is to delegate
- a part of the process to the user without requiring the user to subclass the object to override
- one of the virtual functions. The alternative to subclassing, that is, the use of signals
- to delegate processing to the user, is, however, a bit less optimal in terms of speed: rather
- than just dereferencing a function pointer in a class structure, you must start the whole
- process of signal emission which is a bit heavyweight.
- </para>
-
- <para>
- This is why some people decided to use virtual functions for some signal's default handlers:
- rather than having users connect a handler to the signal and stop the signal emission
- from within that handler, you just need to override the default virtual function which is
- supposedly more efficient.
- </para>
-
- </sect2>
--->
</part>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]