|
1 | 1 | package datadog.context; |
2 | 2 |
|
3 | | -import java.lang.ref.WeakReference; |
4 | | - |
5 | 3 | /** {@link ContextScope} that has no effect on execution units. */ |
6 | | -final class NoopContextScope extends WeakReference<Context> implements ContextScope { |
| 4 | +final class NoopContextScope implements ContextScope { |
7 | 5 | static final ContextScope ROOT_SCOPE = new NoopContextScope(Context.root()); |
8 | 6 |
|
9 | | - private static final int CACHE_SIZE = 32; // must be power of 2 |
10 | | - private static final int SLOT_MASK = CACHE_SIZE - 1; |
11 | | - private static final int MAX_HASH_ATTEMPTS = 3; |
12 | | - |
13 | | - /** Bounded cache of no-op scopes to reduce (re)allocations. */ |
14 | | - private static final NoopContextScope[] cache = new NoopContextScope[CACHE_SIZE]; |
15 | | - |
16 | | - @SuppressWarnings({"resource", "StatementWithEmptyBody"}) |
17 | 7 | static ContextScope create(Context context) { |
18 | | - if (context == Context.root()) { |
19 | | - return ROOT_SCOPE; |
20 | | - } |
21 | | - int hash = System.identityHashCode(context); |
22 | | - int evictedSlot = -1; |
23 | | - // search by repeated hashing; stop when we find an empty slot, |
24 | | - // a matching slot, or we exhaust all attempts and re-use a slot |
25 | | - for (int i = 1, h = hash; true; i++, h = rehash(h)) { |
26 | | - int slot = SLOT_MASK & h; |
27 | | - NoopContextScope existing = cache[slot]; |
28 | | - if (existing != null) { |
29 | | - // slot already used |
30 | | - Context existingContext = existing.get(); |
31 | | - if (context == existingContext) { |
32 | | - return existing; // match found |
33 | | - } |
34 | | - if (i < MAX_HASH_ATTEMPTS) { |
35 | | - // still more slots to search |
36 | | - if (existingContext == null && evictedSlot < 0) { |
37 | | - // record first evicted slot for re-use later |
38 | | - evictedSlot = slot; |
39 | | - } |
40 | | - continue; // rehash and try again |
41 | | - } |
42 | | - // exhausted attempts, pick best slot to re-use |
43 | | - if (evictedSlot >= 0) { |
44 | | - slot = evictedSlot; // re-use first evicted slot |
45 | | - } else if (existingContext == null) { |
46 | | - // last hashed slot is itself evicted, re-use it |
47 | | - } else { |
48 | | - slot = SLOT_MASK & hash; // re-use first hashed slot |
49 | | - } |
50 | | - } |
51 | | - return (cache[slot] = new NoopContextScope(context)); |
52 | | - } |
| 8 | + return context == Context.root() ? ROOT_SCOPE : new NoopContextScope(context); |
53 | 9 | } |
54 | 10 |
|
| 11 | + private final Context context; |
| 12 | + |
55 | 13 | private NoopContextScope(Context context) { |
56 | | - super(context); |
| 14 | + this.context = context; |
57 | 15 | } |
58 | 16 |
|
59 | 17 | @Override |
60 | 18 | public Context context() { |
61 | | - Context context = get(); |
62 | | - // no-op scopes are used when the context is already attached so the reference |
63 | | - // value should still be there; if not then we fall back to empty (root) context |
64 | | - return context != null ? context : Context.root(); |
| 19 | + return context; |
65 | 20 | } |
66 | 21 |
|
67 | 22 | @Override |
68 | 23 | public void close() {} |
69 | | - |
70 | | - private static int rehash(int oldHash) { |
71 | | - // scatter in both directions using value close to golden ratio |
72 | | - return Integer.reverseBytes(oldHash * 0x9e3775cd) * 0x9e3775cd; |
73 | | - } |
74 | 24 | } |
0 commit comments