diff --git a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/ActorTestKit.scala b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/ActorTestKit.scala index f8503872a2c..6b067707564 100644 --- a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/ActorTestKit.scala +++ b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/ActorTestKit.scala @@ -44,7 +44,7 @@ object ActorTestKit { * using default configuration from the reference.conf resources that ship with the Akka libraries. * The application.conf of your project is not used in this case. */ - def create(): ActorTestKit = + @noinline def create(): ActorTestKit = new ActorTestKit(scaladsl.ActorTestKit(TestKitUtils.testNameFromCallStack(classOf[ActorTestKit]))) /** @@ -83,7 +83,7 @@ object ActorTestKit { * When the test has completed you should terminate the `ActorSystem` and * the testkit with [[ActorTestKit#shutdownTestKit]]. */ - def create(customConfig: Config): ActorTestKit = + @noinline def create(customConfig: Config): ActorTestKit = new ActorTestKit(scaladsl.ActorTestKit(TestKitUtils.testNameFromCallStack(classOf[ActorTestKit]), customConfig)) /** diff --git a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/TestKitJunitResource.scala b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/TestKitJunitResource.scala index 72f7e14d323..ad7e445b6bb 100644 --- a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/TestKitJunitResource.scala +++ b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/TestKitJunitResource.scala @@ -66,7 +66,7 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource { * using default configuration from the reference.conf resources that ship with the Akka libraries. * The application.conf of your project is not used in this case. */ - def this() = this(ActorTestKit.create(TestKitUtils.testNameFromCallStack(classOf[TestKitJunitResource]))) + @noinline def this() = this(ActorTestKit.create(TestKitUtils.testNameFromCallStack(classOf[TestKitJunitResource]))) /** * Use a custom [[pekko.actor.typed.ActorSystem]] for the actor system. @@ -76,7 +76,7 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource { /** * Use a custom config for the actor system. */ - def this(customConfig: String) = + @noinline def this(customConfig: String) = this( ActorTestKit.create( TestKitUtils.testNameFromCallStack(classOf[TestKitJunitResource]), @@ -85,13 +85,13 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource { /** * Use a custom config for the actor system. */ - def this(customConfig: Config) = + @noinline def this(customConfig: Config) = this(ActorTestKit.create(TestKitUtils.testNameFromCallStack(classOf[TestKitJunitResource]), customConfig)) /** * Use a custom config for the actor system, and a custom [[pekko.actor.testkit.typed.TestKitSettings]]. */ - def this(customConfig: Config, settings: TestKitSettings) = + @noinline def this(customConfig: Config, settings: TestKitSettings) = this(ActorTestKit.create(TestKitUtils.testNameFromCallStack(classOf[TestKitJunitResource]), customConfig, settings)) @Rule diff --git a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKit.scala b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKit.scala index 540998d2a8f..ffad923a50d 100644 --- a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKit.scala +++ b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKit.scala @@ -57,7 +57,7 @@ object ActorTestKit { * using default configuration from the reference.conf resources that ship with the Akka libraries. * The application.conf of your project is not used in this case. */ - def apply(): ActorTestKit = { + @noinline def apply(): ActorTestKit = { val system = ActorSystem( ActorTestKitGuardian.testKitGuardian, TestKitUtils.testNameFromCallStack(classOf[ActorTestKit]), @@ -111,7 +111,7 @@ object ActorTestKit { * When the test has completed you should terminate the `ActorSystem` and * the testkit with [[ActorTestKit#shutdownTestKit]]. */ - def apply(customConfig: Config): ActorTestKit = { + @noinline def apply(customConfig: Config): ActorTestKit = { val system = ActorSystem( ActorTestKitGuardian.testKitGuardian, TestKitUtils.testNameFromCallStack(classOf[ActorTestKit]), diff --git a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKitBase.scala b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKitBase.scala index 0d480148f04..a9f6b1afe57 100644 --- a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKitBase.scala +++ b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/ActorTestKitBase.scala @@ -29,7 +29,7 @@ import pekko.actor.typed.Props import pekko.util.Timeout object ActorTestKitBase { - def testNameFromCallStack(): String = TestKitUtils.testNameFromCallStack(classOf[ActorTestKitBase]) + @noinline def testNameFromCallStack(): String = TestKitUtils.testNameFromCallStack(classOf[ActorTestKitBase]) } /** diff --git a/actor/src/main/mima-filters/1.1.0.backwards.excludes/future-converters.excludes b/actor/src/main/mima-filters/1.1.0.backwards.excludes/future-converters.excludes new file mode 100644 index 00000000000..bf0a9e2c4b9 --- /dev/null +++ b/actor/src/main/mima-filters/1.1.0.backwards.excludes/future-converters.excludes @@ -0,0 +1,6 @@ +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.FutureConverters#CompletionStageOps.asScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.FutureConverters#CompletionStageOps.asScala") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.FutureConverters#CompletionStageOps.asScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.FutureConverters#FutureOps.asJava$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.FutureConverters#FutureOps.asJava") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.FutureConverters#FutureOps.asJava$extension") diff --git a/actor/src/main/mima-filters/1.1.0.backwards.excludes/option-converters.excludes b/actor/src/main/mima-filters/1.1.0.backwards.excludes/option-converters.excludes new file mode 100644 index 00000000000..3815de9f40a --- /dev/null +++ b/actor/src/main/mima-filters/1.1.0.backwards.excludes/option-converters.excludes @@ -0,0 +1,30 @@ +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOption.toJava$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOption.toJavaPrimitive$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOption.toJava") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOption.toJavaPrimitive") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOption.toJava$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOption.toJavaPrimitive$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptional.toJavaPrimitive$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptional.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptional.toScala") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptional.toJavaPrimitive") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptional.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptional.toJavaPrimitive$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalDouble.toJavaGeneric$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalDouble.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalDouble.toScala") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalDouble.toJavaGeneric") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalDouble.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalDouble.toJavaGeneric$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalInt.toJavaGeneric$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalInt.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalInt.toScala") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalInt.toJavaGeneric") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalInt.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalInt.toJavaGeneric$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalLong.toJavaGeneric$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalLong.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalLong.toScala") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalLong.toJavaGeneric") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalLong.toScala$extension") +ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.util.OptionConverters#RichOptionalLong.toJavaGeneric$extension") diff --git a/actor/src/main/scala-2.12/org/apache/pekko/util/ByteIterator.scala b/actor/src/main/scala-2.12/org/apache/pekko/util/ByteIterator.scala index 150fa32af86..e172cb8298e 100644 --- a/actor/src/main/scala-2.12/org/apache/pekko/util/ByteIterator.scala +++ b/actor/src/main/scala-2.12/org/apache/pekko/util/ByteIterator.scala @@ -38,11 +38,11 @@ object ByteIterator { extends ByteIterator { iterator => - @inline final def len: Int = until - from + final def len: Int = until - from - @inline final def hasNext: Boolean = from < until + final def hasNext: Boolean = from < until - @inline final def head: Byte = array(from) + final def head: Byte = array(from) final def next(): Byte = { if (!hasNext) EmptyImmutableSeq.iterator.next() @@ -206,13 +206,13 @@ object ByteIterator { } normalize() - @inline private def current: ByteArrayIterator = iterators.head - @inline private def dropCurrent(): Unit = { iterators = iterators.tail } - @inline final def clear(): Unit = { iterators = MultiByteArrayIterator.empty.iterators } + private def current: ByteArrayIterator = iterators.head + private def dropCurrent(): Unit = { iterators = iterators.tail } + final def clear(): Unit = { iterators = MultiByteArrayIterator.empty.iterators } - @inline final def hasNext: Boolean = current.hasNext + final def hasNext: Boolean = current.hasNext - @inline final def head: Byte = current.head + final def head: Byte = current.head final def next(): Byte = { val result = current.next() diff --git a/actor/src/main/scala-2.12/org/apache/pekko/util/ByteString.scala b/actor/src/main/scala-2.12/org/apache/pekko/util/ByteString.scala index 14a93a99873..06f7779c941 100644 --- a/actor/src/main/scala-2.12/org/apache/pekko/util/ByteString.scala +++ b/actor/src/main/scala-2.12/org/apache/pekko/util/ByteString.scala @@ -1047,7 +1047,7 @@ final class ByteStringBuilder extends Builder[Byte, ByteString] { this } - @inline protected final def fillByteBuffer(len: Int, byteOrder: ByteOrder)(fill: ByteBuffer => Unit): this.type = { + protected final def fillByteBuffer(len: Int, byteOrder: ByteOrder)(fill: ByteBuffer => Unit): this.type = { fillArray(len) { case (array, start) => val buffer = ByteBuffer.wrap(array, start, len) @@ -1078,7 +1078,7 @@ final class ByteStringBuilder extends Builder[Byte, ByteString] { _tempCapacity = _temp.length } - @inline private def shouldResizeTempFor(size: Int): Boolean = _tempCapacity < size || _tempCapacity == 0 + private def shouldResizeTempFor(size: Int): Boolean = _tempCapacity < size || _tempCapacity == 0 private def ensureTempSize(size: Int): Unit = { if (shouldResizeTempFor(size)) { diff --git a/actor/src/main/scala-2.13/org/apache/pekko/util/ByteIterator.scala b/actor/src/main/scala-2.13/org/apache/pekko/util/ByteIterator.scala index 5965345199e..fccd69fa0c4 100644 --- a/actor/src/main/scala-2.13/org/apache/pekko/util/ByteIterator.scala +++ b/actor/src/main/scala-2.13/org/apache/pekko/util/ByteIterator.scala @@ -39,11 +39,11 @@ object ByteIterator { extends ByteIterator { iterator => - @inline final def len: Int = until - from + final def len: Int = until - from - @inline final def hasNext: Boolean = from < until + final def hasNext: Boolean = from < until - @inline final def head: Byte = array(from) + final def head: Byte = array(from) final def next(): Byte = { if (!hasNext) EmptyImmutableSeq.iterator.next() @@ -218,13 +218,13 @@ object ByteIterator { } normalize() - @inline private def current: ByteArrayIterator = iterators.head - @inline private def dropCurrent(): Unit = { iterators = iterators.tail } - @inline final def clear(): Unit = { iterators = MultiByteArrayIterator.empty.iterators } + private def current: ByteArrayIterator = iterators.head + private def dropCurrent(): Unit = { iterators = iterators.tail } + final def clear(): Unit = { iterators = MultiByteArrayIterator.empty.iterators } - @inline final def hasNext: Boolean = current.hasNext + final def hasNext: Boolean = current.hasNext - @inline final def head: Byte = current.head + final def head: Byte = current.head final def next(): Byte = { val result = current.next() diff --git a/actor/src/main/scala-2.13/org/apache/pekko/util/ByteString.scala b/actor/src/main/scala-2.13/org/apache/pekko/util/ByteString.scala index 41696881436..a03fac661af 100644 --- a/actor/src/main/scala-2.13/org/apache/pekko/util/ByteString.scala +++ b/actor/src/main/scala-2.13/org/apache/pekko/util/ByteString.scala @@ -1097,7 +1097,7 @@ final class ByteStringBuilder extends Builder[Byte, ByteString] { this } - @inline protected final def fillByteBuffer(len: Int, byteOrder: ByteOrder)(fill: ByteBuffer => Unit): this.type = { + protected final def fillByteBuffer(len: Int, byteOrder: ByteOrder)(fill: ByteBuffer => Unit): this.type = { fillArray(len) { case (array, start) => val buffer = ByteBuffer.wrap(array, start, len) @@ -1128,7 +1128,7 @@ final class ByteStringBuilder extends Builder[Byte, ByteString] { _tempCapacity = _temp.length } - @inline private def shouldResizeTempFor(size: Int): Boolean = _tempCapacity < size || _tempCapacity == 0 + private def shouldResizeTempFor(size: Int): Boolean = _tempCapacity < size || _tempCapacity == 0 private def ensureTempSize(size: Int): Unit = { if (shouldResizeTempFor(size)) { diff --git a/actor/src/main/scala-2.13+/org/apache/pekko/util/FutureConverters.scala b/actor/src/main/scala-2.13/org/apache/pekko/util/FutureConverters.scala similarity index 100% rename from actor/src/main/scala-2.13+/org/apache/pekko/util/FutureConverters.scala rename to actor/src/main/scala-2.13/org/apache/pekko/util/FutureConverters.scala diff --git a/actor/src/main/scala-2.13+/org/apache/pekko/util/OptionConverters.scala b/actor/src/main/scala-2.13/org/apache/pekko/util/OptionConverters.scala similarity index 100% rename from actor/src/main/scala-2.13+/org/apache/pekko/util/OptionConverters.scala rename to actor/src/main/scala-2.13/org/apache/pekko/util/OptionConverters.scala diff --git a/actor/src/main/scala-3/org/apache/pekko/util/ByteIterator.scala b/actor/src/main/scala-3/org/apache/pekko/util/ByteIterator.scala index c4eed52125d..92f57e10f9f 100644 --- a/actor/src/main/scala-3/org/apache/pekko/util/ByteIterator.scala +++ b/actor/src/main/scala-3/org/apache/pekko/util/ByteIterator.scala @@ -39,11 +39,11 @@ object ByteIterator { extends ByteIterator { iterator => - @inline final def len: Int = until - from + final def len: Int = until - from - @inline final def hasNext: Boolean = from < until + final def hasNext: Boolean = from < until - @inline final def head: Byte = array(from) + final def head: Byte = array(from) final def next(): Byte = { if (!hasNext) EmptyImmutableSeq.iterator.next() @@ -215,13 +215,13 @@ object ByteIterator { } normalize() - @inline private def current: ByteArrayIterator = iterators.head - @inline private def dropCurrent(): Unit = { iterators = iterators.tail } - @inline def clear(): Unit = { iterators = MultiByteArrayIterator.empty.iterators } + private def current: ByteArrayIterator = iterators.head + private def dropCurrent(): Unit = { iterators = iterators.tail } + def clear(): Unit = { iterators = MultiByteArrayIterator.empty.iterators } - @inline final def hasNext: Boolean = current.hasNext + final def hasNext: Boolean = current.hasNext - @inline final def head: Byte = current.head + final def head: Byte = current.head final def next(): Byte = { val result = current.next() diff --git a/actor/src/main/scala-3/org/apache/pekko/util/ByteString.scala b/actor/src/main/scala-3/org/apache/pekko/util/ByteString.scala index 077a69770e3..9dfa1990f70 100644 --- a/actor/src/main/scala-3/org/apache/pekko/util/ByteString.scala +++ b/actor/src/main/scala-3/org/apache/pekko/util/ByteString.scala @@ -1097,7 +1097,7 @@ final class ByteStringBuilder extends Builder[Byte, ByteString] { this } - @inline protected final def fillByteBuffer(len: Int, byteOrder: ByteOrder)(fill: ByteBuffer => Unit): this.type = { + protected final def fillByteBuffer(len: Int, byteOrder: ByteOrder)(fill: ByteBuffer => Unit): this.type = { fillArray(len) { case (array, start) => val buffer = ByteBuffer.wrap(array, start, len) @@ -1128,7 +1128,7 @@ final class ByteStringBuilder extends Builder[Byte, ByteString] { _tempCapacity = _temp.length } - @inline private def shouldResizeTempFor(size: Int): Boolean = _tempCapacity < size || _tempCapacity == 0 + private def shouldResizeTempFor(size: Int): Boolean = _tempCapacity < size || _tempCapacity == 0 private def ensureTempSize(size: Int): Unit = { if (shouldResizeTempFor(size)) { diff --git a/actor/src/main/scala-3/org/apache/pekko/util/FutureConverters.scala b/actor/src/main/scala-3/org/apache/pekko/util/FutureConverters.scala new file mode 100644 index 00000000000..b3b8e63c9b8 --- /dev/null +++ b/actor/src/main/scala-3/org/apache/pekko/util/FutureConverters.scala @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * license agreements; and to You under the Apache License, version 2.0: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * This file is part of the Apache Pekko project, derived from Akka. + */ + +package org.apache.pekko.util + +import org.apache.pekko.annotation.InternalStableApi + +import java.util.concurrent.CompletionStage +import scala.concurrent.Future + +/** + * INTERNAL API + * + * Remove this once Scala 2.12 support is dropped since all methods are in Scala 2.13+ stdlib + */ +@InternalStableApi +private[pekko] object FutureConverters { + import scala.jdk.javaapi + + def asJava[T](f: Future[T]): CompletionStage[T] = javaapi.FutureConverters.asJava(f) + + implicit final class FutureOps[T](private val f: Future[T]) extends AnyVal { + inline def asJava: CompletionStage[T] = FutureConverters.asJava(f) + } + + def asScala[T](cs: CompletionStage[T]): Future[T] = javaapi.FutureConverters.asScala(cs) + + implicit final class CompletionStageOps[T](private val cs: CompletionStage[T]) extends AnyVal { + inline def asScala: Future[T] = FutureConverters.asScala(cs) + } +} diff --git a/actor/src/main/scala-3/org/apache/pekko/util/OptionConverters.scala b/actor/src/main/scala-3/org/apache/pekko/util/OptionConverters.scala new file mode 100644 index 00000000000..2f2fef5c378 --- /dev/null +++ b/actor/src/main/scala-3/org/apache/pekko/util/OptionConverters.scala @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * license agreements; and to You under the Apache License, version 2.0: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * This file is part of the Apache Pekko project, derived from Akka. + */ + +package org.apache.pekko.util + +import org.apache.pekko.annotation.InternalStableApi + +import java.util._ +import scala.jdk.OptionShape + +/** + * INTERNAL API + * + * Remove this once Scala 2.12 support is dropped since all methods are in Scala 2.13+ stdlib + */ +@InternalStableApi +private[pekko] object OptionConverters { + + inline final def toScala[A](o: Optional[A]): Option[A] = scala.jdk.javaapi.OptionConverters.toScala(o) + + inline def toScala(o: OptionalDouble): Option[java.lang.Double] = scala.jdk.javaapi.OptionConverters.toScala(o) + + inline def toScala(o: OptionalInt): Option[java.lang.Integer] = scala.jdk.javaapi.OptionConverters.toScala(o) + + inline def toScala(o: OptionalLong): Option[java.lang.Long] = scala.jdk.javaapi.OptionConverters.toScala(o) + + inline final def toJava[A](o: Option[A]): Optional[A] = scala.jdk.javaapi.OptionConverters.toJava(o) + + implicit final class RichOptional[A](private val o: java.util.Optional[A]) extends AnyVal { + inline def toScala: Option[A] = scala.jdk.OptionConverters.RichOptional(o).toScala + + inline def toJavaPrimitive[O](implicit shape: OptionShape[A, O]): O = + scala.jdk.OptionConverters.RichOptional(o).toJavaPrimitive + } + + implicit final class RichOption[A](private val o: Option[A]) extends AnyVal { + inline def toJava: Optional[A] = scala.jdk.OptionConverters.RichOption(o).toJava + + inline def toJavaPrimitive[O](implicit shape: OptionShape[A, O]): O = + scala.jdk.OptionConverters.RichOption(o).toJavaPrimitive + } + + implicit class RichOptionalDouble(private val o: OptionalDouble) extends AnyVal { + + /** Convert a Java `OptionalDouble` to a Scala `Option` */ + inline def toScala: Option[Double] = scala.jdk.OptionConverters.RichOptionalDouble(o).toScala + + /** Convert a Java `OptionalDouble` to a generic Java `Optional` */ + inline def toJavaGeneric: Optional[Double] = scala.jdk.OptionConverters.RichOptionalDouble(o).toJavaGeneric + } + + /** Provides conversions from `OptionalInt` to Scala `Option` and the generic `Optional` */ + implicit class RichOptionalInt(private val o: OptionalInt) extends AnyVal { + + /** Convert a Java `OptionalInt` to a Scala `Option` */ + inline def toScala: Option[Int] = scala.jdk.OptionConverters.RichOptionalInt(o).toScala + + /** Convert a Java `OptionalInt` to a generic Java `Optional` */ + inline def toJavaGeneric: Optional[Int] = scala.jdk.OptionConverters.RichOptionalInt(o).toJavaGeneric + } + + /** Provides conversions from `OptionalLong` to Scala `Option` and the generic `Optional` */ + implicit class RichOptionalLong(private val o: OptionalLong) extends AnyVal { + + /** Convert a Java `OptionalLong` to a Scala `Option` */ + inline def toScala: Option[Long] = scala.jdk.OptionConverters.RichOptionalLong(o).toScala + + /** Convert a Java `OptionalLong` to a generic Java `Optional` */ + inline def toJavaGeneric: Optional[Long] = scala.jdk.OptionConverters.RichOptionalLong(o).toJavaGeneric + } +} diff --git a/actor/src/main/scala/org/apache/pekko/actor/ActorSystem.scala b/actor/src/main/scala/org/apache/pekko/actor/ActorSystem.scala index b91961d07d5..945a3bd58d1 100644 --- a/actor/src/main/scala/org/apache/pekko/actor/ActorSystem.scala +++ b/actor/src/main/scala/org/apache/pekko/actor/ActorSystem.scala @@ -860,7 +860,6 @@ private[pekko] class ActorSystemImpl( } } - @inline private def logFatalError(message: String, cause: Throwable, thread: Thread): Unit = { // First log to stderr as this has the best chance to get through in an 'emergency panic' situation: import System.err diff --git a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala index 9988d06c12b..00e9fd00ed5 100644 --- a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala +++ b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala @@ -148,7 +148,7 @@ private[pekko] trait Children { this: ActorCell => /* * low level CAS helpers */ - @inline private final def swapChildrenRefs(oldChildren: ChildrenContainer, newChildren: ChildrenContainer): Boolean = + private final def swapChildrenRefs(oldChildren: ChildrenContainer, newChildren: ChildrenContainer): Boolean = Unsafe.instance.compareAndSwapObject(this, AbstractActorCell.childrenOffset, oldChildren, newChildren) @tailrec final def reserveChild(name: String): Boolean = { diff --git a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala index 4485b071478..99211122951 100644 --- a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala +++ b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala @@ -52,7 +52,7 @@ private[pekko] trait Dispatch { this: ActorCell => _mailboxDoNotCallMeDirectly } - @inline final def mailbox: Mailbox = + final def mailbox: Mailbox = Unsafe.instance.getObjectVolatile(this, AbstractActorCell.mailboxOffset).asInstanceOf[Mailbox] @tailrec final def swapMailbox(newMailbox: Mailbox): Mailbox = { diff --git a/actor/src/main/scala/org/apache/pekko/actor/package.scala b/actor/src/main/scala/org/apache/pekko/actor/package.scala index c0734cf0083..6947d640d13 100644 --- a/actor/src/main/scala/org/apache/pekko/actor/package.scala +++ b/actor/src/main/scala/org/apache/pekko/actor/package.scala @@ -17,7 +17,7 @@ import language.implicitConversions package object actor { @deprecated("implicit conversion is obsolete", "Akka 2.6.13") - @inline implicit final def actorRef2Scala(ref: ActorRef): ScalaActorRef = ref.asInstanceOf[ScalaActorRef] + implicit final def actorRef2Scala(ref: ActorRef): ScalaActorRef = ref.asInstanceOf[ScalaActorRef] @deprecated("implicit conversion is obsolete", "Akka 2.6.13") - @inline implicit final def scala2ActorRef(ref: ScalaActorRef): ActorRef = ref.asInstanceOf[ActorRef] + implicit final def scala2ActorRef(ref: ScalaActorRef): ActorRef = ref.asInstanceOf[ActorRef] } diff --git a/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala b/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala index 08afe54e947..9e6f2af1afb 100644 --- a/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala +++ b/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala @@ -329,7 +329,7 @@ abstract class MessageDispatcher(val configurator: MessageDispatcherConfigurator /** * INTERNAL API */ - @inline protected[pekko] final val isThroughputDeadlineTimeDefined = throughputDeadlineTime.toMillis > 0 + protected[pekko] final val isThroughputDeadlineTimeDefined = throughputDeadlineTime.toMillis > 0 /** * INTERNAL API diff --git a/actor/src/main/scala/org/apache/pekko/dispatch/Mailbox.scala b/actor/src/main/scala/org/apache/pekko/dispatch/Mailbox.scala index 088a0a33e64..b9df8ee00d7 100644 --- a/actor/src/main/scala/org/apache/pekko/dispatch/Mailbox.scala +++ b/actor/src/main/scala/org/apache/pekko/dispatch/Mailbox.scala @@ -121,29 +121,21 @@ private[pekko] abstract class Mailbox(val messageQueue: MessageQueue) @volatile protected var _systemQueueDoNotCallMeDirectly: SystemMessage = _ // null by default - @inline final def currentStatus: Mailbox.Status = Unsafe.instance.getIntVolatile(this, AbstractMailbox.mailboxStatusOffset) - @inline final def shouldProcessMessage: Boolean = (currentStatus & shouldNotProcessMask) == 0 - @inline final def suspendCount: Int = currentStatus / suspendUnit - @inline final def isSuspended: Boolean = (currentStatus & suspendMask) != 0 - @inline final def isClosed: Boolean = currentStatus == Closed - @inline final def isScheduled: Boolean = (currentStatus & Scheduled) != 0 - @inline protected final def updateStatus(oldStatus: Status, newStatus: Status): Boolean = Unsafe.instance.compareAndSwapInt(this, AbstractMailbox.mailboxStatusOffset, oldStatus, newStatus) - @inline protected final def setStatus(newStatus: Status): Unit = Unsafe.instance.putIntVolatile(this, AbstractMailbox.mailboxStatusOffset, newStatus) diff --git a/actor/src/main/scala/org/apache/pekko/dispatch/affinity/AffinityPool.scala b/actor/src/main/scala/org/apache/pekko/dispatch/affinity/AffinityPool.scala index f83b5a456ae..256a1686733 100644 --- a/actor/src/main/scala/org/apache/pekko/dispatch/affinity/AffinityPool.scala +++ b/actor/src/main/scala/org/apache/pekko/dispatch/affinity/AffinityPool.scala @@ -72,7 +72,7 @@ private[affinity] object AffinityPool { private[this] var parkPeriodNs = 0L @volatile private[this] var idling = false - @inline private[this] def transitionTo(newState: IdleState): Unit = { + private[this] def transitionTo(newState: IdleState): Unit = { state = newState turns = 0 } diff --git a/actor/src/main/scala/org/apache/pekko/event/Logging.scala b/actor/src/main/scala/org/apache/pekko/event/Logging.scala index 50c5bd5c1b6..2a9bb428203 100644 --- a/actor/src/main/scala/org/apache/pekko/event/Logging.scala +++ b/actor/src/main/scala/org/apache/pekko/event/Logging.scala @@ -485,10 +485,10 @@ object Logging { * Marker trait for annotating LogLevel, which must be Int after erasure. */ final case class LogLevel(asInt: Int) extends AnyVal { - @inline final def >=(other: LogLevel): Boolean = asInt >= other.asInt - @inline final def <=(other: LogLevel): Boolean = asInt <= other.asInt - @inline final def >(other: LogLevel): Boolean = asInt > other.asInt - @inline final def <(other: LogLevel): Boolean = asInt < other.asInt + final def >=(other: LogLevel): Boolean = asInt >= other.asInt + final def <=(other: LogLevel): Boolean = asInt <= other.asInt + final def >(other: LogLevel): Boolean = asInt > other.asInt + final def <(other: LogLevel): Boolean = asInt < other.asInt } /** diff --git a/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala b/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala index e2ac3da4fc6..1cd660af22f 100644 --- a/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala +++ b/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala @@ -549,11 +549,9 @@ private[pekko] final class PromiseActorRef( _watchedByDoNotCallMeDirectly } - @inline private[this] def watchedBy: Set[ActorRef] = Unsafe.instance.getObjectVolatile(this, watchedByOffset).asInstanceOf[Set[ActorRef]] - @inline private[this] def updateWatchedBy(oldWatchedBy: Set[ActorRef], newWatchedBy: Set[ActorRef]): Boolean = Unsafe.instance.compareAndSwapObject(this, watchedByOffset, oldWatchedBy, newWatchedBy) @@ -575,14 +573,11 @@ private[pekko] final class PromiseActorRef( case other => if (!updateWatchedBy(other, null)) clearWatchers() else other } - @inline private[this] def state: AnyRef = Unsafe.instance.getObjectVolatile(this, stateOffset) - @inline private[this] def updateState(oldState: AnyRef, newState: AnyRef): Boolean = Unsafe.instance.compareAndSwapObject(this, stateOffset, oldState, newState) - @inline private[this] def setState(newState: AnyRef): Unit = Unsafe.instance.putObjectVolatile(this, stateOffset, newState) override def getParent: InternalActorRef = provider.tempContainer diff --git a/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala b/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala index a296c8962fe..18241b70f42 100644 --- a/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala +++ b/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala @@ -317,7 +317,6 @@ class CircuitBreaker( * @param newState Next state on transition * @return Whether the previous state matched correctly */ - @inline private[this] def swapState(oldState: State, newState: State): Boolean = Unsafe.instance.compareAndSwapObject(this, AbstractCircuitBreaker.stateOffset, oldState, newState) @@ -326,14 +325,12 @@ class CircuitBreaker( * * @return Reference to current state */ - @inline private[this] def currentState: State = Unsafe.instance.getObjectVolatile(this, AbstractCircuitBreaker.stateOffset).asInstanceOf[State] /** * Helper method for updating the underlying resetTimeout via Unsafe */ - @inline private[this] def swapResetTimeout(oldResetTimeout: FiniteDuration, newResetTimeout: FiniteDuration): Boolean = Unsafe.instance.compareAndSwapObject( this, @@ -344,7 +341,6 @@ class CircuitBreaker( /** * Helper method for accessing to the underlying resetTimeout via Unsafe */ - @inline private[this] def currentResetTimeout: FiniteDuration = Unsafe.instance.getObjectVolatile(this, AbstractCircuitBreaker.resetTimeoutOffset).asInstanceOf[FiniteDuration] diff --git a/actor/src/main/scala/org/apache/pekko/routing/RouterConfig.scala b/actor/src/main/scala/org/apache/pekko/routing/RouterConfig.scala index ec3e3427a4d..6b5565f38ba 100644 --- a/actor/src/main/scala/org/apache/pekko/routing/RouterConfig.scala +++ b/actor/src/main/scala/org/apache/pekko/routing/RouterConfig.scala @@ -286,13 +286,13 @@ case object FromConfig extends FromConfig { * Java API: get the singleton instance */ def getInstance = this - @inline final def apply( + final def apply( resizer: Option[Resizer] = None, supervisorStrategy: SupervisorStrategy = Pool.defaultSupervisorStrategy, routerDispatcher: String = Dispatchers.DefaultDispatcherId) = new FromConfig(resizer, supervisorStrategy, routerDispatcher) - @inline final def unapply(fc: FromConfig): Option[String] = Some(fc.routerDispatcher) + final def unapply(fc: FromConfig): Option[String] = Some(fc.routerDispatcher) } /** diff --git a/actor/src/main/scala/org/apache/pekko/util/Helpers.scala b/actor/src/main/scala/org/apache/pekko/util/Helpers.scala index 6b00bd58ed9..8e71eea283b 100644 --- a/actor/src/main/scala/org/apache/pekko/util/Helpers.scala +++ b/actor/src/main/scala/org/apache/pekko/util/Helpers.scala @@ -140,7 +140,7 @@ object Helpers { * * @param value The value to check. */ - @inline final implicit class Requiring[A](val value: A) extends AnyVal { + final implicit class Requiring[A](val value: A) extends AnyVal { /** * Check that a condition is true. If true, return `value`, otherwise throw @@ -149,7 +149,7 @@ object Helpers { * @param cond The condition to check. * @param msg The message to report if the condition isn't met. */ - @inline def requiring(cond: Boolean, msg: => Any): A = { + def requiring(cond: Boolean, msg: => Any): A = { require(cond, msg) value } @@ -161,7 +161,7 @@ object Helpers { * @param cond The function used to check the `value`. * @param msg The message to report if the condition isn't met. */ - @inline def requiring(cond: A => Boolean, msg: => Any): A = { + def requiring(cond: A => Boolean, msg: => Any): A = { require(cond(value), msg) value } diff --git a/actor/src/main/scala/org/apache/pekko/util/LockUtil.scala b/actor/src/main/scala/org/apache/pekko/util/LockUtil.scala index af8c069b72f..5c8c834a9a2 100644 --- a/actor/src/main/scala/org/apache/pekko/util/LockUtil.scala +++ b/actor/src/main/scala/org/apache/pekko/util/LockUtil.scala @@ -18,7 +18,6 @@ import java.util.concurrent.locks.ReentrantLock final class ReentrantGuard extends ReentrantLock { - @inline final def withGuard[T](body: => T): T = { lock() try body diff --git a/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/SnapshotStore.scala b/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/SnapshotStore.scala index 8384e95c02b..4d944d93c40 100644 --- a/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/SnapshotStore.scala +++ b/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/SnapshotStore.scala @@ -128,7 +128,7 @@ trait SnapshotStore extends Actor with ActorLogging { } /** Documents intent that the sender() is expected to be the PersistentActor */ - @inline private final def senderPersistentActor(): ActorRef = sender() + private final def senderPersistentActor(): ActorRef = sender() private def tryReceivePluginInternal(evt: Any): Unit = if (receivePluginInternal.isDefinedAt(evt)) receivePluginInternal(evt) diff --git a/project/PekkoInlinePlugin.scala b/project/PekkoInlinePlugin.scala new file mode 100644 index 00000000000..6f99703abcb --- /dev/null +++ b/project/PekkoInlinePlugin.scala @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * license agreements; and to You under the Apache License, version 2.0: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * This file is part of the Apache Pekko project, derived from Akka. + */ + +import sbt.Keys._ +import sbt._ +import sbt.plugins.JvmPlugin + +object PekkoInlinePlugin extends AutoPlugin { + override def trigger: PluginTrigger = allRequirements + + override def requires: Plugins = JvmPlugin + + val enabled = !sys.props.contains("pekko.no.inline") + + private val flagsFor212 = Seq( + "-opt-inline-from:org.apache.pekko.**", + "-opt-inline-from:", + "-opt:l:inline") + + private val flagsFor213 = Seq( + "-opt-inline-from:org.apache.pekko.**", + "-opt-inline-from:", + "-opt:l:inline") + + // Optimizer not yet available for Scala3, see https://docs.scala-lang.org/overviews/compiler-options/optimizer.html + private val flagsFor3 = Seq() + + override lazy val projectSettings = Seq( + Compile / scalacOptions ++= { + if (enabled) { + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, n)) if n == 13 => + flagsFor213 + case Some((2, n)) if n == 12 => + flagsFor212 + case Some((3, _)) => + flagsFor3 + } + } else Seq.empty + }) +} diff --git a/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala b/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala index e44c30140f3..6bf999338ff 100644 --- a/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala +++ b/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala @@ -270,7 +270,6 @@ private[remote] class Association( * @param newState Next state on transition * @return Whether the previous state matched correctly */ - @inline private[artery] def swapState(oldState: AssociationState, newState: AssociationState): Boolean = Unsafe.instance.compareAndSwapObject(this, AbstractAssociation.sharedStateOffset, oldState, newState) diff --git a/remote/src/main/scala/org/apache/pekko/remote/artery/compress/TopHeavyHitters.scala b/remote/src/main/scala/org/apache/pekko/remote/artery/compress/TopHeavyHitters.scala index 47ae15f3553..be6e27f5327 100644 --- a/remote/src/main/scala/org/apache/pekko/remote/artery/compress/TopHeavyHitters.scala +++ b/remote/src/main/scala/org/apache/pekko/remote/artery/compress/TopHeavyHitters.scala @@ -127,8 +127,8 @@ private[remote] final class TopHeavyHitters[T >: Null](val max: Int)(implicit cl v } - @inline private final def index: Int = heap(i) - @inline private final def value: T = { + private final def index: Int = heap(i) + private final def value: T = { val idx = index if (idx < 0) null else items(idx) } diff --git a/slf4j/src/main/scala/org/apache/pekko/event/slf4j/Slf4jLogger.scala b/slf4j/src/main/scala/org/apache/pekko/event/slf4j/Slf4jLogger.scala index 4cbc9a988f5..7fbc1fae372 100644 --- a/slf4j/src/main/scala/org/apache/pekko/event/slf4j/Slf4jLogger.scala +++ b/slf4j/src/main/scala/org/apache/pekko/event/slf4j/Slf4jLogger.scala @@ -118,7 +118,6 @@ class Slf4jLogger extends Actor with SLF4JLogging with RequiresMessageQueue[Logg sender() ! LoggerInitialized } - @inline final def withMdc(logSource: String, logEvent: LogEvent)(logStatement: => Unit): Unit = { logEvent match { case m: LogEventWithMarker if m.marker ne null =>