The Case For Do-Once

Discussion in 'Python' started by Lawrence D'Oliveiro, Feb 8, 2010.

  1. I wrote my first Python extension library over the last couple of weeks. I
    took note of all the recommendations to keep track of reference counts, to
    ensure that objects were not disposed when they shouldn’t be, and were when
    they should. However, the example code seems to use gotos. And the trouble
    with these is that they don’t nest and un-nest easily; try to do too much
    refactoring with them, and you run into the age-old “spaghetti codeâ€
    problem.

    Which is where the do-once block comes in. The basic control flow is this:
    * Unconditionally initialize all dynamic storage to nil
    * Do the main body of the code, aborting in any error
    * Regardless of success or failure of the above, dispose of all
    allocated dynamic storage, using disposal calls which turn into
    noops if passed pointers that are already nil.

    For example, here’s a utility routine from my extension that, passed a
    Python array object, returns the address and length of the storage:

    static void GetBufferInfo
    (
    PyObject * FromArray,
    unsigned long * addr,
    unsigned long * len
    )
    /* returns the address and length of the data in a Python array object. */
    {
    PyObject * TheBufferInfo = 0;
    PyObject * AddrObj = 0;
    PyObject * LenObj = 0;
    do /*once*/
    {
    TheBufferInfo = PyObject_CallMethod(FromArray, "buffer_info", "");
    if (TheBufferInfo == 0)
    break;
    AddrObj = PyTuple_GetItem(TheBufferInfo, 0);
    LenObj = PyTuple_GetItem(TheBufferInfo, 1);
    if (PyErr_Occurred())
    break;
    Py_INCREF(AddrObj);
    Py_INCREF(LenObj);
    *addr = PyInt_AsUnsignedLongMask(AddrObj);
    *len = PyInt_AsUnsignedLongMask(LenObj);
    if (PyErr_Occurred())
    break;
    }
    while (false);
    Py_XDECREF(AddrObj);
    Py_XDECREF(LenObj);
    Py_XDECREF(TheBufferInfo);
    } /*GetBufferInfo*/

    You can pretty much determine by inspection that all the reference counts
    are properly maintained, no need to trace through convoluted flows of
    control.
    Lawrence D'Oliveiro, Feb 8, 2010
    #1
    1. Advertising

  2. Lawrence D'Oliveiro, 08.02.2010 09:53:
    > I wrote my first Python extension library over the last couple of weeks. I
    > took note of all the recommendations to keep track of reference counts, to
    > ensure that objects were not disposed when they shouldn’t be, and were when
    > they should.


    This sounds more like a case for Cython to me, should have saved you a lot
    of time.

    Stefan
    Stefan Behnel, Feb 8, 2010
    #2
    1. Advertising

  3. In message <hkoje5$4nf$>, Lawrence D'Oliveiro wrote:

    > The basic control flow is this:
    > * Unconditionally initialize all dynamic storage to nil
    > * Do the main body of the code, aborting in any error
    > * Regardless of success or failure of the above, dispose of all
    > allocated dynamic storage, using disposal calls which turn into
    > noops if passed pointers that are already nil.


    For more examples, see the spuhelper.c module here
    <http://github.com/ldo/dvd_menu_animator>.
    Lawrence D'Oliveiro, Feb 8, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve Franks
    Replies:
    2
    Views:
    1,234
    Steve Franks
    Jun 10, 2004
  2. Tee
    Replies:
    3
    Views:
    7,765
    Herfried K. Wagner [MVP]
    Jun 23, 2004
  3. Janice

    lower case to upper case

    Janice, Dec 10, 2004, in forum: C Programming
    Replies:
    17
    Views:
    1,150
    Richard Bos
    Dec 14, 2004
  4. Replies:
    1
    Views:
    2,456
    Mark P
    Apr 6, 2007
  5. Gancy
    Replies:
    4
    Views:
    163
    Rasto Levrinc
    Feb 3, 2005
Loading...

Share This Page