Skip to content

Commit

Permalink
Introduce reference support submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
dmlloyd committed Mar 18, 2022
1 parent 1279555 commit e59d12e
Show file tree
Hide file tree
Showing 12 changed files with 706 additions and 0 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
<module>io</module>
<module>net</module>
<module>os</module>
<module>ref</module>
<module>version</module>
<module>vertx-context</module>
</modules>
Expand Down
49 changes: 49 additions & 0 deletions ref/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.smallrye.common</groupId>
<artifactId>smallrye-common-parent</artifactId>
<version>1.10.1-SNAPSHOT</version>
</parent>

<artifactId>smallrye-common-ref</artifactId>

<name>SmallRye Common: References</name>

<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>smallrye-common-constraint</artifactId>
</dependency>
</dependencies>

<profiles>
<profile>
<id>coverage</id>
<properties>
<argLine>@{jacocoArgLine}</argLine>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
37 changes: 37 additions & 0 deletions ref/src/main/java/io/smallrye/common/ref/CleanerReference.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.smallrye.common.ref;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
* A special version of {@link PhantomReference} that is strongly retained until it is reaped by the collection thread.
*/
public class CleanerReference<T, A> extends PhantomReference<T, A> {
private static final Set<CleanerReference<?, ?>> set = Collections
.newSetFromMap(new ConcurrentHashMap<CleanerReference<?, ?>, Boolean>());

/**
* Construct a new instance with a reaper.
*
* @param referent the referent
* @param attachment the attachment
* @param reaper the reaper to use
*/
public CleanerReference(final T referent, final A attachment, final Reaper<T, A> reaper) {
super(referent, attachment, reaper);
set.add(this);
}

void clean() {
set.remove(this);
}

public final int hashCode() {
return super.hashCode();
}

public final boolean equals(final Object obj) {
return super.equals(obj);
}
}
59 changes: 59 additions & 0 deletions ref/src/main/java/io/smallrye/common/ref/PhantomReference.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.smallrye.common.ref;

import java.lang.ref.ReferenceQueue;

/**
* A reapable phantom reference with an attachment. If a {@link Reaper} is given, then it will be used to asynchronously
* clean up the referent.
*
* @param <T> the reference value type
* @param <A> the attachment type
*
* @see java.lang.ref.PhantomReference
*/
public class PhantomReference<T, A> extends java.lang.ref.PhantomReference<T> implements Reference<T, A>, Reapable<T, A> {
private final A attachment;
private final Reaper<T, A> reaper;

/**
* Construct a new instance with an explicit reference queue.
*
* @param referent the referent
* @param attachment the attachment
* @param q the reference queue to use
*/
public PhantomReference(final T referent, final A attachment, final ReferenceQueue<? super T> q) {
super(referent, q);
this.attachment = attachment;
reaper = null;
}

/**
* Construct a new instance with a reaper.
*
* @param referent the referent
* @param attachment the attachment
* @param reaper the reaper to use
*/
public PhantomReference(final T referent, final A attachment, final Reaper<T, A> reaper) {
super(referent, References.ReaperThread.REAPER_QUEUE);
this.reaper = reaper;
this.attachment = attachment;
}

public A getAttachment() {
return attachment;
}

public Type getType() {
return Type.PHANTOM;
}

public Reaper<T, A> getReaper() {
return reaper;
}

public String toString() {
return "phantom reference";
}
}
17 changes: 17 additions & 0 deletions ref/src/main/java/io/smallrye/common/ref/Reapable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.smallrye.common.ref;

/**
* A reference which is reapable (can be automatically collected).
*
* @param <T> the reference type
* @param <A> the reference attachment type
*/
interface Reapable<T, A> {

/**
* Get the associated reaper.
*
* @return the reaper
*/
Reaper<T, A> getReaper();
}
17 changes: 17 additions & 0 deletions ref/src/main/java/io/smallrye/common/ref/Reaper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.smallrye.common.ref;

/**
* A cleaner for a dead object.
*
* @param <T> the reference type
* @param <A> the reference attachment type
*/
public interface Reaper<T, A> {

/**
* Perform the cleanup action for a reference.
*
* @param reference the reference
*/
void reap(Reference<T, A> reference);
}
135 changes: 135 additions & 0 deletions ref/src/main/java/io/smallrye/common/ref/Reference.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package io.smallrye.common.ref;

import java.util.EnumSet;

/**
* An enhanced reference type with a type-safe attachment.
*
* @param <T> the reference value type
* @param <A> the attachment type
*
* @see java.lang.ref.Reference
*/
public interface Reference<T, A> {

/**
* Get the value, or {@code null} if the reference has been cleared.
*
* @return the value
*/
T get();

/**
* Get the attachment, if any.
*
* @return the attachment
*/
A getAttachment();

/**
* Clear the reference.
*/
void clear();

/**
* Get the type of the reference.
*
* @return the type
*/
Type getType();

/**
* A reference type.
*
* @apiviz.exclude
*/
enum Type {

/**
* A strong reference.
*/
STRONG,
/**
* A weak reference.
*/
WEAK,
/**
* A phantom reference.
*/
PHANTOM,
/**
* A soft reference.
*/
SOFT,
/**
* A {@code null} reference.
*/
NULL,
;

private static final int fullSize = values().length;

/**
* Determine whether the given set is fully populated (or "full"), meaning it contains all possible values.
*
* @param set the set
*
* @return {@code true} if the set is full, {@code false} otherwise
*/
public static boolean isFull(final EnumSet<Type> set) {
return set != null && set.size() == fullSize;
}

/**
* Determine whether this instance is equal to one of the given instances.
*
* @param v1 the first instance
*
* @return {@code true} if one of the instances matches this one, {@code false} otherwise
*/
public boolean in(final Type v1) {
return this == v1;
}

/**
* Determine whether this instance is equal to one of the given instances.
*
* @param v1 the first instance
* @param v2 the second instance
*
* @return {@code true} if one of the instances matches this one, {@code false} otherwise
*/
public boolean in(final Type v1, final Type v2) {
return this == v1 || this == v2;
}

/**
* Determine whether this instance is equal to one of the given instances.
*
* @param v1 the first instance
* @param v2 the second instance
* @param v3 the third instance
*
* @return {@code true} if one of the instances matches this one, {@code false} otherwise
*/
public boolean in(final Type v1, final Type v2, final Type v3) {
return this == v1 || this == v2 || this == v3;
}

/**
* Determine whether this instance is equal to one of the given instances.
*
* @param values the possible values
*
* @return {@code true} if one of the instances matches this one, {@code false} otherwise
*/
public boolean in(final Type... values) {
if (values != null)
for (Type value : values) {
if (this == value)
return true;
}
return false;
}
}
}
Loading

0 comments on commit e59d12e

Please sign in to comment.