_PhantomCacheCleanup rewritten to java

This commit is contained in:
Andrew Golovashevich 2025-03-27 00:56:27 +03:00
parent c5d569e0f1
commit 024ddef803
4 changed files with 97 additions and 77 deletions

View File

@ -0,0 +1,88 @@
package ru.langrafhomyak.db.jdbc_resources_manager;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import org.jetbrains.annotations.NotNull;
class _PhantomCacheCleanup {
abstract static class CleanablePhantomReference<T> extends PhantomReference<T> {
protected CleanablePhantomReference(T ref) {
super(ref, _PhantomCacheCleanup._referenceQueue);
}
abstract void cleanup();
}
private static final Thread _thread = _PhantomCacheCleanup._createThread();
@NotNull
private static final String _virtualThreadProperty = "ru.langrafhomyak.db.jdbc_resources_manager._PhantomCacheCleanup.use_virtual_thread";
@NotNull
private static final ReferenceQueue<@NotNull Object> _referenceQueue = new ReferenceQueue<>();
@NotNull
private static final String _threadName = "ru.langrafhomyak.db.jdbc_resources_manager._PhantomCacheCleanup";
@NotNull
private static Thread _createThread() {
if (_PhantomCacheCleanup._isVirtualThreadsSupported() && !System.getProperty(_PhantomCacheCleanup._virtualThreadProperty).equalsIgnoreCase("false")) {
return _PhantomCacheCleanup._startVirtualThread();
} else {
return _PhantomCacheCleanup._startVirtualThread();
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private static boolean _isVirtualThreadsSupported() {
try {
Thread.ofVirtual();
return true;
} catch (NoSuchMethodError e) {
return false;
}
}
@NotNull
private static Thread _startSystemThreadBeforeJ21() {
final Thread t = new Thread(
null,
new CleanupRoutine(), _PhantomCacheCleanup._threadName,
1024 * 16, false
);
t.setDaemon(true);
t.setPriority(Thread.MIN_PRIORITY + 1);
t.start();
return t;
}
@NotNull
private static Thread _startVirtualThread() {
final var b = Thread.ofVirtual();
b.name(_PhantomCacheCleanup._threadName);
b.inheritInheritableThreadLocals(false);
return b.start(new CleanupRoutine());
}
private static class CleanupRoutine implements Runnable {
@Override
public void run() {
while (true) {
// (Thread.currentThread() as? InnocuousThread)?.eraseThreadLocals()
try {
((CleanablePhantomReference<?>) _PhantomCacheCleanup._referenceQueue.remove(60 * 60)).cleanup();
} /* catch (_: LinkageError) {
return
} */ catch (InterruptedException e) {
return;
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}
}

View File

@ -1,11 +1,16 @@
package ru.langrafhomyak.db.jdbc_resources_manager package ru.langrafhomyak.db.jdbc_resources_manager
import java.lang.NullPointerException
import java.sql.ResultSet import java.sql.ResultSet
import java.sql.SQLException import java.sql.SQLException
import java.sql.SQLType import java.sql.SQLType
import java.sql.Statement import java.sql.Statement
import org.jetbrains.annotations.NotNull
internal abstract class ResultSetWrapper(@NotNull orig: ResultSet?) : ResultSet by (orig ?: throw NullPointerException("orig")) {
@JvmField
protected val _orig: ResultSet = (orig ?: throw NullPointerException("orig"))
internal abstract class ResultSetWrapper(@JvmField protected val _orig: ResultSet) : ResultSet by _orig {
@Throws(SQLException::class) @Throws(SQLException::class)
abstract override fun close() abstract override fun close()

View File

@ -1,74 +0,0 @@
package ru.langrafhomyak.db.jdbc_resources_manager
import java.lang.ref.PhantomReference
import java.lang.ref.ReferenceQueue
internal object _PhantomCacheCleanup {
private val _thread: Thread
@Suppress("MAY_BE_CONST")
private val _virtualThreadProperty = "ru.langrafhomyak.db.jdbc_resources_manager._PhantomCacheCleanup.USE_VIRTUAL_THREAD"
private val _referenceQueue = ReferenceQueue<Any?>()
@Suppress("MAY_BE_CONST")
private val _threadName = "ru.langrafhomyak.db.jdbc_resources_manager._PhantomCacheCleanup"
init {
if (this._isVirtualThreadsSupported() && System.getProperty(this._virtualThreadProperty)?.lowercase() != "false")
this._thread = this._startVirtualThread()
else
this._thread = this._startSystemThreadBeforeJ21()
}
private fun _isVirtualThreadsSupported(): Boolean {
try {
Thread::ofVirtual
return true
} catch (_: NoSuchMethodError) {
return false
}
}
private fun _startSystemThreadBeforeJ21(): Thread {
val t = Thread(
null,
CleanupRoutine, this._threadName,
1024 * 16, false
)
t.isDaemon = true
t.priority = Thread.MIN_PRIORITY + 1
t.start()
return t
}
private fun _startVirtualThread(): Thread {
val b = Thread.ofVirtual()
b.name(this._threadName)
return b.start(CleanupRoutine)
}
private object CleanupRoutine : Runnable {
override fun run() {
while (true) {
// (Thread.currentThread() as? InnocuousThread)?.eraseThreadLocals()
try {
(this@_PhantomCacheCleanup._referenceQueue.remove(60 * 60) as CleanablePhantomReference<*>).cleanup()
} /* catch (_: LinkageError) {
return
} */ catch (_: InterruptedException) {
return
} catch (e: Throwable) {
e.printStackTrace()
}
}
}
}
abstract class CleanablePhantomReference<T>(ref: T) : PhantomReference<T>(ref, this@_PhantomCacheCleanup._referenceQueue) {
abstract fun cleanup()
}
}

View File

@ -8,11 +8,12 @@ import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
@Suppress("NOTHING_TO_INLINE")
@JvmName("prepareStatement") @JvmName("prepareStatement")
public fun Connection.prepareStatement(ps: PreparedStatementsCompilationCache): PreparedStatement = ps.preparedStatementForConnection(this) public inline fun Connection.prepareStatement(ps: PreparedStatementsCompilationCache): PreparedStatement = ps.preparedStatementForConnection(this)
@JvmName("prepareStatement\$autoclose") @JvmName("prepareStatement\$autoclose")
public fun <R> Connection.prepareStatement(ps: PreparedStatementsCompilationCache, preparedStatementScope: (ps: PreparedStatement) -> R): R { public inline fun <R> Connection.prepareStatement(ps: PreparedStatementsCompilationCache, preparedStatementScope: (ps: PreparedStatement) -> R): R {
contract { contract {
callsInPlace(preparedStatementScope, InvocationKind.EXACTLY_ONCE) callsInPlace(preparedStatementScope, InvocationKind.EXACTLY_ONCE)
} }