| 72 | } |
| 73 | |
| 74 | void WrapperGarbageCollector::collect() |
| 75 | { |
| 76 | std::vector<PyObject*> toCollect; |
| 77 | |
| 78 | do |
| 79 | { |
| 80 | toCollect.clear(); |
| 81 | for( InstanceMap::iterator it = g_refCountedToPyObject.begin(); it!=g_refCountedToPyObject.end(); ) |
| 82 | { |
| 83 | InstanceMap::iterator nextIt = it; nextIt++; |
| 84 | if( it->first->refCount()==1 ) |
| 85 | { |
| 86 | if( it->second->ob_refcnt==1 ) |
| 87 | { |
| 88 | // add to the list of objects to destroy |
| 89 | toCollect.push_back( it->second ); |
| 90 | |
| 91 | // Make sure the object is removed from the list before the next loop, which |
| 92 | // destroys it. This is because Py_DECREF() can run arbitrary, multithreaded python |
| 93 | // code, (especially if the python object has a __del__ method) which may create |
| 94 | // WrapperGarbageCollector objects, effectively making this method recurse. It's also |
| 95 | // possible that this python code can call collect() directly. Removing the object |
| 96 | // from the list here avoids double deallocation. |
| 97 | g_refCountedToPyObject.erase( it ); |
| 98 | } |
| 99 | } |
| 100 | it = nextIt; |
| 101 | } |
| 102 | |
| 103 | for (std::vector<PyObject*>::const_iterator jt = toCollect.begin(); jt != toCollect.end(); ++jt) |
| 104 | { |
| 105 | // decrement the reference count for the python object, which will trigger the destruction |
| 106 | // of the WrapperGarbageCollector object. |
| 107 | Py_DECREF( *jt ); |
| 108 | } |
| 109 | } while( toCollect.size() ); |
| 110 | |
| 111 | g_allocCount = 0; |
| 112 | /// Scale the collection threshold with the number of objects to be collected, otherwise we get |
| 113 | /// awful (quadratic?) behaviour when creating large numbers of objects. |
| 114 | /// \todo Revisit this with a better thought out strategy, perhaps like python's own garbage collector. |
| 115 | g_allocThreshold = std::max( size_t( 50 ), g_refCountedToPyObject.size() ); |
| 116 | } |
| 117 | |
| 118 | PyObject *WrapperGarbageCollector::pyObject( IECore::RefCounted *refCountedObject ) |
| 119 | { |