The real story behind GtkTreeModel::row-deleted

I have a confession to make. Years ago, I told people who wrote GtkTreeModels that implemented reference counting to emit GtkTreeModel:row-deleted before actually removing the node from the model’s internal data structures, contrary to after like the documentation suggested. GtkTreeModelFilter and GtkTreeModelSort have worked like this for years. It turns out I have been wrong, and I now finally understand why — I failed to correlate two commits which fixed related bugs back in 2002.

Back in February 2002, emitting row-deleted after deleting the node from the internal data structure was indeed a problem and caused warnings/errors to be spewed to the console. I (wrongly) reasoned that the nodes had to be available during the row-deleted phase to receive the unref calls, and added a comment:

  /* we _need_ to emit ::row_deleted before we start unreffing the node
   * itself. This is because of the row refs, which start unreffing nodes
   * when we emit ::row_deleted
   */

I continued to refer to this comment even in 2007.

During that e-mail thread, I did notice a single line in gtktreemodel.c mentioning that “Please note that nodes that are deleted are not unreffed.”. But clearly, the contrary was happening in February 2002? Deleted nodes were being unreffed.

It turns out that these faulty unrefs were caused by another bug which was fixed in April 2002! Unfortunately, I failed to correlate these commits and continued to be wrongly convinced that emitting row-deleted after really removing the node could be troublesome.

The good thing is that this is now documented together with other rules to take into account when dealing with reference counting (blog post on this will follow) and it is now unit tested, so it cannot happen again.