Skip to content
Draft
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 @@ -30,6 +30,9 @@ public <T> T get(ContextKey<T> key) {
public <T> Context with(ContextKey<T> key, @Nullable T value) {
requireNonNull(key, "Context key cannot be null");
int index = key.index;
if (index < this.store.length && this.store[index] == value) {
return this;
}
Object[] newStore = copyOfRange(this.store, 0, max(this.store.length, index + 1));
newStore[index] = value;
return new IndexedContext(newStore);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ public <V> Context with(ContextKey<V> secondKey, @Nullable V secondValue) {
requireNonNull(secondKey, "Context key cannot be null");
int secondIndex = secondKey.index;
if (this.index == secondIndex) {
return secondValue == null
? EmptyContext.INSTANCE
: new SingletonContext(this.index, secondValue);
if (secondValue == null) {
return EmptyContext.INSTANCE;
} else if (secondValue != this.value) {
return new SingletonContext(this.index, secondValue);
} else {
return this;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve distinct contexts for nested scope attachment

When a caller derives a nested scope with the same key/value, e.g. Context.current().with(k, v).attach(), this now reuses the outer Context instance. With the default ThreadLocalContextManager, ContextScope.close() decides whether a scope is current by context == holder[0]; if the outer scope is closed before the inner one (the out-of-order case covered by ContextManagerTest.testOnlyCurrentScopeCanBeClosed for derived contexts), both scopes now carry the same context, so closing the outer scope incorrectly restores the previous context and detaches the still-active inner scope. Please keep with() returning a distinct context for this case, or make scope-close tracking distinguish scope instances rather than context identity.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting point

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This issue should be addressed once my other PR is merged, as it introduces no-op scopes when the same context is attached multiple times...

}
} else {
Object[] store = new Object[max(this.index, secondIndex) + 1];
store[this.index] = this.value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand Down Expand Up @@ -165,6 +166,17 @@ void testToString(Context context) {
"Context string representation should contain implementation name");
}

@ParameterizedTest
@MethodSource("contextImplementations")
void testWithSameValueReturnsThis(Context context) {
String value = "value";
Context context1 = context.with(STRING_KEY, value);
// storing the same value again should return the same instance
assertSame(context1, context1.with(STRING_KEY, value));
// storing a different value should return a new instance
assertNotEquals(context1, context1.with(STRING_KEY, "other"));
}

@SuppressWarnings({"SimplifiableAssertion"})
@Test
void testInflation() {
Expand Down
Loading