Skip to content

Commit 4648113

Browse files
Weak store: close weak store on store close #9
1 parent 62836a0 commit 4648113

File tree

5 files changed

+39
-21
lines changed

5 files changed

+39
-21
lines changed

objectbox/lib/src/native/store.dart

+26-10
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,13 @@ class Store {
6060
/// A list of observers of the Store.close() event.
6161
final _onClose = <dynamic, void Function()>{};
6262

63-
/// If weak and calling [close] does not try to close the native Store and
63+
/// If true and calling [close] will also close the native Store and
6464
/// remove [_absoluteDirectoryPath] from [_openStoreDirectories].
65-
final bool _weak;
65+
final bool _closesNativeStore;
66+
67+
/// If true and calling [close] will also close a cached WeakStore, if one was
68+
/// created for this store.
69+
final bool _closesWeakStore;
6670

6771
/// Default value for string query conditions [caseSensitive] argument.
6872
final bool _queriesCaseSensitiveDefault;
@@ -153,7 +157,8 @@ class Store {
153157
bool queriesCaseSensitiveDefault = true,
154158
String? macosApplicationGroup})
155159
: _defs = modelDefinition,
156-
_weak = false,
160+
_closesNativeStore = true,
161+
_closesWeakStore = true,
157162
_queriesCaseSensitiveDefault = queriesCaseSensitiveDefault,
158163
directoryPath = _safeDirectoryPath(directory),
159164
_absoluteDirectoryPath =
@@ -269,8 +274,10 @@ class Store {
269274
/// ```
270275
Store.fromReference(this._defs, this._reference,
271276
{bool queriesCaseSensitiveDefault = true})
272-
// must not close the same native store twice so [_weak]=true
273-
: _weak = true,
277+
:
278+
// Must not close native store twice, only original store is allowed to.
279+
_closesNativeStore = false,
280+
_closesWeakStore = true,
274281
directoryPath = '',
275282
_absoluteDirectoryPath = '',
276283
_queriesCaseSensitiveDefault = queriesCaseSensitiveDefault {
@@ -297,7 +304,9 @@ class Store {
297304
/// See [_clone] for details.
298305
Store._minimal(int ptrAddress, {bool queriesCaseSensitiveDefault = true})
299306
: _defs = null,
300-
_weak = false,
307+
_closesNativeStore = true,
308+
// Minimal store does not have a model, so could not create Weak Store.
309+
_closesWeakStore = false,
301310
directoryPath = '',
302311
_absoluteDirectoryPath = '',
303312
_queriesCaseSensitiveDefault = queriesCaseSensitiveDefault {
@@ -322,8 +331,8 @@ class Store {
322331
/// is closed (e.g. when the app exits).
323332
Store.attach(this._defs, String? directoryPath,
324333
{bool queriesCaseSensitiveDefault = true})
325-
// _weak = false so store can be closed.
326-
: _weak = false,
334+
: _closesNativeStore = true,
335+
_closesWeakStore = true,
327336
_queriesCaseSensitiveDefault = queriesCaseSensitiveDefault,
328337
directoryPath = _safeDirectoryPath(directoryPath),
329338
_absoluteDirectoryPath =
@@ -368,7 +377,9 @@ class Store {
368377
Store._fromWeakStore(
369378
StoreConfiguration configuration, Pointer<OBX_weak_store> weakStorePtr)
370379
: _defs = configuration.modelDefinition,
371-
_weak = false,
380+
_closesNativeStore = true,
381+
// This Store was obtained from a WeakStore, do not close it.
382+
_closesWeakStore = false,
372383
directoryPath = configuration.directoryPath,
373384
_absoluteDirectoryPath = '',
374385
_queriesCaseSensitiveDefault =
@@ -499,7 +510,12 @@ class Store {
499510

500511
_reader.clear();
501512

502-
if (!_weak) {
513+
if (_closesWeakStore) {
514+
// If there is a weak store reference for this, close it as well.
515+
WeakStore.get(configuration())?.close();
516+
}
517+
518+
if (_closesNativeStore) {
503519
_openStoreDirectories.remove(_absoluteDirectoryPath);
504520
final errors = List.filled(2, 0);
505521
if (_cFinalizer != nullptr) {

objectbox/lib/src/native/weak_store.dart

+8-3
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,20 @@ import 'bindings/helpers.dart';
1414
/// // Do Store operations.
1515
/// store.close();
1616
/// // Optional: if not longer needed, free the weak store reference.
17+
/// // Note this is done automatically if the underlying store is closed.
1718
/// weakStore.close();
1819
/// ```
1920
class WeakStore {
20-
// TODO All these should be closed when the isolate is shut down.
2121
/// Holds previously constructed weak stores by store ID for this isolate.
2222
static final _weakStoresCacheOfIsolate = <int, WeakStore>{};
2323

24+
/// Based on the ID get an existing weak store, or null if there is none.
25+
static WeakStore? get(StoreConfiguration configuration) =>
26+
_weakStoresCacheOfIsolate[configuration.id];
27+
2428
/// Based on the ID get an existing weak store, or create a new one.
25-
static WeakStore get(StoreConfiguration configuration) {
26-
final existingWeakStore = _weakStoresCacheOfIsolate[configuration.id];
29+
static WeakStore getOrCreate(StoreConfiguration configuration) {
30+
final existingWeakStore = get(configuration);
2731
if (existingWeakStore == null) {
2832
final newWeakStore = WeakStore(configuration);
2933
_weakStoresCacheOfIsolate[configuration.id] = newWeakStore;
@@ -61,6 +65,7 @@ class WeakStore {
6165
if (weakStorePtr == null) return;
6266
C.weak_store_free(weakStorePtr);
6367
_weakStorePtr = null;
68+
_weakStoresCacheOfIsolate.remove(configuration.id);
6469
}
6570

6671
/// Obtains a Store from a weak Store for short-time use.

objectbox/lib/src/relations/to_many.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ class _ToManyStoreAccess<EntityT, OwningEntityT> {
351351

352352
factory _ToManyStoreAccess(
353353
_ToManyStoreConfiguration<EntityT, OwningEntityT> configuration) {
354-
final weakStore = WeakStore.get(configuration._storeConfiguration);
354+
final weakStore = WeakStore.getOrCreate(configuration._storeConfiguration);
355355
final store = weakStore.lock();
356356
return _ToManyStoreAccess._fromFactory(configuration, store);
357357
}

objectbox/lib/src/relations/to_one.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ class _ToOneStoreAccess<EntityT> {
250250
Store _store;
251251

252252
factory _ToOneStoreAccess(_ToOneStoreConfiguration<EntityT> configuration) {
253-
final weakStore = WeakStore.get(configuration._storeConfiguration);
253+
final weakStore = WeakStore.getOrCreate(configuration._storeConfiguration);
254254
final store = weakStore.lock();
255255
return _ToOneStoreAccess._fromFactory(configuration, store);
256256
}

objectbox/test/store_test.dart

+3-6
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void main() {
7979
expect(storeConfig.id, isNot(0));
8080

8181
// Create weak store by ID.
82-
var weakStore = WeakStore.get(storeConfig);
82+
var weakStore = WeakStore.getOrCreate(storeConfig);
8383

8484
// Obtain strong reference.
8585
final store = weakStore.lock();
@@ -97,11 +97,8 @@ void main() {
9797
env.closeAndDelete();
9898
expect(
9999
() => weakStore.lock(),
100-
throwsA(predicate(
101-
(ObjectBoxException e) => e.message == "failed to create store")));
102-
103-
// Clean up.
104-
weakStore.close();
100+
throwsA(
101+
predicate((StateError e) => e.message == "Weak store is closed")));
105102

106103
// Re-open underlying store, store ID should have changed.
107104
final env2 = TestEnv("store");

0 commit comments

Comments
 (0)