1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.buffer.api.internal;
17
18 import io.netty5.buffer.api.MemoryManager;
19 import io.netty5.buffer.api.bytebuffer.ByteBufferMemoryManager;
20 import io.netty5.buffer.api.unsafe.UnsafeMemoryManager;
21 import io.netty5.util.internal.PlatformDependent;
22 import io.netty5.util.internal.logging.InternalLogger;
23 import io.netty5.util.internal.logging.InternalLoggerFactory;
24
25 import java.util.Collections;
26 import java.util.IdentityHashMap;
27 import java.util.Map;
28 import java.util.Optional;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.function.Supplier;
31
32 public final class MemoryManagerOverride {
33 private static final MemoryManager DEFAULT = createDefaultMemoryManagerInstance();
34 private static final AtomicInteger OVERRIDES_AVAILABLE = new AtomicInteger();
35 private static final Map<Thread, MemoryManager> OVERRIDES = Collections.synchronizedMap(new IdentityHashMap<>());
36
37 private MemoryManagerOverride() {
38 }
39
40 private static MemoryManager createDefaultMemoryManagerInstance() {
41 String systemProperty = "io.netty5.buffer.api.MemoryManager";
42 String configured = System.getProperty(systemProperty);
43 InternalLogger logger = InternalLoggerFactory.getInstance(MemoryManagerOverride.class);
44 if (configured != null) {
45 Optional<MemoryManager> candidateManager = MemoryManager.lookupImplementation(configured);
46 if (candidateManager.isPresent()) {
47 logger.debug("{} configured: {}", systemProperty, configured);
48 return candidateManager.get();
49 } else {
50 MemoryManager fallback = new ByteBufferMemoryManager();
51 logger.debug("{} requested implementation is unavailable: {} (using default {} implementation instead)",
52 systemProperty, configured, fallback.implementationName());
53 return fallback;
54 }
55 }
56 if (PlatformDependent.hasUnsafe() && PlatformDependent.hasDirectBufferNoCleanerConstructor()) {
57 try {
58 return new UnsafeMemoryManager();
59 } catch (Exception exception) {
60
61 logger.warn("Both sun.misc.Unsafe and DirectByteBuffer-without-Cleaner constructor are available, " +
62 "yet an UnsafeMemoryManager could not be created.", exception);
63 }
64 }
65 return new ByteBufferMemoryManager();
66 }
67
68 public static MemoryManager configuredOrDefaultManager() {
69 return configuredOrDefaultManager(DEFAULT);
70 }
71
72 public static MemoryManager configuredOrDefaultManager(MemoryManager desiredDefault) {
73 if (OVERRIDES_AVAILABLE.get() > 0) {
74 return OVERRIDES.getOrDefault(Thread.currentThread(), desiredDefault);
75 }
76 return desiredDefault;
77 }
78
79 public static <T> T using(MemoryManager managers, Supplier<T> supplier) {
80 Thread thread = Thread.currentThread();
81 OVERRIDES.put(thread, managers);
82 OVERRIDES_AVAILABLE.incrementAndGet();
83 try {
84 return supplier.get();
85 } finally {
86 OVERRIDES_AVAILABLE.decrementAndGet();
87 OVERRIDES.remove(thread);
88 }
89 }
90 }