From 024ddef8035c32d244136d7e3978e8353b5cdbbb Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Thu, 27 Mar 2025 00:56:27 +0300 Subject: [PATCH] _PhantomCacheCleanup rewritten to java --- .../_PhantomCacheCleanup.java | 88 +++++++++++++++++++ .../ResultSetWrapper.kt | 7 +- .../_PhantomCacheCleanup.kt | 74 ---------------- .../db/jdbc_resources_manager/entry_points.kt | 5 +- 4 files changed, 97 insertions(+), 77 deletions(-) create mode 100644 src/jvmMain/java/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.java delete mode 100644 src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.kt diff --git a/src/jvmMain/java/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.java b/src/jvmMain/java/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.java new file mode 100644 index 0000000..184b6ad --- /dev/null +++ b/src/jvmMain/java/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.java @@ -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 extends PhantomReference { + 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(); + } + } + + } + } + +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/ResultSetWrapper.kt b/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/ResultSetWrapper.kt index 2dc6d8d..4a4aa20 100644 --- a/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/ResultSetWrapper.kt +++ b/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/ResultSetWrapper.kt @@ -1,11 +1,16 @@ package ru.langrafhomyak.db.jdbc_resources_manager +import java.lang.NullPointerException import java.sql.ResultSet import java.sql.SQLException import java.sql.SQLType 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) abstract override fun close() diff --git a/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.kt b/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.kt deleted file mode 100644 index e3fb003..0000000 --- a/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/_PhantomCacheCleanup.kt +++ /dev/null @@ -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() - - @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(ref: T) : PhantomReference(ref, this@_PhantomCacheCleanup._referenceQueue) { - abstract fun cleanup() - } -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/entry_points.kt b/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/entry_points.kt index d965589..a61f84e 100644 --- a/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/entry_points.kt +++ b/src/jvmMain/kotlin/ru/langrafhomyak/db/jdbc_resources_manager/entry_points.kt @@ -8,11 +8,12 @@ import kotlin.contracts.InvocationKind import kotlin.contracts.contract import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 +@Suppress("NOTHING_TO_INLINE") @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") -public fun Connection.prepareStatement(ps: PreparedStatementsCompilationCache, preparedStatementScope: (ps: PreparedStatement) -> R): R { +public inline fun Connection.prepareStatement(ps: PreparedStatementsCompilationCache, preparedStatementScope: (ps: PreparedStatement) -> R): R { contract { callsInPlace(preparedStatementScope, InvocationKind.EXACTLY_ONCE) }