Skip to content
Open
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 @@ -2,6 +2,7 @@

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.function.BiConsumer;
import javax.annotation.Nullable;

/** {@link ContextManager} that uses a {@link ThreadLocal} to track context per thread. */
Expand Down Expand Up @@ -40,10 +41,7 @@ ContextScope doAttach(Context context, @Nullable ContextContinuationImpl continu
return context.asScope(); // convert to scope without attaching
}

ContextListener[] ls = listeners;
notifyDetach(beforeAttach, ls);
holder.current = context;
notifyAttach(context, ls);
doSwap(holder, beforeAttach, context);

if (continuation == null) {
return new ContextScopeImpl(context, holder, beforeAttach);
Expand All @@ -61,10 +59,7 @@ public Context swap(Context context) {
return beforeSwap;
}

ContextListener[] ls = listeners;
notifyDetach(beforeSwap, ls);
holder.current = context;
notifyAttach(context, ls);
doSwap(holder, beforeSwap, context);

return beforeSwap;
}
Expand Down Expand Up @@ -103,46 +98,44 @@ static void notifyAttach(Context context, ContextListener[] listeners) {
if (context == Context.root()) {
return; // don't emit attach events for the default "no context" case
}
for (ContextListener l : listeners) {
try {
l.onAttach(context);
} catch (Throwable ignore) {
}
}
dispatch(context, listeners, ContextListener::onAttach);
}

static void notifyDetach(Context context, ContextListener[] listeners) {
if (context == Context.root()) {
return; // don't emit detach events for the default "no context" case
}
for (ContextListener l : listeners) {
try {
l.onDetach(context);
} catch (Throwable ignore) {
}
}
dispatch(context, listeners, ContextListener::onDetach);
}

static void notifyCapture(Context context, ContextListener[] listeners) {
// only called for non-empty continuations
for (ContextListener l : listeners) {
try {
l.onCapture(context);
} catch (Throwable ignore) {
}
}
dispatch(context, listeners, ContextListener::onCapture);
}

static void notifyRelease(Context context, ContextListener[] listeners) {
// only called for non-empty continuations
dispatch(context, listeners, ContextListener::onRelease);
}

private static void dispatch(
Context context, ContextListener[] listeners, BiConsumer<ContextListener, Context> event) {
for (ContextListener l : listeners) {
try {
l.onRelease(context);
event.accept(l, context);
} catch (Throwable ignore) {
}
}
}

private static void doSwap(ContextHolder holder, Context before, Context after) {
// Snapshot listeners so same listeners will get the two events
ContextListener[] ls = INSTANCE.listeners;
notifyDetach(before, ls);
holder.current = after;
notifyAttach(after, ls);
}

private static class ContextScopeImpl implements ContextScope {

private final Context context;
Expand All @@ -166,10 +159,7 @@ public final Context context() {
public void close() {
// check for out-of-order close to avoid corrupting the current state
if (!closed && context == holder.current) {
ContextListener[] ls = INSTANCE.listeners;
notifyDetach(context, ls);
holder.current = beforeAttach;
notifyAttach(beforeAttach, ls);
doSwap(holder, context, beforeAttach);
closed = true;
}
}
Expand Down