thoughts, ideas, code and other things...

Sunday, October 03, 2010

Stopping it from "just leaking" in PyObjC

*** __NSAutoreleaseNoPool(): Object 0x1040bf0f0 of class NSCFString autoreleased with no pool in place - just leaking

Found a way to get rid of these leakages. We need an NSAutoreleasePool to take care of all actions that happen under threads.

So if you have a CPU/disk/network heavy operation in a module that you're importing into say, a window controller, start them under an NSThread like this -

def do_heavy_task((callback, arg1, arg2)):
... # all heavy ops here

and in the controller -

import foo_module
class Controller_MainWindow(NSWindowController):
def btnFoo_Click_(self,sender):
thread = NSThread.detachNewThreadSelector_toTarget_withObject_(
'start_heavy_task',self, (self.return_heavy_task, arg1, arg2) )

def start_heavy_task(self, params):
pool = NSAutoreleasePool.alloc().init()
del pool

def return_heavy_task(self, msg):

Why all the call spaghetti with start_heavy_task, etc?
The issue is with detachNewThreadSelector_toTarget_withObject_ where I haven't been able to figure out how to pass a module's function as selector and the module as object. Also in this way your foo_module can remain independent of cocoa/objc/Foundation pollutions.

Anyhow, this works out into a clean solution. In case you have all your logical code in the window controller itself, you would find this programmish article extremely useful.

Update: a much better way would be to use decorators :D

def AutoPooled(f):
def pooled_func(self):
pool = NSAutoreleasePool.alloc().init()
del pool
return pooled_func

Now your start_heavy_task function becomes -

def start_heavy_task(self, params):

How fantastic :D

Labels: , ,


Post a Comment

Subscribe to Post Comments [Atom]

<< Home