diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 013eb7e21..d4d2bcdb2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,39 +10,41 @@ on: jobs: jvm-tests: name: JVM / scala ${{ matrix.scala }}, jdk ${{ matrix.java }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - java: [ 8, 11 ] + java: [ 11, 17, 21, 25 ] # WARN: build.sbt depends on this key path, as scalaVersion and # crossScalaVersions is determined from it - scala: [ 2.12.20, 2.13.16, 3.3.5 ] + scala: [ 2.13.8, 3.1.2 ] env: CI: true steps: - - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v10 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - java-version: "adopt@1.${{ matrix.java }}" + distribution: temurin + java-version: ${{ matrix.java }} + - uses: sbt/setup-sbt@v1 - name: Cache ivy2 - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.ivy2/cache key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache coursier (linux) if: contains(runner.os, 'linux') - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.cache/coursier/v1 key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache sbt - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.sbt key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} @@ -56,47 +58,48 @@ jobs: js-tests: name: JS / scala ${{ matrix.scala }}, jdk ${{ matrix.java }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: # WARN: build.sbt depends on this key path, as scalaVersion and # crossScalaVersions is determined from it include: - - { java: 8, scala: 2.12.20 } - - { java: 8, scala: 2.13.16 } - - { java: 8, scala: 3.3.5 } + - { java: 11, scala: 2.13.8 } + - { java: 11, scala: 3.1.2 } env: CI: true steps: - - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v10 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - java-version: "adopt@1.${{ matrix.java }}" + distribution: temurin + java-version: ${{ matrix.java }} + - uses: sbt/setup-sbt@v1 - name: Cache ivy2 - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.ivy2/cache key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache coursier (linux) if: contains(runner.os, 'linux') - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.cache/coursier/v1 key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache sbt - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.sbt key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Setup NodeJS - uses: actions/setup-node@v2.1.2 + uses: actions/setup-node@v4 with: node-version: 14 @@ -110,36 +113,37 @@ jobs: mima: name: Mima / scala ${{ matrix.scala }}, jdk ${{ matrix.java }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - - { java: 8, scala: 2.12.20 } - - { java: 8, scala: 2.13.16 } - - { java: 8, scala: 3.3.5 } + - { java: 11, scala: 2.13.8 } + - { java: 11, scala: 3.1.2 } steps: - - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v10 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - java-version: "adopt@1.${{ matrix.java }}" + distribution: temurin + java-version: ${{ matrix.java }} + - uses: sbt/setup-sbt@v1 - name: Cache ivy2 - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.ivy2/cache key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache coursier (linux) if: contains(runner.os, 'linux') - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.cache/coursier/v1 key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache sbt - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.sbt key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} @@ -153,36 +157,38 @@ jobs: unidoc: name: Unidoc / scala ${{ matrix.scala }}, jdk ${{ matrix.java }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - - { java: 8, scala: 2.13.16 } + - { java: 11, scala: 2.13.8 } # TODO: enable this after it works! - # - { java: 8, scala: 3.3.5 } + # - { java: 11, scala: 3.1.2 } steps: - - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v10 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - java-version: "adopt@1.${{ matrix.java }}" + distribution: temurin + java-version: ${{ matrix.java }} + - uses: sbt/setup-sbt@v1 - name: Cache ivy2 - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.ivy2/cache key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache coursier (linux) if: contains(runner.os, 'linux') - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.cache/coursier/v1 key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Cache sbt - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.sbt key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} @@ -197,7 +203,7 @@ jobs: all_tests: name: All Tests needs: [ jvm-tests, js-tests, mima, unidoc ] - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Ack run: | @@ -208,15 +214,17 @@ jobs: if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/series/3.x') needs: [ all_tests ] - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 100 - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v4 with: - java-version: "adopt@1.8" + distribution: temurin + java-version: 11 + - uses: sbt/setup-sbt@v1 - name: Install GnuPG2 run: | diff --git a/.github/workflows/manual-publish.yml b/.github/workflows/manual-publish.yml index e855853f2..885fb75f5 100644 --- a/.github/workflows/manual-publish.yml +++ b/.github/workflows/manual-publish.yml @@ -16,16 +16,18 @@ jobs: publish: name: Publish to Sonatype (Request) - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 100 ref: ${{ github.event.inputs.ref_to_publish }} - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v4 with: - java-version: "adopt@1.8" + distribution: temurin + java-version: 8 + - uses: sbt/setup-sbt@v1 - name: Install GnuPG2 run: | diff --git a/build.sbt b/build.sbt index e51405983..79af7ddfb 100644 --- a/build.sbt +++ b/build.sbt @@ -27,7 +27,7 @@ addCommandAlias("ci-release", ";+publishSigned ;sonatypeBundleRelease") val cats_Version = "2.7.0" val catsEffect_Version = "2.5.5" val fs2_Version = "2.5.11" -val jcTools_Version = "3.3.0" +val jcTools_Version = "4.0.5" val reactiveStreams_Version = "1.0.4" val macrotaskExecutor_Version = "1.0.0" val minitest_Version = "2.9.6" @@ -314,7 +314,6 @@ lazy val crossVersionSourcesSettings: Seq[Setting[_]] = (sc / unmanagedSourceDirectories) ++= { (sc / unmanagedSourceDirectories).value.flatMap { dir => scalaPartV.value match { - case Some((2, 12)) => Seq(new File(dir.getPath + "_2.13-"), new File(dir.getPath + "_3.0-")) case Some((3, _)) => Seq(new File(dir.getPath + "_3.0")) case _ => Seq(new File(dir.getPath + "_2.13+"), new File(dir.getPath + "_3.0-")) } @@ -393,7 +392,8 @@ def mimaSettings(projectName: String) = Seq( mimaBinaryIssueFilters ++= MimaFilters.changesFor_3_0_1, mimaBinaryIssueFilters ++= MimaFilters.changesFor_3_2_0, mimaBinaryIssueFilters ++= MimaFilters.changesFor_3_3_0, - mimaBinaryIssueFilters ++= MimaFilters.changesFor_3_4_0 + mimaBinaryIssueFilters ++= MimaFilters.changesFor_3_4_0, + mimaBinaryIssueFilters ++= MimaFilters.changesFor_avs ) lazy val doctestTestSettings = Seq( diff --git a/monix-execution/jvm/src/main/scala/monix/execution/internal/Platform.scala b/monix-execution/jvm/src/main/scala/monix/execution/internal/Platform.scala index a008f28cb..9f1f1bd1e 100644 --- a/monix-execution/jvm/src/main/scala/monix/execution/internal/Platform.scala +++ b/monix-execution/jvm/src/main/scala/monix/execution/internal/Platform.scala @@ -17,7 +17,10 @@ package monix.execution.internal +import monix.execution.internal.ThreadCompat.ThreadCompatOps import monix.execution.schedulers.CanBlock + +import scala.annotation.nowarn import scala.concurrent.{Await, Awaitable} import scala.concurrent.duration.Duration import scala.util.Try @@ -175,6 +178,7 @@ private[monix] object Platform { * To be used for multi-threading optimizations. Note that * in JavaScript this always returns the same value. */ + @nowarn("msg=deprecated") def currentThreadId(): Long = { Thread.currentThread().getId } diff --git a/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromCircularQueue.scala b/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromCircularQueue.scala index 6a51f952e..57b59bffc 100644 --- a/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromCircularQueue.scala +++ b/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromCircularQueue.scala @@ -19,10 +19,10 @@ package monix.execution.internal.collection.queues import monix.execution.ChannelType import monix.execution.ChannelType.{SingleConsumer, SingleProducer} +import java.lang.invoke.VarHandle import monix.execution.internal.atomic.UnsafeAccess import monix.execution.internal.collection.LowLevelConcurrentQueue import monix.execution.internal.jctools.queues.MessagePassingQueue -import sun.misc.Unsafe import scala.collection.mutable private[internal] abstract class FromCircularQueue[A](queue: MessagePassingQueue[A]) @@ -77,29 +77,20 @@ private[internal] object FromCircularQueue { private final class Java8SPMC[A](queue: MessagePassingQueue[A]) extends FromCircularQueue[A](queue) { - private[this] val UNSAFE = - UnsafeAccess.getInstance().asInstanceOf[Unsafe] - - def fenceOffer(): Unit = UNSAFE.fullFence() + def fenceOffer(): Unit = VarHandle.fullFence() def fencePoll(): Unit = () } private final class Java8MPSC[A](queue: MessagePassingQueue[A]) extends FromCircularQueue[A](queue) { - private[this] val UNSAFE = - UnsafeAccess.getInstance().asInstanceOf[Unsafe] - def fenceOffer(): Unit = () - def fencePoll(): Unit = UNSAFE.fullFence() + def fencePoll(): Unit = VarHandle.fullFence() } private final class Java8SPSC[A](queue: MessagePassingQueue[A]) extends FromCircularQueue[A](queue) { - private[this] val UNSAFE = - UnsafeAccess.getInstance().asInstanceOf[Unsafe] - - def fenceOffer(): Unit = UNSAFE.fullFence() - def fencePoll(): Unit = UNSAFE.fullFence() + def fenceOffer(): Unit = VarHandle.fullFence() + def fencePoll(): Unit = VarHandle.fullFence() } private final class Java7[A](queue: MessagePassingQueue[A], ct: ChannelType) diff --git a/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromMessagePassingQueue.scala b/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromMessagePassingQueue.scala index c0fd9a1ff..d9618b018 100644 --- a/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromMessagePassingQueue.scala +++ b/monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromMessagePassingQueue.scala @@ -19,10 +19,10 @@ package monix.execution.internal.collection.queues import monix.execution.ChannelType import monix.execution.ChannelType.{SingleConsumer, SingleProducer} +import java.lang.invoke.VarHandle import monix.execution.internal.atomic.UnsafeAccess import monix.execution.internal.collection.LowLevelConcurrentQueue import monix.execution.internal.jctools.queues.MessagePassingQueue -import sun.misc.Unsafe import scala.collection.mutable private[internal] abstract class FromMessagePassingQueue[A](queue: MessagePassingQueue[A]) @@ -74,29 +74,20 @@ private[internal] object FromMessagePassingQueue { private final class Java8SPMC[A](queue: MessagePassingQueue[A]) extends FromMessagePassingQueue[A](queue) { - private[this] val UNSAFE = - UnsafeAccess.getInstance().asInstanceOf[Unsafe] - - def fenceOffer(): Unit = UNSAFE.fullFence() + def fenceOffer(): Unit = VarHandle.fullFence() def fencePoll(): Unit = () } private final class Java8MPSC[A](queue: MessagePassingQueue[A]) extends FromMessagePassingQueue[A](queue) { - private[this] val UNSAFE = - UnsafeAccess.getInstance().asInstanceOf[Unsafe] - def fenceOffer(): Unit = () - def fencePoll(): Unit = UNSAFE.fullFence() + def fencePoll(): Unit = VarHandle.fullFence() } private final class Java8SPSC[A](queue: MessagePassingQueue[A]) extends FromMessagePassingQueue[A](queue) { - private[this] val UNSAFE = - UnsafeAccess.getInstance().asInstanceOf[Unsafe] - - def fenceOffer(): Unit = UNSAFE.fullFence() - def fencePoll(): Unit = UNSAFE.fullFence() + def fenceOffer(): Unit = VarHandle.fullFence() + def fencePoll(): Unit = VarHandle.fullFence() } private final class Java7[A](queue: MessagePassingQueue[A], ct: ChannelType) diff --git a/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/DynamicWorkerThreadFactory.scala b/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/DynamicWorkerThreadFactory.scala index 584183fce..8e297e2c6 100644 --- a/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/DynamicWorkerThreadFactory.scala +++ b/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/DynamicWorkerThreadFactory.scala @@ -19,20 +19,21 @@ package monix.execution.internal.forkJoin import java.util.concurrent.ForkJoinPool.{ForkJoinWorkerThreadFactory, ManagedBlocker} import java.util.concurrent.{ForkJoinPool, ForkJoinWorkerThread, ThreadFactory} - import monix.execution.internal.forkJoin.DynamicWorkerThreadFactory.EmptyBlockContext +import scala.annotation.nowarn import scala.concurrent.{BlockContext, CanAwait} // Implement BlockContext on FJP threads private[monix] final class DynamicWorkerThreadFactory( prefix: String, uncaught: Thread.UncaughtExceptionHandler, - daemonic: Boolean) - extends ThreadFactory with ForkJoinWorkerThreadFactory { + daemonic: Boolean +) extends ThreadFactory with ForkJoinWorkerThreadFactory { require(prefix ne null, "DefaultWorkerThreadFactory.prefix must be non null") + @nowarn("msg=deprecated") def wire[T <: Thread](thread: T): T = { thread.setDaemon(daemonic) thread.setUncaughtExceptionHandler(uncaught) diff --git a/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/StandardWorkerThreadFactory.scala b/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/StandardWorkerThreadFactory.scala index 7d6d885e2..2edcfc0f5 100644 --- a/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/StandardWorkerThreadFactory.scala +++ b/monix-execution/jvm/src/main/scala/monix/execution/internal/forkJoin/StandardWorkerThreadFactory.scala @@ -20,12 +20,15 @@ package monix.execution.internal.forkJoin import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory import java.util.concurrent.{ForkJoinPool, ForkJoinWorkerThread, ThreadFactory} +import scala.annotation.nowarn + private[monix] final class StandardWorkerThreadFactory( prefix: String, uncaught: Thread.UncaughtExceptionHandler, - daemonic: Boolean) - extends ThreadFactory with ForkJoinWorkerThreadFactory { + daemonic: Boolean +) extends ThreadFactory with ForkJoinWorkerThreadFactory { + @nowarn("msg=deprecated") def wire[T <: Thread](thread: T): T = { thread.setDaemon(daemonic) thread.setUncaughtExceptionHandler(uncaught) diff --git a/monix-execution/jvm/src/main/scala/monix/execution/schedulers/ThreadFactoryBuilder.scala b/monix-execution/jvm/src/main/scala/monix/execution/schedulers/ThreadFactoryBuilder.scala index d22978783..974a07ad9 100644 --- a/monix-execution/jvm/src/main/scala/monix/execution/schedulers/ThreadFactoryBuilder.scala +++ b/monix-execution/jvm/src/main/scala/monix/execution/schedulers/ThreadFactoryBuilder.scala @@ -17,9 +17,11 @@ package monix.execution.schedulers -import java.util.concurrent.ThreadFactory import monix.execution.UncaughtExceptionReporter +import java.util.concurrent.ThreadFactory +import scala.annotation.nowarn + private[schedulers] object ThreadFactoryBuilder { /** Constructs a ThreadFactory using the provided name prefix and appending * with a unique incrementing thread identifier. @@ -28,8 +30,10 @@ private[schedulers] object ThreadFactoryBuilder { * @param daemonic specifies whether the created threads should be daemonic * (non-daemonic threads are blocking the JVM process on exit). */ + def apply(name: String, reporter: UncaughtExceptionReporter, daemonic: Boolean): ThreadFactory = { new ThreadFactory { + @nowarn("cat=deprecated") def newThread(r: Runnable) = { val thread = new Thread(r) thread.setName(name + "-" + thread.getId) diff --git a/monix-execution/shared/src/main/scala_2.13-/monix/execution/compat.scala b/monix-execution/shared/src/main/scala_2.13-/monix/execution/compat.scala deleted file mode 100644 index 44487e7a3..000000000 --- a/monix-execution/shared/src/main/scala_2.13-/monix/execution/compat.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2014-2021 by The Monix Project Developers. - * See the project homepage at: https://monix.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package monix.execution - -import scala.collection.generic.CanBuildFrom -import scala.collection.mutable - -object compat { - - type BuildFrom[-From, -A, +C] = CanBuildFrom[From, A, C] - - private[monix] object internal { - type IterableOnce[+X] = scala.collection.GenTraversableOnce[X] - def toIterator[X](i: IterableOnce[X]): Iterator[X] = i.toIterator - def hasDefiniteSize[X](i: IterableOnce[X]): Boolean = i.hasDefiniteSize - - def newBuilder[From, A, C](bf: BuildFrom[From, A, C], from: From): mutable.Builder[A, C] = bf.apply(from) - - def toSeq[A](array: Array[AnyRef]): Seq[A] = - new scala.collection.mutable.WrappedArray.ofRef(array).toSeq.asInstanceOf[Seq[A]] - } - - private[monix] object Features { - type Flag <: Long with monix.execution.Features.FlagTag - - type Flags <: Long with monix.execution.Features.FlagsTag - } -} diff --git a/project/MimaFilters.scala b/project/MimaFilters.scala index 491aa12a2..48a1ae9f5 100644 --- a/project/MimaFilters.scala +++ b/project/MimaFilters.scala @@ -100,4 +100,11 @@ object MimaFilters { // Scala 3 / Dotty support exclude[MissingClassProblem]("monix.execution.schedulers.AdaptedThreadPoolExecutorMixin") ) + + lazy val changesFor_avs = Seq( + // TrampolineExecutionContext signature tweaks (internal API) + exclude[IncompatibleMethTypeProblem]("monix.execution.schedulers.TrampolineExecutionContext#JVMNormalTrampoline.startLoop"), + exclude[IncompatibleMethTypeProblem]("monix.execution.schedulers.TrampolineExecutionContext#JVMOptimalTrampoline.startLoop"), + exclude[IncompatibleMethTypeProblem]("monix.execution.schedulers.TrampolineExecutionContext.this") + ) }