Skip to content

Commit

Permalink
Return a new reference when iterating over a collection. (#1080)
Browse files Browse the repository at this point in the history
# Description
Return a new reference when iterating over a collection and ensure that
it is decreased again when the instances goes out of scope (memory
managed by dlite).

## Type of change
- [x] Bug fix & code cleanup
- [ ] New feature
- [ ] Documentation update
- [ ] Test update
  • Loading branch information
francescalb authored Jan 27, 2025
2 parents eda4e8b + c44e8d9 commit 2702cf0
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
5 changes: 3 additions & 2 deletions bindings/python/dlite-collection.i
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,12 @@ struct _DLiteCollection {
free($self);
}

%newobject next;
%feature("docstring",
"Returns a reference to next matching relation."
"Returns a new reference next instance in the collection."
) next;
const struct _DLiteInstance *next(void) {
return dlite_collection_next($self->coll, &$self->state);
return dlite_collection_next_new($self->coll, &$self->state);
}

%feature("docstring",
Expand Down
1 change: 1 addition & 0 deletions bindings/python/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(tests
test_python_bindings
test_collection
test_collection_load
test_collection_refcount
test_entity
test_factory
test_misc
Expand Down
64 changes: 64 additions & 0 deletions bindings/python/tests/test_collection_refcount.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Test that the reference counting of instances added to a collection
is working properly.
The test ensures that the reference count is increased when new
references are created and decreased when the references goes out of
scope or are deleted.
"""
import dlite


def add_blob(coll):
"""Adds two blob instances to the collection."""
Blob = dlite.get_instance("http://onto-ns.com/meta/0.1/Blob")
blob = Blob([10])
blob2 = Blob([2])
coll.add("blob", blob)
coll.add("blob2", blob2)


def use_blob(coll):
"""Access instance using the Collection.get() method."""
blob = coll.get("blob")
assert blob._refcount == 3 # coll, local blob, global blob


def use_blob2(coll):
"""Access instances using the Collection.get_instances() method."""
blob, blob2 = coll.get_instances()
assert blob._refcount == 3 # coll, local blob, global blob
assert blob2._refcount == 2 # coll, local blob2


coll = dlite.Collection()
assert coll._refcount == 1

add_blob(coll)
assert coll._refcount == 1

blob = coll.get("blob")
assert blob._refcount == 2 # coll, blob

use_blob(coll)
use_blob(coll)
assert coll._refcount == 1
assert blob._refcount == 2 # coll, blob

use_blob2(coll)
assert coll._refcount == 1
assert blob._refcount == 2 # coll, blob

use_blob2(coll)
assert blob._refcount == 2 # coll, blob


insts = list(coll.get_instances())
inst = insts[0]
assert inst._refcount == 3 # inst, blob, coll

del coll
assert inst._refcount == 2 # inst, blob

del blob
assert inst._refcount == 1 # inst

0 comments on commit 2702cf0

Please sign in to comment.