Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,33 +126,24 @@ protected void decrementCounterRight(ExistsCounter<LeftTuple_> counter) {
} // Else do not even propagate an update
}

// Prepends tracker into the left tuple's hidden intrusive tracker list.
// The left tuple's store at inputStoreIndexLeftTrackerList holds the list head (null = empty).
private void linkLeft(FilteringTracker<LeftTuple_> tracker) {
var leftTuple = tracker.counter.leftTuple;
FilteringTracker<LeftTuple_> head = leftTuple.getStore(inputStoreIndexLeftTrackerList);
tracker.leftNext = head;
if (head != null) {
head.leftPrev = tracker;
// Clears the left tracker list rooted at leftTuple's inputStoreIndexLeftTrackerList slot,
// cross-removing each tracker from its right tuple's hidden list. No-op when !isFiltering.
// Walk safety: removeFromRight only touches right-side links, so leftNext is stable across the call.
protected void clearLeftTrackerList(LeftTuple_ leftTuple) {
if (!isFiltering) {
return;
}
leftTuple.setStore(inputStoreIndexLeftTrackerList, tracker);
}

// Prepends tracker into the right tuple's hidden intrusive tracker list.
// The right tuple's store at inputStoreIndexRightTrackerList holds the list head (null = empty).
private void linkRight(FilteringTracker<LeftTuple_> tracker) {
var rightTuple = tracker.rightTuple;
FilteringTracker<LeftTuple_> head = rightTuple.getStore(inputStoreIndexRightTrackerList);
tracker.rightNext = head;
if (head != null) {
head.rightPrev = tracker;
FilteringTracker<LeftTuple_> tracker = leftTuple.removeStore(inputStoreIndexLeftTrackerList);
while (tracker != null) {
var next = tracker.leftNext;
removeRight(tracker);
tracker = next;
}
rightTuple.setStore(inputStoreIndexRightTrackerList, tracker);
}

// Splices tracker out of its right tuple's hidden list (used when clearing from the left side).
// Nulls the tracker's right links; if tracker is the head, updates the right tuple's slot.
private void removeFromRight(FilteringTracker<LeftTuple_> tracker) {
private void removeRight(FilteringTracker<LeftTuple_> tracker) {
var prev = tracker.rightPrev;
var next = tracker.rightNext;
if (prev != null) {
Expand All @@ -168,9 +159,22 @@ private void removeFromRight(FilteringTracker<LeftTuple_> tracker) {
tracker.rightNext = null;
}

// Clears the right tracker list rooted at rightTuple's inputStoreIndexRightTrackerList slot,
// decrementing each counter and cross-removing each tracker from its left tuple's hidden list.
// Walk safety: removeFromLeft only touches left-side links, so rightNext is stable across the call.
protected void clearRightTrackerList(UniTuple<Right_> rightTuple) {
FilteringTracker<LeftTuple_> tracker = rightTuple.removeStore(inputStoreIndexRightTrackerList);
while (tracker != null) {
var next = tracker.rightNext;
decrementCounterRight(tracker.counter);
removeLeft(tracker);
tracker = next;
}
}

// Splices tracker out of its left tuple's hidden list (used when clearing from the right side).
// Nulls the tracker's left links; if tracker is the head, updates the left tuple's slot.
private void removeFromLeft(FilteringTracker<LeftTuple_> tracker) {
private void removeLeft(FilteringTracker<LeftTuple_> tracker) {
var prev = tracker.leftPrev;
var next = tracker.leftNext;
if (prev != null) {
Expand All @@ -186,44 +190,47 @@ private void removeFromLeft(FilteringTracker<LeftTuple_> tracker) {
tracker.leftNext = null;
}

// Clears the left tracker list rooted at leftTuple's inputStoreIndexLeftTrackerList slot,
// cross-removing each tracker from its right tuple's hidden list. No-op when !isFiltering.
// Walk safety: removeFromRight only touches right-side links, so leftNext is stable across the call.
protected void clearLeftTrackerList(LeftTuple_ leftTuple) {
if (!isFiltering) {
protected void updateCounterLeft(ExistsCounter<LeftTuple_> counter, UniTuple<Right_> rightTuple) {
if (!rightTuple.getState().isActive()) {
// The mirror image of updateCounterRight(...): here the right tuple is the retracting one,
// which happens when the right input's node sits in a higher layer than the left input's,
// so the left's inserts and updates are delivered before the right's retracts are.
// Skipping is safe, as the pending retract will not have a tracker to clear for this pair.
return;
}
FilteringTracker<LeftTuple_> tracker = leftTuple.removeStore(inputStoreIndexLeftTrackerList);
while (tracker != null) {
var next = tracker.leftNext;
removeFromRight(tracker);
tracker = next;
if (testFiltering(counter.leftTuple, rightTuple)) {
counter.countRight++;
var tracker = new FilteringTracker<>(counter, rightTuple);
linkLeft(tracker);
linkRight(tracker);
}
}

// Clears the right tracker list rooted at rightTuple's inputStoreIndexRightTrackerList slot,
// decrementing each counter and cross-removing each tracker from its left tuple's hidden list.
// Walk safety: removeFromLeft only touches left-side links, so rightNext is stable across the call.
protected void clearRightTrackerList(UniTuple<Right_> rightTuple) {
FilteringTracker<LeftTuple_> tracker = rightTuple.removeStore(inputStoreIndexRightTrackerList);
while (tracker != null) {
var next = tracker.rightNext;
decrementCounterRight(tracker.counter);
removeFromLeft(tracker);
tracker = next;
// Prepends tracker into the left tuple's hidden intrusive tracker list.
// The left tuple's store at inputStoreIndexLeftTrackerList holds the list head (null = empty).
private void linkLeft(FilteringTracker<LeftTuple_> tracker) {
var leftTuple = tracker.counter.leftTuple;
FilteringTracker<LeftTuple_> head = leftTuple.getStore(inputStoreIndexLeftTrackerList);
tracker.leftNext = head;
if (head != null) {
head.leftPrev = tracker;
}
leftTuple.setStore(inputStoreIndexLeftTrackerList, tracker);
}

protected void updateCounterFromLeft(ExistsCounter<LeftTuple_> counter, UniTuple<Right_> rightTuple) {
if (testFiltering(counter.leftTuple, rightTuple)) {
counter.countRight++;
var tracker = new FilteringTracker<>(counter, rightTuple);
linkLeft(tracker);
linkRight(tracker);
// Prepends tracker into the right tuple's hidden intrusive tracker list.
// The right tuple's store at inputStoreIndexRightTrackerList holds the list head (null = empty).
private void linkRight(FilteringTracker<LeftTuple_> tracker) {
var rightTuple = tracker.rightTuple;
FilteringTracker<LeftTuple_> head = rightTuple.getStore(inputStoreIndexRightTrackerList);
tracker.rightNext = head;
if (head != null) {
head.rightPrev = tracker;
}
rightTuple.setStore(inputStoreIndexRightTrackerList, tracker);
}

protected void updateCounterFromRight(ExistsCounter<LeftTuple_> counter, UniTuple<Right_> rightTuple) {
protected void updateCounterRight(ExistsCounter<LeftTuple_> counter, UniTuple<Right_> rightTuple) {
var leftTuple = counter.leftTuple;
if (!leftTuple.getState().isActive()) {
// Assume the following scenario:
Expand All @@ -237,9 +244,9 @@ protected void updateCounterFromRight(ExistsCounter<LeftTuple_> counter, UniTupl
// We avoid this situation as it is clear that the outTuple must be retracted anyway,
// and therefore any further updates to it are pointless.
//
// It is possible that the same problem would exist coming from the other side as well,
// and therefore the right tuple would have to be checked for active state as well.
// However, no such issue could have been reproduced; when in doubt, leave it out.
// The left tuple can be inactive here because its node sits in a higher layer than the right's:
// the right's inserts and updates are delivered before the left's retracts are.
// The mirror case is possible too, see updateCounterLeft(...).
return;
}
if (testFiltering(leftTuple, rightTuple)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private void updateCounterRight(LeftTuple_ leftTuple, Object compositeKey, Exist
// Trackers link themselves into the left tuple's inputStoreIndexLeftTrackerList slot.
// No list object is needed; the slot starts null and the first tracker becomes the head.
forEachRightFromLeft(leftTuple, compositeKey,
rightTuple -> updateCounterFromLeft(counter, rightTuple));
rightTuple -> updateCounterLeft(counter, rightTuple));
}
}

Expand Down Expand Up @@ -138,7 +138,7 @@ public final void updateLeft(LeftTuple_ leftTuple) {
clearLeftTrackerList(leftTuple);
counter.countRight = 0;
forEachRightFromLeft(leftTuple, oldCompositeKey,
rightTuple -> updateCounterFromLeft(counter, rightTuple));
rightTuple -> updateCounterLeft(counter, rightTuple));
updateCounterLeft(counter);
}
} else {
Expand Down Expand Up @@ -208,7 +208,7 @@ private void updateCounterLeft(UniTuple<Right_> rightTuple, Object compositeKey)
// Trackers link themselves into the right tuple's inputStoreIndexRightTrackerList slot.
// No list object is needed; the slot starts null and the first tracker becomes the head.
forEachLeftCounter(rightTuple, compositeKey,
counter -> updateCounterFromRight(counter, rightTuple));
counter -> updateCounterRight(counter, rightTuple));
}
}

Expand All @@ -226,7 +226,7 @@ public final void updateRight(UniTuple<Right_> rightTuple) {
if (isFiltering) {
clearRightTrackerList(rightTuple);
forEachLeftCounter(rightTuple, oldCompositeKey,
counter -> updateCounterFromRight(counter, rightTuple));
counter -> updateCounterRight(counter, rightTuple));
}
} else {
// sameBucket: equal prefix unchanged ⇒ keep & reuse the cached bucket (no top lookup, no drop/recreate).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public final void updateLeft(LeftTuple_ leftTuple) {
indexerLeft.remove(oldCompositeKey, entry);
}
}
outTupleListLeft.clear(this::retractOutTupleByLeft);
outTupleListLeft.clear(this::retractOutTupleLeft);
// outTupleListLeft is now empty
// No need for leftTuple.setStore(inputStoreIndexLeftOutTupleList, outTupleListLeft);
indexAndPropagateLeft(leftTuple, newCompositeKey, reuseBucket);
Expand Down Expand Up @@ -153,12 +153,13 @@ private void indexAndPropagateLeft(LeftTuple_ leftTuple, Object compositeKey, bo
// and requires adding null checks to the filter for something that should intuitively be impossible.
// We avoid this situation as it is clear that it is pointless to insert this tuple.
//
// It is possible that the same problem would exist coming from the other side as well,
// and therefore the right tuple would have to be checked for active state as well.
// However, no such issue could have been reproduced; when in doubt, leave it out.
// The left tuple can be inactive here because its node sits in a higher layer than the right's:
// the right's inserts are delivered before the left's retracts are.
return;
}
forEachRightMatch(leftTuple, compositeKey, rightTuple -> insertOutTupleFiltered(leftTuple, rightTuple));
// The right tuples come out of the index and can be retracting for the mirror-image reason,
// hence insertOutTupleFilteredFromRight(...) rather than the unguarded insert.
forEachRightMatch(leftTuple, compositeKey, rightTuple -> insertOutTupleFilteredRight(leftTuple, rightTuple));
}

@Override
Expand All @@ -177,7 +178,7 @@ public final void retractLeft(LeftTuple_ leftTuple) {
} else {
indexerLeft.remove(compositeKey, entry);
}
outTupleListLeft.clear(this::retractOutTupleByLeft);
outTupleListLeft.clear(this::retractOutTupleLeft);
}

@Override
Expand Down Expand Up @@ -222,7 +223,7 @@ public final void updateRight(UniTuple<Right_> rightTuple) {
indexerRight.remove(oldCompositeKey, entry);
}
}
outTupleListRight.clear(this::retractOutTupleByRight);
outTupleListRight.clear(this::retractOutTupleRight);
// outTupleListRight is now empty
// No need for rightTuple.setStore(inputStoreIndexRightOutTupleList, outTupleListRight);
indexAndPropagateRight(rightTuple, newCompositeKey, reuseBucket);
Expand All @@ -245,7 +246,7 @@ private void indexAndPropagateRight(UniTuple<Right_> rightTuple, Object composit
} else {
rightTuple.setStore(inputStoreIndexRightEntry, indexerRight.put(compositeKey, rightTuple));
}
forEachLeftMatch(rightTuple, compositeKey, leftTuple -> insertOutTupleFilteredFromLeft(leftTuple, rightTuple));
forEachLeftMatch(rightTuple, compositeKey, leftTuple -> insertOutTupleFilteredLeft(leftTuple, rightTuple));
}

@Override
Expand All @@ -265,7 +266,7 @@ public final void retractRight(UniTuple<Right_> rightTuple) {
indexerRight.remove(compositeKey, entry);
}

outTupleListRight.clear(this::retractOutTupleByRight);
outTupleListRight.clear(this::retractOutTupleRight);
}

/**
Expand Down
Loading
Loading