Skip to content

Commit

Permalink
segregate MethodHandles code from aggregation logic to make it easier…
Browse files Browse the repository at this point in the history
… to delete when increasing the language level
  • Loading branch information
richardstartin committed Oct 31, 2022
1 parent 1cf9bf3 commit 46ffe13
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 43 deletions.
51 changes: 51 additions & 0 deletions src/main/java/com/timgroup/statsd/MapUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.timgroup.statsd;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Map;

/**
* MethodHandle based bridge for using JDK8+ functionality at JDK7 language level.
* Can be removed when support for JDK7 is dropped.
*/
public class MapUtils {

private static final MethodHandle MAP_PUT_IF_ABSENT = buildMapPutIfAbsent();
/**
* Emulates {@code Map.putIfAbsent} semantics. Replace when baselining at JDK8+.
* @return the previous value associated with the message, or null if the value was not seen before
*/
static Message putIfAbsent(Map<Message, Message> map, Message message) {
if (MAP_PUT_IF_ABSENT != null) {
try {
return (Message) (Object) MAP_PUT_IF_ABSENT.invokeExact(map, (Object) message, (Object) message);
} catch (Throwable ignore) {
return putIfAbsentFallback(map, message);
}
}
return putIfAbsentFallback(map, message);
}

/**
* Emulates {@code Map.putIfAbsent} semantics. Replace when baselining at JDK8+.
* @return the previous value associated with the message, or null if the value was not seen before
*/
private static Message putIfAbsentFallback(Map<Message, Message> map, Message message) {
if (map.containsKey(message)) {
return map.get(message);
}
map.put(message, message);
return null;
}

private static MethodHandle buildMapPutIfAbsent() {
try {
return MethodHandles.publicLookup()
.findVirtual(Map.class, "putIfAbsent",
MethodType.methodType(Object.class, Object.class, Object.class));
} catch (Throwable ignore) {
return null;
}
}
}
44 changes: 1 addition & 43 deletions src/main/java/com/timgroup/statsd/StatsDAggregator.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.timgroup.statsd;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
Expand All @@ -18,8 +15,6 @@ public class StatsDAggregator {
public static int DEFAULT_SHARDS = 4; // 4 partitions to reduce contention.

protected final String AGGREGATOR_THREAD_NAME = "statsd-aggregator-thread";

private static final MethodHandle MAP_PUT_IF_ABSENT = buildMapPutIfAbsent();
protected static final Set<Message.Type> AGGREGATE_SET = EnumSet.of(Message.Type.COUNT, Message.Type.GAUGE,
Message.Type.SET);
protected final ArrayList<Map<Message, Message>> aggregateMetrics;
Expand Down Expand Up @@ -109,7 +104,7 @@ public boolean aggregateMessage(Message message) {

synchronized (map) {
// For now let's just put the message in the map
Message msg = putIfAbsent(map, message);
Message msg = MapUtils.putIfAbsent(map, message);
if (msg != null) {
msg.aggregate(message);
if (telemetry != null) {
Expand Down Expand Up @@ -163,41 +158,4 @@ protected void flush() {
}
}
}

/**
* Emulates {@code Map.putIfAbsent} semantics. Replace when baselining at JDK8+.
* @return the previous value associated with the message, or null if the value was not seen before
*/
private static Message putIfAbsent(Map<Message, Message> map, Message message) {
if (MAP_PUT_IF_ABSENT != null) {
try {
return (Message) (Object) MAP_PUT_IF_ABSENT.invokeExact(map, (Object) message, (Object) message);
} catch (Throwable ignore) {
return putIfAbsentFallback(map, message);
}
}
return putIfAbsentFallback(map, message);
}

/**
* Emulates {@code Map.putIfAbsent} semantics. Replace when baselining at JDK8+.
* @return the previous value associated with the message, or null if the value was not seen before
*/
private static Message putIfAbsentFallback(Map<Message, Message> map, Message message) {
if (map.containsKey(message)) {
return map.get(message);
}
map.put(message, message);
return null;
}

private static MethodHandle buildMapPutIfAbsent() {
try {
return MethodHandles.publicLookup()
.findVirtual(Map.class, "putIfAbsent",
MethodType.methodType(Object.class, Object.class, Object.class));
} catch (Throwable ignore) {
return null;
}
}
}

0 comments on commit 46ffe13

Please sign in to comment.