[twenty-years] Start the languages chapter with pre-refcounting GTK+
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [twenty-years] Start the languages chapter with pre-refcounting GTK+
- Date: Thu, 27 Apr 2017 15:50:04 +0000 (UTC)
commit ae8ae29d67e91417826c8d78d6034f5ea79bf542
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Apr 27 08:21:15 2017 -0500
Start the languages chapter with pre-refcounting GTK+
book/languages.tex | 143 +++++++++++++++++++++++++++++++++++++++++++++++++--
book/references.bib | 9 +++
2 files changed, 148 insertions(+), 4 deletions(-)
---
diff --git a/book/languages.tex b/book/languages.tex
index 137f171..523e29d 100644
--- a/book/languages.tex
+++ b/book/languages.tex
@@ -1,14 +1,149 @@
\chapter{Programming Languages and Language Bindings}
-Scheme
+Miguel and I were very excited about the Scheme language when GNOME
+started. We had both read \cite{sicp} and liked the conciseness and
+power of this little Lisp-like language. In addition, two things had
+happened recently then: the \GIMP\ had started using Scheme as a
+language to write plug-ins for image manipulation (or as it called
+them, Script-fu scripts); also, the GNU project had released Guile,
+its embeddable Scheme interpreter.
-Python. Pygtk. Matt Wilson's Anaconda.
+Back then, the state of high-level languages was rather grim. Perl
+already existed and was quite popular, but more for system
+administration and casual scripting. Python was just beginning to get
+popular --- the first public version appeared in 1991, just a few
+years before \GNOME.
+
+We definitely wanted to write applications in a high-level language.
+There was good precedent for this: the \GIMP\ allowed it in a
+rudimentary but interesting way, and of course Emacs was written as a
+small core in C, with a Lisp interpreter, and the majority of its code
+was actually written in Lisp.
+
+At first, GTK+ didn't have reference counting. Widgets were owned by
+their parent containers, and containers were responsible for freeing
+their children recursively. This worked reasonably well for minimal
+applications, like the \GIMP and its plug-ins, but it was not a good
+scheme for large-scale applications where tracking the lifetime of
+objects is complex.
+
+Also, if we were going to have high-level languages calling into GTK+,
+we would need a way for the language to hold references to GTK+
+widgets, possibly tied to the language's garbage collector, and also
+for GTK to have its own references to widgets.
+
+Marius Vollmer appeared and started adding reference-counting to
+GTK+. The base class was GtkObject, and it had ref() and unref()
+functions.
+
+Before GTK+ had reference counting, code looked more or less like
+this:
+
+\begin{lstlisting}[basicstyle=\footnotesize,
+ GtkWidget *window;
+ GtkWidget *box;
+ GtkWidget *menubar;
+ GtkWidget *child;
+
+ window = gtk_window_new ("Window title");
+
+ box = gtk_vbox_new (...);
+ gtk_container_add (window, box);
+
+ menubar = gtk_menubar_new (...);
+ /* ... add menu items to menubar ... */
+ gtk_container_add (box, menubar);
+
+ child = gtk_button_new ("Click me");
+ gtk_container_add (box, child);
+
+ /* Hold on to window; when the program ends, just gtk_widget_destroy (window) */
+\end{lstlisting}
+
+At the end of the program, or when the user closed a window, the
+window would destroy itself and recursively destroy its children. If
+any other part of the program needed to hold a reference to a widget
+that might be destroyed in the meantime... well, people had to be
+careful not to do that, or to really ensure that they wouldn't try to
+access an object that had already been freed. C does not protect us
+from invalid accesses!
+
+Reference counting was a way to deal with the problem of holding more
+than one reference to a widget. Also, it would allow garbage
+collectors to work on top of GTK+'s simple reference counting.
+
+Now, in a purely reference-counted scheme of things, the code would
+have to look something like this:
+
+\begin{lstlisting}[basicstyle=\footnotesize,
+ GtkWidget *window;
+ GtkWidget *box;
+ GtkWidget *menubar;
+ GtkWidget *child;
+
+ window = gtk_window_new ("Window title");
+
+ box = gtk_vbox_new (...); /* box has a single reference */
+ gtk_container_add (window, box); /* box has two references */
+
+ menubar = gtk_menubar_new (...); /* menubar has a single reference */
+ /* ... add menu items to menubar ... */
+ gtk_container_add (box, menubar); /* menubar has two references */
+ gtk_object_unref (menubar); /* drop our ref; we don't need it anymore */
+
+ child = gtk_button_new ("Click me"); /* child has a single reference */
+ gtk_container_add (box, child); /* child has two references */
+ gtk_object_unref (child); /* drop our ref */
+
+ gtk_object_unref (box); /* we don't need this anymore */
+
+ /* We keep only a reference to window */
+\end{lstlisting}
+
+Here, most of the times that we create a child widget, we add it to
+its parent container, and then unref() the widget if we don't need it
+to hold on to it ourselves anymore --- the container hierarchy owns
+the base references to widgets. We only keep base references to our
+toplevel windows; for multi-window applications, it was common to have
+a GList of the program's main windows, and to exit the program when
+that list became empty.
+
+However, there was already a lot of code written for GTK+ when it did
+{\em not} have reference counting! People would not want to carefully
+audit their code to add calls to unref() all over the place.
+
+To make it possible for people to keep their existing code unchanged,
+and still add reference counting, we added a quirk: new objects would
+start out with a ``floating'' reference. This basically meant, ``this
+object is unowned until it gets added to a container''. Then, when a
+container was asked to add a child widget, the container would
+ref() the object and then ``sink'' the initial reference. The child
+widget would end up with a reference count of 1, owned by its parent
+container --- and the calling code would not need to unref() the child
+it just created.
+
+And of course, this caused confusion for widget implementors since the
+beginning. For application writers this was mostly fine: create
+widgets, add them to containers, and don't worry about them; if part
+of the app needed to hold an extra reference to a widget, they would
+just ref() it. However, writers of containers and libraries had to
+remember that they had to ref() {\bf and} then sink() a child widget
+that was being added to a container, {\bf or} just ref() a widget if
+they simply needed an extra reference to it.
+
+Backwards compatibility is great, but it grows the institutional
+memory...
+
+\section{Python}
+
+Python. Pygtk. Matt Wilson's Anaconda. Hand-written bindings.
GTK--
-Mono
+\section{Mono}
+
+\section{Language bindings, the civilized way}
Generating bindings from machine-readable descriptions of the API
GObject Introspection
-
diff --git a/book/references.bib b/book/references.bib
index 1dedde3..6a01b84 100644
--- a/book/references.bib
+++ b/book/references.bib
@@ -48,3 +48,12 @@
year = {2017}
url = {https://magcius.github.io/xplain/article/index.html}
}
+
+@book{sicp,
+ author = {Harold Abelson, Gerald Sussman, Julie Sussman},
+ title = {Structure and Interpretation of Computer Programs, Second Edition},
+ year = {1996},
+ publisher = {MIT Press},
+ location = {Cambridge, Massachusetts}
+ url = {https://mitpress.mit.edu/sicp/}
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]