Skip to content

Commit f8d0935

Browse files
committed
Allow contexts to wrap themselves as scopes without attaching.
This helps reduce allocations when attaching the same context multiple times.
1 parent e00a5f0 commit f8d0935

9 files changed

Lines changed: 38 additions & 25 deletions

File tree

components/context/src/main/java/datadog/context/Context.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,13 @@ default Context with(@Nullable ImplicitContextKeyed value) {
168168
}
169169
return value.storeInto(this);
170170
}
171+
172+
/**
173+
* Wraps context as a scope without attaching it to the current execution unit.
174+
*
175+
* @return a scope that has no effect on execution units.
176+
*/
177+
default ContextScope asScope() {
178+
return new NoopContextScope(this);
179+
}
171180
}

components/context/src/main/java/datadog/context/EmptyContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import javax.annotation.Nullable;
66

77
/** {@link Context} containing no values. */
8-
final class EmptyContext implements Context {
8+
final class EmptyContext implements SelfScopedContext {
99
static final Context INSTANCE = new EmptyContext();
1010

1111
private EmptyContext() {}

components/context/src/main/java/datadog/context/IndexedContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import javax.annotation.Nullable;
99

1010
/** {@link Context} containing many values. */
11-
final class IndexedContext implements Context {
11+
final class IndexedContext implements SelfScopedContext {
1212
final Object[] store;
1313

1414
IndexedContext(Object[] store) {

components/context/src/main/java/datadog/context/NoopContextContinuation.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22

33
/** {@link ContextContinuation} that has no effect on execution units. */
44
final class NoopContextContinuation implements ContextContinuation, ContextScope {
5-
static final NoopContextContinuation ROOT_CONTINUATION =
6-
new NoopContextContinuation(Context.root());
7-
85
private final Context context;
96

10-
private NoopContextContinuation(Context context) {
7+
NoopContextContinuation(Context context) {
118
this.context = context;
129
}
1310

components/context/src/main/java/datadog/context/NoopContextScope.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,9 @@
22

33
/** {@link ContextScope} that has no effect on execution units. */
44
final class NoopContextScope implements ContextScope {
5-
static final NoopContextScope ROOT_SCOPE = new NoopContextScope(Context.root());
6-
7-
static NoopContextScope create(Context context) {
8-
return context == Context.root() ? ROOT_SCOPE : new NoopContextScope(context);
9-
}
10-
115
private final Context context;
126

13-
private NoopContextScope(Context context) {
7+
NoopContextScope(Context context) {
148
this.context = context;
159
}
1610

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package datadog.context;
2+
3+
/** Context that acts as its own unattached scope. */
4+
interface SelfScopedContext extends Context, ContextScope {
5+
@Override
6+
default ContextScope asScope() {
7+
return this; // acts as no-op scope, avoiding allocation
8+
}
9+
10+
@Override
11+
default Context context() {
12+
return this;
13+
}
14+
15+
@Override
16+
default void close() {}
17+
}

components/context/src/main/java/datadog/context/SingletonContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import javax.annotation.Nullable;
88

99
/** {@link Context} containing a single value. */
10-
final class SingletonContext implements Context {
10+
final class SingletonContext implements SelfScopedContext {
1111
final int index;
1212
final Object value;
1313

components/context/src/main/java/datadog/context/ThreadLocalContextManager.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
final class ThreadLocalContextManager implements ContextManager {
99
static final ThreadLocalContextManager INSTANCE = new ThreadLocalContextManager();
1010

11+
private static final NoopContextContinuation ROOT_CONTINUATION =
12+
new NoopContextContinuation(Context.root());
13+
1114
private static final ThreadLocal<ContextHolder> CONTEXT_HOLDER =
1215
ThreadLocal.withInitial(ContextHolder::new);
1316

@@ -34,11 +37,7 @@ ContextScope doAttach(Context context, @Nullable ContextContinuationImpl continu
3437
continuation.releaseOnScopeClose();
3538
return continuation; // acts as no-op scope, avoiding allocation
3639
}
37-
NoopContextScope noopScope = holder.noopScope;
38-
if (context != noopScope.context()) {
39-
noopScope = holder.noopScope = NoopContextScope.create(context);
40-
}
41-
return noopScope;
40+
return context.asScope(); // convert to scope without attaching
4241
}
4342

4443
ContextListener[] ls = listeners;
@@ -73,7 +72,7 @@ public Context swap(Context context) {
7372
@Override
7473
public ContextContinuation capture(Context context) {
7574
if (context == Context.root()) {
76-
return NoopContextContinuation.ROOT_CONTINUATION;
75+
return ROOT_CONTINUATION;
7776
} else {
7877
return new ContextContinuationImpl(context);
7978
}
@@ -170,7 +169,6 @@ public void close() {
170169
ContextListener[] ls = INSTANCE.listeners;
171170
notifyDetach(context, ls);
172171
holder.current = previous;
173-
holder.noopScope = NoopContextScope.ROOT_SCOPE;
174172
notifyAttach(previous, ls);
175173
closed = true;
176174
}
@@ -295,7 +293,5 @@ public void close() {}
295293

296294
private static final class ContextHolder {
297295
Context current = Context.root();
298-
299-
NoopContextScope noopScope = NoopContextScope.ROOT_SCOPE;
300296
}
301297
}

components/context/src/test/java/datadog/context/ContextProvidersForkedTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public Context current() {
7373

7474
@Override
7575
public ContextScope attach(Context context) {
76-
return NoopContextScope.ROOT_SCOPE;
76+
return new NoopContextScope(root());
7777
}
7878

7979
@Override
@@ -83,7 +83,7 @@ public Context swap(Context context) {
8383

8484
@Override
8585
public ContextContinuation capture(Context context) {
86-
return NoopContextContinuation.ROOT_CONTINUATION;
86+
return new NoopContextContinuation(root());
8787
}
8888

8989
@Override

0 commit comments

Comments
 (0)