Reference Counting Guide

This is a quick guide to the rules for reference counting that I wrote for myself while trying to track down some refcounting issues in the closures code. I wrote this for myself, but it's probably useful to anyone who's trying to modify the parts of Cython that generates reference counts.

Of course, we only refcount Python objects. In all of the text below, everything is assumed to be a PyObject *.

One should also read about the refnanny here, and the relevant Python docs are here.

Where's the Code?

Most of the reference counting code is concentrated in two places:

What are the reference counting operations?

There are essentially four reference counting operations available in Cython: two are essentially macros from the Python/C API, and two more are available via the refnanny. All of these take a single argument, which should be a non-NULL PyObject *. Each of these also has a variant with an X in the name (such as __Pyx_XDECREF), which is identical except that it accepts NULL as an argument (and does nothing in that case).

In the case that the refnanny is turned off, the INCREF and DECREF calls simply become the corresponding Python/C API calls, and the GOTREF and GIVEREF simply disappear. If the refnanny is turned on, then all four of these become calls into the refnanny, which increment and decrement the reference counts it maintains, and then call the Python/C API if necessary.

Another way of thinking about the INC/DEC operations vs. the GOT/GIVE operations is this: if you're doing an operation that leads to changing the number of references to an object, you're responsible for doing the appropriate incref or decref. On the other hand, if you're making calls to the Python/C API which change the reference count of an object, you should do a giveref or gotref to tell the refnanny what happened.

When should reference counts change?

The general rule is the obvious one: whenever we make a new reference to some Python object, you should do an incref, and whenever you set that variable to point to something else, you should do a decref. Of course, there are reasons that we want to break this rule, most commonly in the name of optimization. If we are generating both an incref and decref statement, and we don't have to worry about anything suspect happening in-between, we can simply eliminate both. Of course, there are plenty of things that can happen in between; here are two standard examples to keep in mind:

Rules for Cython refcounting code generation

Here are the rules for what reference counting code is generated.

Random Notes

refcounting (last edited 2010-02-02 01:32:14 by robertwb)