• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ben-manes / caffeine / #5173

29 Dec 2025 05:27AM UTC coverage: 0.0% (-100.0%) from 100.0%
#5173

push

github

ben-manes
speed up development ci build

0 of 3838 branches covered (0.0%)

0 of 7869 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/caffeine/src/main/java/com/github/benmanes/caffeine/cache/NodeFactory.java
1
/*
2
 * Copyright 2015 Ben Manes. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.github.benmanes.caffeine.cache;
17

18
import java.lang.invoke.MethodHandles;
19
import java.lang.invoke.MethodType;
20
import java.lang.ref.ReferenceQueue;
21
import java.util.concurrent.ConcurrentHashMap;
22
import java.util.concurrent.ConcurrentMap;
23

24
import org.jspecify.annotations.Nullable;
25

26
import com.github.benmanes.caffeine.cache.References.LookupKeyReference;
27
import com.github.benmanes.caffeine.cache.References.WeakKeyReference;
28
import com.google.errorprone.annotations.Var;
29

30
/**
31
 * A factory for cache nodes optimized for a particular configuration.
32
 *
33
 * @author ben.manes@gmail.com (Ben Manes)
34
 */
35
interface NodeFactory<K, V> {
36
  MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
×
37
  MethodType FACTORY = MethodType.methodType(void.class);
×
38
  ConcurrentMap<String, NodeFactory<Object, Object>> FACTORIES = new ConcurrentHashMap<>();
×
39

40
  RetiredStrongKey RETIRED_STRONG_KEY = new RetiredStrongKey();
×
41
  RetiredWeakKey RETIRED_WEAK_KEY = new RetiredWeakKey();
×
42
  DeadStrongKey DEAD_STRONG_KEY = new DeadStrongKey();
×
43
  DeadWeakKey DEAD_WEAK_KEY = new DeadWeakKey();
×
44
  String ACCESS_TIME = "accessTime";
45
  String WRITE_TIME = "writeTime";
46
  String VALUE = "value";
47
  String KEY = "key";
48

49
  /** Returns whether this factory supports weak values. */
50
  default boolean weakValues() {
51
    return false;
×
52
  }
53

54
  /** Returns whether this factory supports soft values. */
55
  default boolean softValues() {
56
    return false;
×
57
  }
58

59
  /** Returns a node optimized for the specified features. */
60
  Node<K, V> newNode(K key, @Nullable ReferenceQueue<K> keyReferenceQueue, V value,
61
      @Nullable ReferenceQueue<V> valueReferenceQueue, int weight, long now);
62

63
  /** Returns a node optimized for the specified features. */
64
  Node<K, V> newNode(Object keyReference, V value,
65
      @Nullable ReferenceQueue<V> valueReferenceQueue, int weight, long now);
66

67
  /**
68
   * Returns a key suitable for inserting into the cache. If the cache holds keys strongly then the
69
   * key is returned. If the cache holds keys weakly then a {@link java.lang.ref.Reference<K>}
70
   * holding the key argument is returned.
71
   */
72
  default Object newReferenceKey(K key, ReferenceQueue<K> referenceQueue) {
73
    return key;
×
74
  }
75

76
  /**
77
   * Returns a key suitable for looking up an entry in the cache. If the cache holds keys strongly
78
   * then the key is returned. If the cache holds keys weakly then a {@link LookupKeyReference}
79
   * holding the key argument is returned.
80
   */
81
  default Object newLookupKey(Object key) {
82
    return key;
×
83
  }
84

85
  /** Returns a factory optimized for the specified features. */
86
  @SuppressWarnings("unchecked")
87
  static <K, V> NodeFactory<K, V> newFactory(Caffeine<K, V> builder, boolean isAsync) {
88
    if (builder.interner) {
×
89
      return (NodeFactory<K, V>) Interned.FACTORY;
×
90
    }
91
    var className = getClassName(builder, isAsync);
×
92
    return loadFactory(className);
×
93
  }
94

95
  static String getClassName(Caffeine<?, ?> builder, boolean isAsync) {
96
    var className = new StringBuilder();
×
97
    if (builder.isStrongKeys()) {
×
98
      className.append('P');
×
99
    } else {
100
      className.append('F');
×
101
    }
102
    if (builder.isStrongValues()) {
×
103
      className.append('S');
×
104
    } else if (builder.isWeakValues()) {
×
105
      className.append('W');
×
106
    } else {
107
      className.append('D');
×
108
    }
109
    if (builder.expiresVariable()) {
×
110
      if (builder.refreshAfterWrite()) {
×
111
        className.append('A');
×
112
        if (builder.evicts()) {
×
113
          className.append('W');
×
114
        }
115
      } else {
116
        className.append('W');
×
117
      }
118
    } else {
119
      if (builder.expiresAfterAccess()) {
×
120
        className.append('A');
×
121
      }
122
      if (builder.expiresAfterWrite()) {
×
123
        className.append('W');
×
124
      }
125
    }
126
    if (builder.refreshAfterWrite()) {
×
127
      className.append('R');
×
128
    }
129
    if (builder.evicts()) {
×
130
      className.append('M');
×
131
      if (isAsync || (builder.isWeighted() && (builder.weigher != Weigher.singletonWeigher()))) {
×
132
        className.append('W');
×
133
      } else {
134
        className.append('S');
×
135
      }
136
    }
137
    return className.toString();
×
138
  }
139

140
  @SuppressWarnings("unchecked")
141
  static <K, V> NodeFactory<K, V> loadFactory(String className) {
142
    @Var var factory = FACTORIES.get(className);
×
143
    if (factory == null) {
×
144
      factory = FACTORIES.computeIfAbsent(className, NodeFactory::newFactory);
×
145
    }
146
    return (NodeFactory<K, V>) factory;
×
147
  }
148

149
  @SuppressWarnings("unchecked")
150
  static NodeFactory<Object, Object> newFactory(String className) {
151
    try {
152
      var clazz = LOOKUP.findClass(Node.class.getPackageName() + "." + className);
×
153
      var constructor = LOOKUP.findConstructor(clazz, FACTORY);
×
154
      return (NodeFactory<Object, Object>) constructor.invoke();
×
155
    } catch (RuntimeException | Error e) {
×
156
      throw e;
×
157
    } catch (Throwable t) {
×
158
      throw new IllegalStateException(className, t);
×
159
    }
160
  }
161

162
  final class RetiredWeakKey extends WeakKeyReference<Object> {
163
    RetiredWeakKey() { super(/* key= */ null, /* queue= */ null); }
×
164
  }
165
  final class DeadWeakKey extends WeakKeyReference<Object> {
166
    DeadWeakKey() { super(/* key= */ null, /* queue= */ null); }
×
167
  }
168
  final class RetiredStrongKey {}
×
169
  final class DeadStrongKey {}
×
170
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc