pyobjc-dev Mailing List for PyObjC (Page 191)
Brought to you by:
ronaldoussoren
You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(9) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(1) |
Feb
(2) |
Mar
(3) |
Apr
(30) |
May
(18) |
Jun
|
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2002 |
Jan
(7) |
Feb
(2) |
Mar
(1) |
Apr
|
May
|
Jun
(3) |
Jul
(13) |
Aug
|
Sep
(23) |
Oct
(180) |
Nov
(291) |
Dec
(95) |
2003 |
Jan
(338) |
Feb
(352) |
Mar
(97) |
Apr
(46) |
May
(226) |
Jun
(184) |
Jul
(145) |
Aug
(141) |
Sep
(69) |
Oct
(161) |
Nov
(96) |
Dec
(90) |
2004 |
Jan
(66) |
Feb
(87) |
Mar
(98) |
Apr
(132) |
May
(115) |
Jun
(68) |
Jul
(150) |
Aug
(92) |
Sep
(59) |
Oct
(52) |
Nov
(17) |
Dec
(75) |
2005 |
Jan
(84) |
Feb
(191) |
Mar
(133) |
Apr
(114) |
May
(158) |
Jun
(185) |
Jul
(62) |
Aug
(28) |
Sep
(36) |
Oct
(88) |
Nov
(65) |
Dec
(43) |
2006 |
Jan
(85) |
Feb
(62) |
Mar
(92) |
Apr
(75) |
May
(68) |
Jun
(101) |
Jul
(73) |
Aug
(37) |
Sep
(91) |
Oct
(65) |
Nov
(30) |
Dec
(39) |
2007 |
Jan
(24) |
Feb
(28) |
Mar
(10) |
Apr
(2) |
May
(18) |
Jun
(16) |
Jul
(21) |
Aug
(6) |
Sep
(30) |
Oct
(31) |
Nov
(153) |
Dec
(31) |
2008 |
Jan
(63) |
Feb
(70) |
Mar
(47) |
Apr
(24) |
May
(59) |
Jun
(22) |
Jul
(12) |
Aug
(7) |
Sep
(14) |
Oct
(26) |
Nov
(5) |
Dec
(5) |
2009 |
Jan
(10) |
Feb
(41) |
Mar
(70) |
Apr
(88) |
May
(49) |
Jun
(62) |
Jul
(34) |
Aug
(15) |
Sep
(55) |
Oct
(40) |
Nov
(67) |
Dec
(21) |
2010 |
Jan
(60) |
Feb
(17) |
Mar
(26) |
Apr
(26) |
May
(29) |
Jun
(4) |
Jul
(21) |
Aug
(21) |
Sep
(10) |
Oct
(12) |
Nov
(3) |
Dec
(19) |
2011 |
Jan
(3) |
Feb
(13) |
Mar
(8) |
Apr
(8) |
May
(17) |
Jun
(20) |
Jul
(21) |
Aug
(7) |
Sep
|
Oct
|
Nov
(9) |
Dec
(11) |
2012 |
Jan
(3) |
Feb
|
Mar
|
Apr
(5) |
May
(4) |
Jun
(14) |
Jul
(5) |
Aug
(2) |
Sep
(15) |
Oct
(2) |
Nov
(23) |
Dec
(1) |
2013 |
Jan
(8) |
Feb
(1) |
Mar
|
Apr
|
May
(5) |
Jun
(1) |
Jul
(5) |
Aug
(4) |
Sep
|
Oct
(12) |
Nov
(10) |
Dec
(3) |
2014 |
Jan
(7) |
Feb
(14) |
Mar
(2) |
Apr
|
May
(2) |
Jun
(11) |
Jul
(10) |
Aug
(4) |
Sep
|
Oct
(8) |
Nov
(1) |
Dec
(2) |
2015 |
Jan
(9) |
Feb
(7) |
Mar
(1) |
Apr
|
May
(7) |
Jun
|
Jul
(5) |
Aug
(6) |
Sep
|
Oct
(1) |
Nov
(4) |
Dec
|
2016 |
Jan
(1) |
Feb
(1) |
Mar
(4) |
Apr
(2) |
May
(1) |
Jun
|
Jul
(6) |
Aug
(8) |
Sep
(21) |
Oct
(17) |
Nov
|
Dec
(36) |
2017 |
Jan
(6) |
Feb
(2) |
Mar
(4) |
Apr
(2) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
(6) |
2018 |
Jan
(2) |
Feb
(3) |
Mar
(3) |
Apr
(14) |
May
(2) |
Jun
(2) |
Jul
(4) |
Aug
(3) |
Sep
(6) |
Oct
(16) |
Nov
(1) |
Dec
(6) |
2019 |
Jan
(3) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
(6) |
Nov
|
Dec
|
2020 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(1) |
Jul
(7) |
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(2) |
Dec
(1) |
2021 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
(5) |
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2023 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2025 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: b.bum <bb...@ma...> - 2004-04-08 22:04:10
|
On Apr 8, 2004, at 1:59 PM, Michael Tsai wrote: > I've never heard that before. The docs say: > >> Released autorelease pools, if not on the top of the stack, cause all >> (unreleased) autorelease pools above them on the stack to be >> released, along with all their objects. If you neglect to send >> release to an autorelease pool when you are finished with it >> (something not recommended), it is released when one of the >> autorelease pools in which it nests is released. > > <http://developer.apple.com/Documentation/Cocoa/Conceptual/MemoryMgmt/ > Concepts/AutoreleasePools.html#//apple_ref/doc/uid/20000047/EGGBFFED> Yup. You're right. I'm wrong (though only technically -- the "something not recommended" would indicate that I was conceptually right ... ;-). Thanks for the pointer! This also explains the behavior in Ronald's code. It isn't a bug, it is a feature! Since the code was deallocating the old pool after creating a new pool, the new pool was "above" the old pool in the stack and was therefore removed along with the old pool. b.bum |
From: Pierce T.W. I. <pi...@tw...> - 2004-04-08 22:01:16
|
> Anyone want to move to Subversion? > > I can have the project converted, moved over and setup in short order > -- potentially even preserving all history information. It mostly a > matter of grabbing a block of time where the CVS repository doesn't > change. > > A number of advantages: > > - it isn't CVS Not being CVS isn't an advantage in and of itself. That only works in presidential elections. > - web based repos browser that is much more straightforward But no Cocoa GUI tool like CVL. > - can mount the repos in Finder and drag a copy of the trunk or > branch just like any other filesystem If you're not on dialup. And only if the repository is hosted on a WebDAV server. > - it isn't CVS See above. > - repository checkout -- anonymous or otherwise -- is considerably > more straightforward It's what two steps to checkout? > - no more "wait 24 hours or so before changes are visible in > anonymous repos" That's a SF thing, not a CVS thing though. > - much better tagging/branching Well, better tagging. I'm not convinced the branching is better. > - atomic commits Does PyObjC ever run into this as a problem. > > Disadvantage: > - it is a change, and change is scary svn has some disadvantages too. I like Gnu arch better, especially for open source projects. http://wiki.gnuarch.org/ SVN is definitely a solution to source control, but I'm not convinced its better then CVS. 1. Its slower on dialup then CVS in my experience. 2. Tagging is better, branching looks better until you try to use it, then you realize that they forgot merging, which is the hard part of branching. So it ends up just being "different". 3. The repository is opaque. While SVN seems to be better designed then CVS, that's not saying much. Its not clear that it adds enough to CVS to be worth the trouble to switch. tla/arch is both better designed then CVS, and adds enough to be worth the trouble, but its hard to learn. Pierce |
From: Bob I. <bo...@re...> - 2004-04-08 21:19:33
|
On Apr 8, 2004, at 4:53 PM, b.bum wrote: > It would be hosted on red-bean.com > > svn.red-bean.com, specifically. Could also have a project page at > Tigris -- I find their UI to be better, but am indifferent either > way.... +1 |
From: Michael T. <li...@mj...> - 2004-04-08 20:59:24
|
On Apr 8, 2004, at 4:08 PM, b.bum wrote: > Releasing a pool only ever releases a single pool; it will never > cause two pools to be released (because a pool can never be > autoreleased). > > [...] > > Like thread looking, pulls are a stack. You shouldn't pull a pool > after pushing a new pool on top. I've never heard that before. The docs say: > Released autorelease pools, if not on the top of the stack, cause all > (unreleased) autorelease pools above them on the stack to be released, > along with all their objects. If you neglect to send release to an > autorelease pool when you are finished with it (something not > recommended), it is released when one of the autorelease pools in > which it nests is released. <http://developer.apple.com/Documentation/Cocoa/Conceptual/MemoryMgmt/ Concepts/AutoreleasePools.html#//apple_ref/doc/uid/20000047/EGGBFFED> --Michael |
From: Zachery B. <zb...@ur...> - 2004-04-08 20:58:58
|
On Apr 8, 2004, at 4:53 PM, b.bum wrote: > It would be hosted on red-bean.com > > svn.red-bean.com, specifically. Could also have a project page at > Tigris -- I find their UI to be better, but am indifferent either > way.... +1 Zac |
From: b.bum <bb...@ma...> - 2004-04-08 20:53:06
|
It would be hosted on red-bean.com svn.red-bean.com, specifically. Could also have a project page at Tigris -- I find their UI to be better, but am indifferent either way.... On Apr 8, 2004, at 1:49 PM, Zachery Bir wrote: > On Apr 8, 2004, at 4:40 PM, b.bum wrote: > >> Disadvantage: >> - it is a change, and change is scary > > and SF doesn't currently host SVN repositories? > > Zac > |
From: Zachery B. <zb...@ur...> - 2004-04-08 20:50:03
|
On Apr 8, 2004, at 4:40 PM, b.bum wrote: > Disadvantage: > - it is a change, and change is scary and SF doesn't currently host SVN repositories? Zac |
From: Donovan P. <ds...@ma...> - 2004-04-08 20:48:21
|
On Apr 8, 2004, at 4:40 PM, b.bum wrote: > Anyone want to move to Subversion? Yes. Please! Subversion is so much nicer in a lot of little tiny ways. It's also much faster for me. dp |
From: b.bum <bb...@ma...> - 2004-04-08 20:40:35
|
Anyone want to move to Subversion? I can have the project converted, moved over and setup in short order -- potentially even preserving all history information. It mostly a matter of grabbing a block of time where the CVS repository doesn't change. A number of advantages: - it isn't CVS - web based repos browser that is much more straightforward - can mount the repos in Finder and drag a copy of the trunk or branch just like any other filesystem - it isn't CVS - repository checkout -- anonymous or otherwise -- is considerably more straightforward - no more "wait 24 hours or so before changes are visible in anonymous repos" - much better tagging/branching - atomic commits Disadvantage: - it is a change, and change is scary b.bum |
From: b.bum <bb...@ma...> - 2004-04-08 20:07:57
|
On Apr 8, 2004, at 11:59 AM, Michael Tsai wrote: >> I'm not sure why Cocoa behaves like this, but this might be the >> intended behaviour. The documentation for NSAutoreleasePool explictly >> mentions that pools behave like a stack, I suppose the implementation >> doesn't like it when you pop the second highest entry of that stack. > > I think popping the second highest element on the stack should be > fine. That can happen in Objective-C if control leaves a pool's > "scope" because of an exception. Popping the outer (lower on the > stack) pool should cause it to empty the inner (higher on the stack) > pool. Autorelease pools are implemented as a stack. In the context of pure Obj-C, there is no requirement that you have a top level stack. All [almost?] of the classes in the Foundation and AppKit have allocation and initialization paths that can be followed to instantiate an object without that object ever sitting in an autorelease pool. This is useful in threaded or tool environments where you don't want to use an autorelease pool, for whatever reason. One of the most common reasons to avoid an autorelease pool is for efficiency's sake. Creating 10,000 objects that are intended to stick around beyond the current release pool is much less expensive if you can avoid having those 10,000 objects stuck in the release pool. Now, in the context of PyObjC, the move to automatically maintaining retain counts on the Python side of the bridge incurred the cost of effectively requiring an autorelease pool be present per thread (at least with the current design/implementation). Removing retain/release/autorelease from the Python side of the bridge is such a boon to the developer that paying that cost is pretty minor in comparison. Besides, if you really need to optimize memory usage and performance to that point, you can always write the performance sensitive code in ObjC and call to it from Python. > So I think what's happening is that the [oldpool release] is popping > both pools, causing the NSArray to be put into the top-level pool > created by the objc module. The top-level pool is never emptied inside > the loop, so it *looks* like the NSArrays are being leaked. Releasing a pool only ever releases a single pool; it will never cause two pools to be released (because a pool can never be autoreleased). There is a bug in this code: > while (1) { > oldpool = pool; > pool = [[NSAutoreleasePool alloc] init]; > [oldpool release]; > > [NSArray array]; > } > > If you run this code you'll notice lots of messages on stderr: It's > complaining that an NSArray instance is leaked due to missing an > autorelease pool. The first pass through, pool is uninitialized.... so, [oldpool release] does nothing. The reason it spews a message over and over is because the loops are not nested correctly. Unrolling the loop yields the following: oldpool = pool; pool = [[NSAutoreleasePool alloc] init]; [oldpool release]; [NSArray array]; oldpool = pool; pool = [[NSAutoreleasePool alloc] init]; [oldpool release]; [NSArray array]; oldpool = pool; pool = [[NSAutoreleasePool alloc] init]; [oldpool release]; [NSArray array]; Like thread looking, pulls are a stack. You shouldn't pull a pool after pushing a new pool on top. That is why you see such loops written as: while(1) { NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init]; [NSArray array]; [p release]; } |
From: Michael T. <li...@mj...> - 2004-04-08 18:59:55
|
On Apr 8, 2004, at 2:20 PM, Ronald Oussoren wrote: > I found what's causing this. Due to the way python and PyObjC work > this code above is equivalent to: > > NSObject* oldpool; > NSObject* pool; > > while (1) { > oldpool = pool; > pool = [[NSAutoreleasePool alloc] init]; > [oldpool release]; > > [NSArray array]; > } > > If you run this code you'll notice lots of messages on stderr: It's > complaining that an NSArray instance is leaked due to missing an > autorelease pool. > > You don't see that in python because the objc module creates a pool > when it is loaded, this is necessary to be able to use Cocoa at all. > ... Hmm, to be more precise it used to be required, I suppose we could > nowadays require the user to create a pool. Something else to look > into. > > I'm not sure why Cocoa behaves like this, but this might be the > intended behaviour. The documentation for NSAutoreleasePool explictly > mentions that pools behave like a stack, I suppose the implementation > doesn't like it when you pop the second highest entry of that stack. I think popping the second highest element on the stack should be fine. That can happen in Objective-C if control leaves a pool's "scope" because of an exception. Popping the outer (lower on the stack) pool should cause it to empty the inner (higher on the stack) pool. So I think what's happening is that the [oldpool release] is popping both pools, causing the NSArray to be put into the top-level pool created by the objc module. The top-level pool is never emptied inside the loop, so it *looks* like the NSArrays are being leaked. --Michael |
From: Ronald O. <ous...@ci...> - 2004-04-08 18:21:02
|
On 8-apr-04, at 17:54, Michael Tsai wrote: > will use memory without bound unless I put in an autorelease pool: > > while 1: > pool = NSAutoreleasePool.alloc().init() > NSArray.array() > pool.release() The release is not necessary, 'pool = None' or 'del pool' also do the trick. See below for an explanation. > > I thought I might be able to get away with: > > while 1: > pool = NSAutoreleasePool.alloc().init() > NSArray.array() I found what's causing this. Due to the way python and PyObjC work this code above is equivalent to: NSObject* oldpool; NSObject* pool; while (1) { oldpool = pool; pool = [[NSAutoreleasePool alloc] init]; [oldpool release]; [NSArray array]; } If you run this code you'll notice lots of messages on stderr: It's complaining that an NSArray instance is leaked due to missing an autorelease pool. You don't see that in python because the objc module creates a pool when it is loaded, this is necessary to be able to use Cocoa at all. ... Hmm, to be more precise it used to be required, I suppose we could nowadays require the user to create a pool. Something else to look into. I'm not sure why Cocoa behaves like this, but this might be the intended behaviour. The documentation for NSAutoreleasePool explictly mentions that pools behave like a stack, I suppose the implementation doesn't like it when you pop the second highest entry of that stack. There's not much we can do about that, other than documenting this fact. I have added some notes to the documentation about this issue. > > because at the start of each loop there are no more Python references > to > the old pool. What happens, though, is that memory use gradually grows, > albeit slower than in the case with just NSArray.array() and no pool. > > Strings behave differently from arrays. This doesn't run in a constant > amount of memory: > > while 1: > NSString.alloc().init() That's because the conversion from Cocoa to Python uses an autoreleased object. That will be changed soon, for other reasons. > > So, it seems that the bridge relieves me from calling retain, > release, and autorelease, but that I still have to make sure that > there is a pool in place and that it is emptied now and then. If the > pool is created in Python, it must be released by calling > pool.release(); Python's GC somehow doesn't do the right thing. Is > this correct? Almost correct. You must make sure that the old pool is gone before you create a new one. pool.release() is unsafe, this should cause serious problems because the bridge will also call -release later on (oddly enough this doesn't cause problems, probably an implementation artifact). I'd use 'del pool' to make it explicit that I'm killing off the old pool before creating the new one. Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Michael T. <li...@mj...> - 2004-04-08 17:26:52
|
On Apr 8, 2004, at 12:59 PM, Ronald Oussoren wrote: > That's correct, the bridge does not (and can not) hide the fact that > an autorelease pool exists. This is not a problem in the normal > use-case for PyObjC: writing GUI programs where you wouldn't use such > a pool in Cocoa either. Right. I was thinking about how in Cocoa I sometimes use extra pools in loops and such, to reduce the maximum memory usage. Looks like I should also do that with Python. > That's very interesting. I'm going to look into this, it's definitely > my intention to make sure that the bridge won't leak memory. > > BTW. What version of PyObjC are you using? 1.1b1 with Python 2.3. > Your example is a method name that is incorrectly recognized as an > initializer, which does have a minor influence on the behaviour of the > bridge, although not one that you should normally run into (the bridge > knows that +alloc returns uninitialized objects and won't -release > such objects unless an initializer method has been called). Thanks for explaining that. I saw from the code that the bridge cared about whether a method was an initializer, but it wasn't obvious to me why. Aside from the possible leaks in the bridge, I guess the documentation is right that it Just Works. :-) --Michael |
From: Ronald O. <ous...@ci...> - 2004-04-08 16:59:34
|
On 8-apr-04, at 17:54, Michael Tsai wrote: > Hi, > > I've been happily using PyObjC to write little scripts for testing > and automation. Now I'd like to use it to write some apps, and so I > want to make sure that I don't leak memory and also have a > reasonable memory high-water mark. The documentation says: > > The `Cocoa libraries`_, and most (if not all) other class > libraries for Objective-C use explicit reference counting to > manage memory. The methods ``retain``, ``release`` and > ``autorelease`` are used to manage these reference counts. You > won't have to manage reference counts in Python, the bridge does > all that work for you. > > Wow, that's nice. However, I'm always a bit skeptical of unexplained > magic, and indeed it doesn't appear to be *quite* that simple (even > ignoring weakrefs). The code: > > while 1: > NSArray.alloc().init() > > does indeed run with a constant amount of memory. However: > > while 1: > NSArray.array() > will use memory without bound unless I put in an autorelease pool: That's correct, the bridge does not (and can not) hide the fact that an autorelease pool exists. This is not a problem in the normal use-case for PyObjC: writing GUI programs where you wouldn't use such a pool in Cocoa either. [... some interesting examples where PyObjC seems to be leaking memory snipped ... ] That's very interesting. I'm going to look into this, it's definitely my intention to make sure that the bridge won't leak memory. BTW. What version of PyObjC are you using? > One more question. It seems that PyObjC uses naming conventions to > determine whether a selector transfers ownership. Does this mean > that bad things will happen if I have an Objective-C class with an > accessor method called -initialValue? That is, will PyObjC fail to > retain the returned value because it thinks this is an -init method? The method that tranfers ownership is named 'alloc', or 'copy'. The initializer doesn't come into play. Your example is a method name that is incorrectly recognized as an initializer, which does have a minor influence on the behaviour of the bridge, although not one that you should normally run into (the bridge knows that +alloc returns uninitialized objects and won't -release such objects unless an initializer method has been called). Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Michael T. <li...@mj...> - 2004-04-08 15:55:46
|
Hi, I've been happily using PyObjC to write little scripts for testing and automation. Now I'd like to use it to write some apps, and so I want to make sure that I don't leak memory and also have a reasonable memory high-water mark. The documentation says: The `Cocoa libraries`_, and most (if not all) other class libraries for Objective-C use explicit reference counting to manage memory. The methods ``retain``, ``release`` and ``autorelease`` are used to manage these reference counts. You won't have to manage reference counts in Python, the bridge does all that work for you. Wow, that's nice. However, I'm always a bit skeptical of unexplained magic, and indeed it doesn't appear to be *quite* that simple (even ignoring weakrefs). The code: while 1: NSArray.alloc().init() does indeed run with a constant amount of memory. However: while 1: NSArray.array() will use memory without bound unless I put in an autorelease pool: while 1: pool =3D NSAutoreleasePool.alloc().init() NSArray.array() pool.release() I thought I might be able to get away with: while 1: pool =3D NSAutoreleasePool.alloc().init() NSArray.array() because at the start of each loop there are no more Python references to the old pool. What happens, though, is that memory use gradually grows, albeit slower than in the case with just NSArray.array() and no pool. Strings behave differently from arrays. This doesn't run in a constant amount of memory: while 1: NSString.alloc().init() although this does: while 1: pool =3D NSAutoreleasePool.alloc().init() NSString.string() pool.release() and so does this: while 1: pool =3D NSAutoreleasePool.alloc().init() NSString.alloc().init() pool.release() So, it seems that the bridge relieves me from calling retain, release, and autorelease, but that I still have to make sure that there is a pool in place and that it is emptied now and then. If the pool is created in Python, it must be released by calling pool.release(); Python's GC somehow doesn't do the right thing. Is this correct? One more question. It seems that PyObjC uses naming conventions to determine whether a selector transfers ownership. Does this mean that bad things will happen if I have an Objective-C class with an accessor method called -initialValue? That is, will PyObjC fail to retain the returned value because it thinks this is an -init method? --Michael |
From: Bob I. <bo...@re...> - 2004-04-07 18:35:09
|
On Apr 7, 2004, at 1:43 PM, Ronald Oussoren wrote: > > On 7-apr-04, at 19:30, Bob Ippolito wrote: > >> >> On Apr 7, 2004, at 1:17 PM, Ronald Oussoren wrote: >> >>> >>> On 7-apr-04, at 19:11, Bob Ippolito wrote: >>>> >>>> Because creating one is harmless, and if you don't create one you >>>> leak memory. >>> >>> Creating one is not harmless if you never release it, you still leak >>> memory without any message about this. >>> >>> We currently leak 1 NSInvocation while creating the >>> NSAutoreleasePool in a new thread, and this is logged. Because it is >>> logged I get nagged anytime I run the unittests, which makes it more >>> likely that this problem will be fixed. >> >> The NSAutoreleasePool goes away whenever the threadstate dict does, >> and that's up to Python to decide. My best guess is that it goes >> away as soon as you call PyGILState_Release, but I have not yet >> looked at the implementation. > > It goes away when the gilstate_counter is 0, which is when you call > PyGILState_Release. > > I'm not sure what happens when you call into ObjC from a thread that > already has a python threadstate (e.g. a thread created using > thread/threading). From a fairly light reading of the source I assume > that the pool won't be released until the thread dies. If ObjC calls into a thread that already has a Python threadstate it will not create an NSAutoreleasePool, if you look closely at the code you can see that it will only execute that code if PyGILState_Ensure is creating a new threadstate. As far as this code is concerned, there are 3 kinds of threads: 1) The main thread. It already has a global NSAutoreleasePool (by PyObjC initialization) and a Python threadstate. When it gets a callback from ObjC, since it has a threadstate already, it just does PyGILState_Ensure(). 2) A Python-created thread. You must create an NSAutoreleasePool yourself if you create a python thread and then start calling into ObjC from it. Since it has a threadstate already, it just does PyGILState_Ensure(). 3) An ObjC-created thread. These do not have a threadstate already, so it will do PyGILState_Ensure() and create a NSAutoreleasePool which will be collected at PyGILState_Release() time. -bob |
From: b.bum <bb...@ma...> - 2004-04-07 18:22:19
|
On Apr 7, 2004, at 6:03 AM, Ronald Oussoren wrote: > With the arrival of the new binding examples I finally spent some time > to convert an existing application to Cocoa bindings. I immediately > ran into a problem that can easily be reproduced using the > TableModelWithSearch example: > > 1) Open the NIB > 2) Change the attributes for the table view: deselect 'allow empty > selection' > 3) Add a text field and bind that to the 'name' key of the 'selection' > of the NSArrayController > > All seems to be well when you run the application, the name of the > selected row is also shown in the text field, even when you select > another row. However, when you enter a query in the search box, the > text field remains empty (it contains 'no entry selected') even though > the table view does contain a selected row. > > Do you have any idea what may be wrong (me, PyObjC, Cocoa)? A Cocoa Bindings bug. Filed as #3615180. I verified the behavior in a handy ObjC app I had laying around. Thanks! b.bum |
From: Ronald O. <ous...@ci...> - 2004-04-07 17:43:37
|
On 7-apr-04, at 19:30, Bob Ippolito wrote: > > On Apr 7, 2004, at 1:17 PM, Ronald Oussoren wrote: > >> >> On 7-apr-04, at 19:11, Bob Ippolito wrote: >>> >>> Because creating one is harmless, and if you don't create one you >>> leak memory. >> >> Creating one is not harmless if you never release it, you still leak >> memory without any message about this. >> >> We currently leak 1 NSInvocation while creating the NSAutoreleasePool >> in a new thread, and this is logged. Because it is logged I get >> nagged anytime I run the unittests, which makes it more likely that >> this problem will be fixed. > > The NSAutoreleasePool goes away whenever the threadstate dict does, > and that's up to Python to decide. My best guess is that it goes away > as soon as you call PyGILState_Release, but I have not yet looked at > the implementation. It goes away when the gilstate_counter is 0, which is when you call PyGILState_Release. I'm not sure what happens when you call into ObjC from a thread that already has a python threadstate (e.g. a thread created using thread/threading). From a fairly light reading of the source I assume that the pool won't be released until the thread dies. > > +[NSThread detachNewThreadSelector:toTarget:withObject:] leaks memory > without these autorelease pools because "primitive" types such as > NSString will cause an autorelease to happen while creating a python > shadow type (like pyobjc_unicode) before any code gets executed in the > new thread. Hmm, I hadn't though about those API's. Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Bob I. <bo...@re...> - 2004-04-07 17:26:40
|
On Apr 7, 2004, at 1:17 PM, Ronald Oussoren wrote: > > On 7-apr-04, at 19:11, Bob Ippolito wrote: >> >> Because creating one is harmless, and if you don't create one you >> leak memory. > > Creating one is not harmless if you never release it, you still leak > memory without any message about this. > > We currently leak 1 NSInvocation while creating the NSAutoreleasePool > in a new thread, and this is logged. Because it is logged I get nagged > anytime I run the unittests, which makes it more likely that this > problem will be fixed. The NSAutoreleasePool goes away whenever the threadstate dict does, and that's up to Python to decide. My best guess is that it goes away as soon as you call PyGILState_Release, but I have not yet looked at the implementation. +[NSThread detachNewThreadSelector:toTarget:withObject:] leaks memory without these autorelease pools because "primitive" types such as NSString will cause an autorelease to happen while creating a python shadow type (like pyobjc_unicode) before any code gets executed in the new thread. -bob |
From: Ronald O. <ous...@ci...> - 2004-04-07 17:17:48
|
On 7-apr-04, at 19:11, Bob Ippolito wrote: > > Because creating one is harmless, and if you don't create one you leak > memory. Creating one is not harmless if you never release it, you still leak memory without any message about this. We currently leak 1 NSInvocation while creating the NSAutoreleasePool in a new thread, and this is logged. Because it is logged I get nagged anytime I run the unittests, which makes it more likely that this problem will be fixed. Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Bob I. <bo...@re...> - 2004-04-07 17:07:23
|
On Apr 7, 2004, at 6:18 AM, Ronald Oussoren wrote: > > On 7-apr-04, at 11:21, Bob Ippolito wrote: > >> >> On Apr 7, 2004, at 3:21 AM, Ronald Oussoren wrote: >> >>> >>> On 6-apr-04, at 18:32, Bob Ippolito wrote: >>> >>>> Update of /cvsroot/pyobjc/pyobjc/Modules/objc >>>> In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21862 >>>> >>>> Modified Files: >>>> objc_util.h objc_util.m >>>> Log Message: >>>> move the threadstate autoreleasepool key name into a macro so that >>>> it can be checked when calling _into_ ObjC at some point so that >>>> python >>>> threads can create an NSAutoreleasePool and call +[NSThread >>>> currentThread] >>>> (not necessarily in that order). >>> >>> I'm probably pretty dense (no coffee yet), but why is >>> PyObjCGILState_Ensure necessary at all? >>> >>> This seems to create an arbitrary NSAutoreleasePool the first time >>> someone calls into python from ObjC, and that might not play nicely >>> with existing pool (e.g. what if the calling code already created a >>> pool and later releases that to clean up memory, our pool might >>> contain objects that should be cleaned up). >>> >>> It should be possible to create a new autorelease pool inside a >>> thread before doing anything else with Cocoa. >> >> That is exactly what it is doing. If Python has never seen this >> thread before, and we are in an objc method stub, then assume that we >> need to create an NSAutoreleasePool. It only happens for threads >> that have no threadstate yet. > > But why create an autorelease pool? The thread may be a perfectly > valid thread that already has an autorelease pool, such as internal > background threads used by Cocoa. Because creating one is harmless, and if you don't create one you leak memory. -bob |
From: Ronald O. <ous...@ci...> - 2004-04-07 13:03:44
|
With the arrival of the new binding examples I finally spent some time to convert an existing application to Cocoa bindings. I immediately ran into a problem that can easily be reproduced using the TableModelWithSearch example: 1) Open the NIB 2) Change the attributes for the table view: deselect 'allow empty selection' 3) Add a text field and bind that to the 'name' key of the 'selection' of the NSArrayController All seems to be well when you run the application, the name of the selected row is also shown in the text field, even when you select another row. However, when you enter a query in the search box, the text field remains empty (it contains 'no entry selected') even though the table view does contain a selected row. Do you have any idea what may be wrong (me, PyObjC, Cocoa)? Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Ronald O. <ous...@ci...> - 2004-04-07 10:18:13
|
On 7-apr-04, at 11:21, Bob Ippolito wrote: > > On Apr 7, 2004, at 3:21 AM, Ronald Oussoren wrote: > >> >> On 6-apr-04, at 18:32, Bob Ippolito wrote: >> >>> Update of /cvsroot/pyobjc/pyobjc/Modules/objc >>> In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21862 >>> >>> Modified Files: >>> objc_util.h objc_util.m >>> Log Message: >>> move the threadstate autoreleasepool key name into a macro so that >>> it can be checked when calling _into_ ObjC at some point so that >>> python >>> threads can create an NSAutoreleasePool and call +[NSThread >>> currentThread] >>> (not necessarily in that order). >> >> I'm probably pretty dense (no coffee yet), but why is >> PyObjCGILState_Ensure necessary at all? >> >> This seems to create an arbitrary NSAutoreleasePool the first time >> someone calls into python from ObjC, and that might not play nicely >> with existing pool (e.g. what if the calling code already created a >> pool and later releases that to clean up memory, our pool might >> contain objects that should be cleaned up). >> >> It should be possible to create a new autorelease pool inside a >> thread before doing anything else with Cocoa. > > That is exactly what it is doing. If Python has never seen this > thread before, and we are in an objc method stub, then assume that we > need to create an NSAutoreleasePool. It only happens for threads that > have no threadstate yet. But why create an autorelease pool? The thread may be a perfectly valid thread that already has an autorelease pool, such as internal background threads used by Cocoa. Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Bob I. <bo...@re...> - 2004-04-07 09:17:15
|
On Apr 7, 2004, at 3:21 AM, Ronald Oussoren wrote: > > On 6-apr-04, at 18:32, Bob Ippolito wrote: > >> Update of /cvsroot/pyobjc/pyobjc/Modules/objc >> In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21862 >> >> Modified Files: >> objc_util.h objc_util.m >> Log Message: >> move the threadstate autoreleasepool key name into a macro so that >> it can be checked when calling _into_ ObjC at some point so that >> python >> threads can create an NSAutoreleasePool and call +[NSThread >> currentThread] >> (not necessarily in that order). > > I'm probably pretty dense (no coffee yet), but why is > PyObjCGILState_Ensure necessary at all? > > This seems to create an arbitrary NSAutoreleasePool the first time > someone calls into python from ObjC, and that might not play nicely > with existing pool (e.g. what if the calling code already created a > pool and later releases that to clean up memory, our pool might > contain objects that should be cleaned up). > > It should be possible to create a new autorelease pool inside a thread > before doing anything else with Cocoa. That is exactly what it is doing. If Python has never seen this thread before, and we are in an objc method stub, then assume that we need to create an NSAutoreleasePool. It only happens for threads that have no threadstate yet. -bob |
From: Ronald O. <ous...@ci...> - 2004-04-07 07:21:35
|
On 6-apr-04, at 18:32, Bob Ippolito wrote: > Update of /cvsroot/pyobjc/pyobjc/Modules/objc > In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21862 > > Modified Files: > objc_util.h objc_util.m > Log Message: > move the threadstate autoreleasepool key name into a macro so that > it can be checked when calling _into_ ObjC at some point so that python > threads can create an NSAutoreleasePool and call +[NSThread > currentThread] > (not necessarily in that order). I'm probably pretty dense (no coffee yet), but why is PyObjCGILState_Ensure necessary at all? This seems to create an arbitrary NSAutoreleasePool the first time someone calls into python from ObjC, and that might not play nicely with existing pool (e.g. what if the calling code already created a pool and later releases that to clean up memory, our pool might contain objects that should be cleaned up). It should be possible to create a new autorelease pool inside a thread before doing anything else with Cocoa. Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |