Use hash for Collection.gobject lookup, speedup object linking #104553
|
@ -67,8 +67,10 @@ static bool collection_child_remove(Collection *parent, Collection *collection);
|
|||
static bool collection_object_add(
|
||||
Main *bmain, Collection *collection, Object *ob, int flag, const bool add_us);
|
||||
|
||||
static void collection_object_remove_no_gobject_hash(
|
||||
Main *bmain, Collection *collection, Object *ob, CollectionObject *cob, const bool free_us);
|
||||
static void collection_object_remove_no_gobject_hash(Main *bmain,
|
||||
Collection *collection,
|
||||
CollectionObject *cob,
|
||||
const bool free_us);
|
||||
static bool collection_object_remove(Main *bmain,
|
||||
Collection *collection,
|
||||
Object *ob,
|
||||
|
@ -565,7 +567,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
|
|||
/* Remove child objects. */
|
||||
CollectionObject *cob = collection->gobject.first;
|
||||
while (cob != NULL) {
|
||||
collection_object_remove_no_gobject_hash(bmain, collection, cob->ob, cob, true);
|
||||
collection_object_remove_no_gobject_hash(bmain, collection, cob, true);
|
||||
cob = collection->gobject.first;
|
||||
}
|
||||
|
||||
|
@ -594,7 +596,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
|
|||
}
|
||||
|
||||
/* Remove child object. */
|
||||
collection_object_remove_no_gobject_hash(bmain, collection, cob->ob, cob, true);
|
||||
collection_object_remove_no_gobject_hash(bmain, collection, cob, true);
|
||||
cob = collection->gobject.first;
|
||||
}
|
||||
}
|
||||
|
@ -1144,12 +1146,13 @@ static bool collection_object_add(
|
|||
/**
|
||||
* A version of #collection_object_remove that does not handle `collection->runtime.gobject_hash`,
|
||||
* Either the caller must have removed the object from the hash or the hash may be NULL.
|
||||
ideasman42 marked this conversation as resolved
|
||||
*
|
||||
* \note in rare cases `cob->ob != ob`, so both arguments need to be passed in.
|
||||
*/
|
||||
static void collection_object_remove_no_gobject_hash(
|
||||
Main *bmain, Collection *collection, Object *ob, CollectionObject *cob, const bool free_us)
|
||||
static void collection_object_remove_no_gobject_hash(Main *bmain,
|
||||
Collection *collection,
|
||||
ideasman42 marked this conversation as resolved
Bastien Montagne
commented
This call can be removed (see comment in This call can be removed (see comment in `collection_gobject_hash_ensure`).
|
||||
CollectionObject *cob,
|
||||
const bool free_us)
|
||||
{
|
||||
Object *ob = cob->ob;
|
||||
BLI_freelinkN(&collection->gobject, cob);
|
||||
ideasman42 marked this conversation as resolved
Bastien Montagne
commented
Couldn't this use instead Couldn't this use instead `cob = BLI_ghash_popkey(collection->runtime.gobject_hash, ob, NULL);`? Then there is no need for an extra lookup below in the call to `collection_gobject_hash_remove_object(collection, ob);`
Campbell Barton
commented
Yep, good idea. Yep, good idea.
|
||||
BKE_collection_object_cache_free(collection);
|
||||
|
||||
|
@ -1174,7 +1177,7 @@ static bool collection_object_remove(Main *bmain,
|
|||
if (cob == NULL) {
|
||||
return false;
|
||||
}
|
||||
collection_object_remove_no_gobject_hash(bmain, collection, ob, cob, free_us);
|
||||
collection_object_remove_no_gobject_hash(bmain, collection, cob, free_us);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
This is something very surprising to me. I am not sure why this is the case, but it definitely asks to be written down in the comment here.
From quick look around the
collection_object_remove_no_gobject_hash
is either called with ob=cob->ob, and in other cases is called with a result of ghash lookup. The latter one is done aftercollection_gobject_hash_ensure
which seems to assert thatcob->ob
is the same asob
.In general, always document such cases for the future reader. It saves a lot of time (for both current review, and future you and future developers looking into the code).
This must have been a use-after-free mistake, double checked with the
ob
argument removed and the tests now pass.