File: sec-finalization.html

package info (click to toggle)
ebook-dev-ggad 199908-5
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k, sarge
  • size: 2,264 kB
  • ctags: 1,163
  • sloc: sh: 44; makefile: 35
file content (552 lines) | stat: -rw-r--r-- 21,728 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>
      Object Finalization
    </title>
    <meta name="GENERATOR" content=
    "Modular DocBook HTML Stylesheet Version 1.45">
    <link rel="HOME" title="GTK+ / Gnome Application Development"
    href="ggad.html">
    <link rel="UP" title="The GTK+ Object and Type System" href= 
    "cha-objects.html">
    <link rel="PREVIOUS" title="Signals" href="z109.html">
    <link rel="NEXT" title="Attaching Data to Objects" href= 
    "sec-objectdata.html">
  </head>
  <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink= 
  "#840084" alink="#0000FF">
    <div class="NAVHEADER">
      <table width="100%" border="0" bgcolor="#ffffff" cellpadding= 
      "1" cellspacing="0">
        <tr>
          <th colspan="4" align="center">
            <font color="#000000" size="2">GTK+ / Gnome Application
            Development</font>
          </th>
        </tr>
        <tr>
          <td width="25%" bgcolor="#ffffff" align="left">
            <a href="z109.html"><font color="#0000ff" size="2"><b>
            &lt;&lt;&lt; Previous</b></font></a>
          </td>
          <td width="25%" colspan="2" bgcolor="#ffffff" align= 
          "center">
            <font color="#0000ff" size="2"><b><a href="ggad.html">
            <font color="#0000ff" size="2"><b>
            Home</b></font></a></b></font>
          </td>
          <td width="25%" bgcolor="#ffffff" align="right">
            <a href="sec-objectdata.html"><font color="#0000ff"
            size="2"><b>Next &gt;&gt;&gt;</b></font></a>
          </td>
        </tr>
      </table>
    </div>
    <div class="SECT1">
      <h1 class="SECT1">
        <a name="SEC-FINALIZATION">Object Finalization</a>
      </h1>
      <p>
        To write a <span class="STRUCTNAME">GtkObject</span>, you
        must implement the methods provided by the <span class= 
        "STRUCTNAME">GtkObject</span> interface, or at least be
        sure you are happy with the default implementations. There
        are only five <span class="STRUCTNAME">GtkObject</span>
        methods; two of them are <span class="STRUCTNAME">
        get_arg</span> and <span class="STRUCTNAME">set_arg</span>,
        described in <a href="hc-objectargs.html#SEC-GETSETARG">the
        section called <i>Using Object Arguments in Your Own <span
        class="STRUCTNAME">GtkObject</span> Subclass</i></a>. The
        other three implement object destruction; here are the
        fields in <span class="STRUCTNAME">GtkObjectClass</span>:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;  void (* shutdown) (GtkObject *object);
  void (* destroy)  (GtkObject *object);
  
  void (* finalize) (GtkObject *object);&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        As you might guess from this, objects are destroyed in a
        three-stage process. Each method represents one stage in
        the process; if your object subclass overrides any of them,
        it must "chain up" to the corresponding method in the
        parent class (see <a href=
        "sec-finalization.html#SEC-CHAINUP">the section called <i>
        Chaining Up</i></a>). The three methods do the following:
      </p>
      <ul>
        <li>
          <p>
            The <span class="STRUCTNAME">shutdown</span> method
            allows objects to perform actions before destruction
            begins. Most subclasses do not override this method;
            the default <span class="STRUCTNAME">shutdown</span>
            method emits the <span class="SYMBOL">"destroy"</span>
            signal to start the next phase. (The default
            implementation will <i class="EMPHASIS">always</i> be
            invoked, even if overridden, because subclasses are
            required to "chain up.")&#13;
          </p>
        </li>
        <li>
          <p>
            The <span class="STRUCTNAME">destroy</span> method
            marks the object "useless" and cleans up associated
            resources, but does not free the object itself.
            Typically a destroy method would free data, strings,
            and so on stored in the instance struct, and set the
            struct members to <span class="STRUCTNAME">NULL</span>.
            This is the method most subclasses override.&#13;
          </p>
        </li>
        <li>
          <p>
            The <span class="STRUCTNAME">finalize</span> method is
            invoked <i class="EMPHASIS">only when the object's
            reference count reaches 0</i>. The default
            implementation frees the object instance struct, so
            that further attempts to use the object result in a
            segmentation fault. The <span class="STRUCTNAME">
            finalize</span> method must also consider that user
            code could have been invoked after the <span class= 
            "STRUCTNAME">destroy</span> method, and free any data
            that user code could have allocated. &#13;
          </p>
        </li>
      </ul>
      <p>
        Note: <i class="EMPHASIS">Objects can be destroyed
        regardless of their reference count</i>. This means that
        the <span class="STRUCTNAME">shutdown</span> method is
        invoked and the <span class="STRUCTNAME">destroy</span>
        signal is emitted. However, as long as the reference count
        is greater than 0, the object will not be <i class=
        "EMPHASIS">finalized</i>.
      </p>
      <p>
        The <span class="STRUCTNAME">shutdown</span> method has no
        defined role; its purpose depends on the particular object.
        For example, the <tt class="CLASSNAME">GtkWidget</tt>
        shutdown implementation removes the widget from its parent
        container, and unrealizes the widget. This is especially
        important for containers: their <span class="STRUCTNAME">
        destroy</span> method destroys all children of the
        container. If the container was not unrealized before
        destruction, it would still be visible and the user would
        see each child disappear, followed by the container. With
        the <span class="STRUCTNAME">shutdown</span> method,
        everything disappears at once.
      </p>
      <p>
        The <span class="STRUCTNAME">destroy</span> method frees as
        many resources as possible without rendering the object
        "unsafe." If your object has invariants describing its
        integrity, a <span class="STRUCTNAME">destroy</span> method
        will not violate them. All public functions exported by an
        object implementation should gracefully handle destroyed
        objects (they should not crash---remember that an object
        can be destroyed while references to it persist). The <span
        class="STRUCTNAME">finalize</span> method actually frees
        the object, meaning that attempts to use the object become
        dangerous bugs.
      </p>
      <p>
        The statement that "public functions exported by an object
        implementation should gracefully handle destroyed objects"
        requires some qualification. This is the intended behavior;
        otherwise, code could not ensure the sanity of an object by
        increasing its reference count. However, the implementation
        does not yet live up to the guarantee in all cases. Some
        public functions in GTK+ and Gnome still assume data
        structures freed in the destroy method exist, or
        re-allocate data structures the destroy method already
        freed. Unless the finalize method re-frees those data
        structures, they will be leaked. To avoid these bugs, it is
        best to avoid calling functions on destroyed objects (in
        practice, it would be uncommon to do so).
      </p>
      <p>
        You <i class="EMPHASIS">can</i> count on being able to
        check the type and object flags of a destroyed object,
        however; and it is certainly safe to call <tt class= 
        "FUNCTION">gtk_object_unref()</tt> on a destroyed object.
        In your own object implementations, be sure you implement
        each public function correctly; check whether the object is
        destroyed with <tt class="FUNCTION">
        GTK_OBJECT_DESTROYED()</tt>, and keep in mind that user
        code can run between the <span class="STRUCTNAME">
        destroy</span> method and the <span class="STRUCTNAME">
        finalize</span> method.
      </p>
      <p>
        Notice that the <span class="STRUCTNAME">destroy</span>
        method is the default handler for a <span class="SYMBOL">
        "destroy"</span> signal, but the <span class="STRUCTNAME">
        shutdown</span> and <span class="STRUCTNAME">
        finalize</span> methods are class functions only. This
        reduces the complexity and increases the speed of the
        finalization process. Also, because <span class=
        "STRUCTNAME">finalize</span> destroys the integrity of an
        object, it would be unsafe to emit as a signal (GTK+ does
        have a facility called "weak references" that allows you to
        invoke a callback when an object is finalized---weak
        references do not assume that the <span class="STRUCTNAME">
        GtkObject</span> is in a sane state).
      </p>
      <p>
        To make things more concrete, let's look at the functions
        you would use to destroy an object. First, <tt class= 
        "FUNCTION">gtk_object_destroy()</tt>:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;void
gtk_object_destroy (GtkObject *object)
{
  g_return_if_fail (object != NULL);
  g_return_if_fail (GTK_IS_OBJECT (object));
  g_return_if_fail (GTK_OBJECT_CONSTRUCTED (object));
  
  if (!GTK_OBJECT_DESTROYED (object))
    {
      gtk_object_ref (object);
      object-&gt;klass-&gt;shutdown (object);
      gtk_object_unref (object);
    }
}&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        Notice that destroyed-but-not-finalized objects are
        flagged, and this flag can be checked with the <tt class= 
        "FUNCTION">GTK_OBJECT_DESTROYED()</tt> macro. <tt class= 
        "FUNCTION">gtk_object_destroy()</tt> ensures that objects
        are not destroyed twice by ignoring any already-destroyed
        objects. If an object has not been destroyed, <tt class= 
        "FUNCTION">gtk_object_destroy()</tt> references it to
        prevent finalization during the destroy process and invokes
        the shutdown method; by default, that method looks like
        this:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;static void
gtk_object_shutdown (GtkObject *object)
{
  GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED);
  gtk_signal_emit (object, object_signals[DESTROY]);
}&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        This method sets the destroyed flag, to ensure that any
        recursive <tt class="FUNCTION">gtk_object_destroy()</tt>
        calls have no effect; then it emits the <span class=
        "SYMBOL">"destroy"</span> signal. <tt class="FUNCTION">
        gtk_object_shutdown()</tt> seems pointless by itself;
        however, subclasses may override this method with something
        more substantial, chaining up to the <span class=
        "STRUCTNAME">GtkObject</span> default method (see <a href= 
        "sec-finalization.html#SEC-CHAINUP">the section called <i>
        Chaining Up</i></a>).
      </p>
      <p>
        It may be unclear that <tt class="FUNCTION">
        gtk_object_shutdown()</tt> is a method implementation,
        while <tt class="FUNCTION">gtk_object_destroy()</tt> is a
        public function. Note that <tt class="FUNCTION">
        gtk_object_shutdown()</tt> is the internal function that
        implements the <span class="STRUCTNAME">shutdown</span>
        method for the <span class="STRUCTNAME">GtkObject</span>
        class, while <tt class="FUNCTION">gtk_object_destroy()</tt>
        is part of the public API. The <span class="STRUCTNAME">
        GtkObject</span> implementation of the <span class= 
        "STRUCTNAME">destroy</span> method is called <tt class= 
        "FUNCTION">gtk_object_real_destroy()</tt>:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;static void
gtk_object_real_destroy (GtkObject *object)
{
  if (GTK_OBJECT_CONNECTED (object))
    gtk_signal_handlers_destroy (object);
}&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        This code simply cleans up any signal handlers associated
        with the object. <tt class="FUNCTION">
        gtk_object_real_destroy()</tt> is the default handler
        invoked when the <span class="SYMBOL">"destroy"</span>
        signal is emitted. <tt class="FUNCTION">
        gtk_object_destroy()</tt> invokes the (possibly overridden)
        class function <span class="STRUCTNAME">shutdown</span>;
        the default shutdown method emits the <span class="SYMBOL">
        "destroy"</span> signal.
      </p>
      <p>
        Finalization is initiated by <tt class="FUNCTION">
        gtk_object_unref()</tt>, if and only if the reference count
        has reached 0. <tt class="FUNCTION">gtk_object_unref()</tt>
        can be invoked directly by a user, but often <tt class= 
        "FUNCTION">gtk_object_destroy()</tt> invokes it. Here it
        is:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;void
gtk_object_unref (GtkObject *object)
{
  g_return_if_fail (object != NULL);
  g_return_if_fail (GTK_IS_OBJECT (object));
  g_return_if_fail (object-&gt;ref_count &gt; 0);
  
  if (object-&gt;ref_count == 1)
    {
      gtk_object_destroy (object);
  
      g_return_if_fail (object-&gt;ref_count &gt; 0);
    }

  object-&gt;ref_count -= 1;

  if (object-&gt;ref_count == 0)
    {
      object-&gt;klass-&gt;finalize (object);
    }
}&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        If an object has a reference count of 1, calling <tt class= 
        "FUNCTION">gtk_object_unref()</tt> invokes the shutdown and
        destroy methods (via <tt class="FUNCTION">
        gtk_object_destroy()</tt>) and then finalizes the object
        (unless the reference count was incremented sometime during
        the shutdown/destroy process; this is allowed and will
        prevent finalization). If an object's reference count is
        greater than 1 at the start of <tt class="FUNCTION">
        gtk_object_unref()</tt>, the reference count is simply
        decremented.
      </p>
      <p>
        Again, notice that an object can be <i class="EMPHASIS">
        destroyed</i> while the reference count is greater than 1
        if the user calls <tt class="FUNCTION">
        gtk_object_destroy()</tt>; if this happens, finalization
        does not take place until the holders of the remaining
        references call <tt class="FUNCTION">
        gtk_object_unref()</tt>. In the most common case, the <tt
        class="FUNCTION">gtk_object_destroy()</tt> implementation
        holds the last reference count --- have another look at the
        <tt class="FUNCTION">gtk_object_destroy()</tt> code with
        this in mind.
      </p>
      <p>
        For completeness, here is <span class="STRUCTNAME">
        GtkObject</span>'s default <span class="STRUCTNAME">
        finalize</span> method:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;static void
gtk_object_finalize (GtkObject *object)
{
  gtk_object_notify_weaks (object);

  g_datalist_clear (&amp;object-&gt;object_data);
  
  gtk_type_free (GTK_OBJECT_TYPE (object), object);
}&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        The three function calls in this method do the following:
      </p>
      <ul>
        <li>
          <p>
            Invoke "weak references," which are callbacks invoked
            on object finalization. This is a little-used <span
            class="STRUCTNAME">GtkObject</span> feature not
            described in this book (usually connecting to the <span
            class="SYMBOL">"destroy"</span> signal is more
            appropriate).&#13;
          </p>
        </li>
        <li>
          <p>
            Clear any object data (described in <a href= 
            "sec-objectdata.html">the section called <i>Attaching
            Data to Objects</i></a>).&#13;
          </p>
        </li>
        <li>
          <p>
            Free the instance struct. &#13;
          </p>
        </li>
      </ul>
      <p>
        <a href="z57.html#WIDGETLIFECYCLE">the section called <i>
        Widget Life Cycle</i> in the chapter called <i>GTK+
        Basics</i></a> has more to say about reference counting and
        destruction with respect to widgets.
      </p>
      <div class="SECT2">
        <h2 class="SECT2">
          <a name="SEC-CHAINUP">Chaining Up</a>
        </h2>
        <p>
          If an object overrides the shutdown, destroy, or finalize
          methods, it should chain up to the default
          implementation, to ensure that each parent class has a
          chance to clean up. Here is an example of chaining up:
        </p>
        <table border="0" bgcolor="#E0E0E0" width="100%">
          <tr>
            <td>
<pre class="PROGRAMLISTING">
&#13;static void
gtk_widget_real_destroy (GtkObject *object)
{

  /* ... */

  if (parent_class-&gt;destroy)
    parent_class-&gt;destroy (object);

};&#13;
</pre>
            </td>
          </tr>
        </table>
        <p>
          <tt class="FUNCTION">gtk_widget_real_destroy()</tt> is
          installed in the widget's class struct in the class
          initialization function, overwriting the <span class= 
          "STRUCTNAME">GtkObject</span> default. <span class= 
          "STRUCTNAME">parent_class</span> is a pointer to the
          parent's class struct; usually you will want to store
          this pointer in your class initialization function, as
          <span class="STRUCTNAME">GtkWidget</span> does:
        </p>
        <table border="0" bgcolor="#E0E0E0" width="100%">
          <tr>
            <td>
<pre class="PROGRAMLISTING">
&#13;static GtkObjectClass *parent_class = NULL;

/* ... code omitted ... */

static void
gtk_widget_class_init (GtkWidgetClass *klass)
{
  GtkObjectClass *object_class;
  
  object_class = (GtkObjectClass*) klass;
  
  parent_class = gtk_type_class (gtk_object_get_type ());

  /* ... code omitted ... */
  
  object_class-&gt;set_arg = gtk_widget_set_arg;
  object_class-&gt;get_arg = gtk_widget_get_arg;
  object_class-&gt;shutdown = gtk_widget_shutdown;
  object_class-&gt;destroy = gtk_widget_real_destroy;
  object_class-&gt;finalize = gtk_widget_finalize;
} &#13;
</pre>
            </td>
          </tr>
        </table>
        <p>
          Of course, if <span class="STRUCTNAME">
          parent_class</span> is not a <span class="STRUCTNAME">
          GtkObjectClass*</span>, you will need to cast it with the
          <tt class="FUNCTION">GTK_OBJECT_CLASS()</tt> macro.
        </p>
        <p>
          An aside: notice that you should <i class="EMPHASIS">
          not</i> chain up when implementing <span class=
          "STRUCTNAME">get_arg</span> and <span class="STRUCTNAME">
          set_arg</span> --- GTK+ special-cases these methods in
          <tt class="FUNCTION">gtk_object_set()</tt> and <tt class= 
          "FUNCTION">gtk_object_get()</tt>. Recall that the <span
          class="STRUCTNAME">GtkObject</span> base class
          initializer zeroes these two methods, rather than leaving
          the default implementation. When setting or getting an
          argument value, GTK+ uses the information provided on
          argument registration to jump directly to the correct
          class struct and invoke only the correct <span class= 
          "STRUCTNAME">get_arg</span> or <span class="STRUCTNAME">
          set_arg</span> method. Chaining up would be a much slower
          way to implement the same thing (and would require unique
          argument IDs within the same class ancestry).
        </p>
      </div>
    </div>
    <div class="NAVFOOTER">
      <br>
      <br>
      <table width="100%" border="0" bgcolor="#ffffff" cellpadding= 
      "1" cellspacing="0">
        <tr>
          <td width="25%" bgcolor="#ffffff" align="left">
            <a href="z109.html"><font color="#0000ff" size="2"><b>
            &lt;&lt;&lt; Previous</b></font></a>
          </td>
          <td width="25%" colspan="2" bgcolor="#ffffff" align= 
          "center">
            <font color="#0000ff" size="2"><b><a href="ggad.html">
            <font color="#0000ff" size="2"><b>
            Home</b></font></a></b></font>
          </td>
          <td width="25%" bgcolor="#ffffff" align="right">
            <a href="sec-objectdata.html"><font color="#0000ff"
            size="2"><b>Next &gt;&gt;&gt;</b></font></a>
          </td>
        </tr>
        <tr>
          <td colspan="2" align="left">
            <font color="#000000" size="2"><b>Signals</b></font>
          </td>
          <td colspan="2" align="right">
            <font color="#000000" size="2"><b>Attaching Data to
            Objects</b></font>
          </td>
        </tr>
      </table>
    </div>
  </body>
</html>