Friday, January 26, 2007

Hang on

Delegate persistence is an interesting challenge in a pinvoke binding like Gtk#. Hang on to delegates too long and you tie up the delegate instance memory and keep objects alive which are providing the delegate's invocation target. Release the delegate too soon and you get crashes when the native code tries to invoke it posthumously.

Most of the callback parameters in Gtk+ are destroy notified, taking away the guesswork of when to release the delegate. We have supported notified delegate release for a while now.

Of the non-notified callbacks, most only need to persist for the duration of the method to which they are passed. Foreach methods are a common user of this style of delegate scope. I refer to this as "call" scope. You may have noticed warnings for method parameters defaulted to call scope. The generator treats all callback parameters as call scope if the method signature doesn't contain destroy notification and a scope attribute isn't explicitly provided via metadata.

The challenge appears when a callback parameter doesn't fit into either of these paradigms. There are callbacks which persist until removed by another method. Some of these luckily also provide destroy notification, but not all of them. There is also another class of callbacks that I will call "async" since they are typically provided to allow non-blocking implementations of functionality. The task is queued up by the method call and control returns before the task is actually completed.

Often these async methods take a delegate parameter that is invoked at the completion of the operation to notify the caller the operation is finished. I ran across an example of this method type while documenting the new Gtk printing API from 2.10. Since I was bored of writing documentation, I decided to take a crack at implementing async scope callbacks in the generator.

If you have any async callback delegates in your bindings, you can now add the scope="async" attribute to the parameter with metadata to automatically handle the persistence for this new scope.

No comments: