4
4
package io .deephaven .engine .table .impl .indexer ;
5
5
6
6
import com .google .common .collect .Sets ;
7
+ import io .deephaven .base .reference .HardSimpleReference ;
8
+ import io .deephaven .base .reference .SimpleReference ;
9
+ import io .deephaven .base .reference .WeakSimpleReference ;
7
10
import io .deephaven .base .verify .Require ;
8
11
import io .deephaven .engine .liveness .LivenessScopeStack ;
9
12
import io .deephaven .engine .rowset .RowSet ;
20
23
import org .jetbrains .annotations .NotNull ;
21
24
import org .jetbrains .annotations .Nullable ;
22
25
23
- import java .lang .ref .Reference ;
24
- import java .lang .ref .WeakReference ;
25
26
import java .util .*;
26
27
import java .util .concurrent .atomic .AtomicReferenceFieldUpdater ;
27
28
import java .util .function .Predicate ;
@@ -390,6 +391,27 @@ private static DataIndex validateAndManageCachedDataIndex(@Nullable final DataIn
390
391
return dataIndex ;
391
392
}
392
393
394
+ /**
395
+ * Interface for {@link DataIndex} implementations that may opt into strong reachability within the DataIndexer's
396
+ * cache.
397
+ */
398
+ public interface RetainableDataIndex extends DataIndex {
399
+
400
+ /**
401
+ * @return Whether {@code this} should be strongly held (if {@link #addDataIndex(DataIndex) added}) to maintain
402
+ * reachability
403
+ */
404
+ boolean shouldRetain ();
405
+
406
+ /**
407
+ * @return Whether {@code dataIndex} should be strongly held (if {@link #addDataIndex(DataIndex) added}) to
408
+ * maintain reachability
409
+ */
410
+ static boolean shouldRetain (@ NotNull final DataIndex dataIndex ) {
411
+ return dataIndex instanceof RetainableDataIndex && ((RetainableDataIndex ) dataIndex ).shouldRetain ();
412
+ }
413
+ }
414
+
393
415
/**
394
416
* Node structure for our multi-level cache of indexes.
395
417
*/
@@ -399,14 +421,14 @@ private static class DataIndexCache {
399
421
@ SuppressWarnings ("rawtypes" )
400
422
private static final AtomicReferenceFieldUpdater <DataIndexCache , Map > DESCENDANT_CACHES_UPDATER =
401
423
AtomicReferenceFieldUpdater .newUpdater (DataIndexCache .class , Map .class , "descendantCaches" );
402
- private static final Reference <DataIndex > MISSING_INDEX_REFERENCE = new WeakReference <>(null );
424
+ private static final SimpleReference <DataIndex > MISSING_INDEX_REFERENCE = new WeakSimpleReference <>(null );
403
425
404
426
/** The sub-indexes below this level. */
405
427
@ SuppressWarnings ("FieldMayBeFinal" )
406
428
private volatile Map <ColumnSource <?>, DataIndexCache > descendantCaches = EMPTY_DESCENDANT_CACHES ;
407
429
408
430
/** A reference to the index at this level. Note that there will never be an index at the "root" level. */
409
- private volatile Reference <DataIndex > dataIndexReference = MISSING_INDEX_REFERENCE ;
431
+ private volatile SimpleReference <DataIndex > dataIndexReference = MISSING_INDEX_REFERENCE ;
410
432
411
433
private DataIndexCache () {}
412
434
@@ -509,7 +531,9 @@ private boolean add(@NotNull final List<ColumnSource<?>> keyColumns, @NotNull fi
509
531
// noinspection SynchronizationOnLocalVariableOrMethodParameter
510
532
synchronized (cache ) {
511
533
if (!isValidAndLive (cache .dataIndexReference .get ())) {
512
- cache .dataIndexReference = new WeakReference <>(dataIndex );
534
+ cache .dataIndexReference = RetainableDataIndex .shouldRetain (dataIndex )
535
+ ? new HardSimpleReference <>(dataIndex )
536
+ : new WeakSimpleReference <>(dataIndex );
513
537
return true ;
514
538
}
515
539
}
@@ -544,7 +568,7 @@ private DataIndex computeIfAbsent(
544
568
// managed by the appropriate scope for the caller's own use. Further validation is deferred
545
569
// as in add.
546
570
dataIndex = dataIndexFactory .get ();
547
- cache .dataIndexReference = new WeakReference <>(dataIndex );
571
+ cache .dataIndexReference = new WeakSimpleReference <>(dataIndex );
548
572
}
549
573
}
550
574
}
0 commit comments