diff --git a/build.sbt b/build.sbt index 64b8d059..28987aba 100644 --- a/build.sbt +++ b/build.sbt @@ -419,6 +419,7 @@ lazy val stm = crossProject(JVMPlatform, JSPlatform) // there is no backward compat for `choam-stm`: ProblemFilters.exclude[ReversedMissingMethodProblem]("dev.tauri.choam.stm.TRef.update"), ProblemFilters.exclude[ReversedMissingMethodProblem]("dev.tauri.choam.stm.TRef.modify"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("dev.tauri.choam.stm.TRef.getAndSet"), ), ) diff --git a/stm/js/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala b/stm/js/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala index 143d0671..79638718 100644 --- a/stm/js/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala +++ b/stm/js/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala @@ -109,6 +109,9 @@ private final class TRefImpl[F[_], A]( final override def modify[B](f: A => (A, B)): Txn[F, B] = core.Rxn.loc.upd[A, Any, B](this) { (ov, _) => f(ov) }.castF[F] + final override def getAndSet(a: A): Txn[F, A] = + this.modify { ov => (a, ov) } + final override def hashCode: Int = { // `RefIdGen` generates IDs with // Fibonacci hashing, so no need diff --git a/stm/jvm/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala b/stm/jvm/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala index 4b146328..e64d3f83 100644 --- a/stm/jvm/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala +++ b/stm/jvm/src/main/scala/dev/tauri/choam/stm/TRefImpl.scala @@ -98,6 +98,9 @@ private final class TRefImpl[F[_], A]( final override def modify[B](f: A => (A, B)): Txn[F, B] = core.Rxn.loc.upd[A, Any, B](this) { (ov, _) => f(ov) }.castF[F] + final override def getAndSet(a: A): Txn[F, A] = + this.modify { ov => (a, ov) } + final override def hashCode: Int = { // `RefIdGen` generates IDs with // Fibonacci hashing, so no need diff --git a/stm/shared/src/main/scala/dev/tauri/choam/stm/TRef.scala b/stm/shared/src/main/scala/dev/tauri/choam/stm/TRef.scala index d76f9b1d..d59c7c8c 100644 --- a/stm/shared/src/main/scala/dev/tauri/choam/stm/TRef.scala +++ b/stm/shared/src/main/scala/dev/tauri/choam/stm/TRef.scala @@ -23,6 +23,7 @@ sealed trait TRef[F[_], A] { def set(a: A): Txn[F, Unit] def update(f: A => A): Txn[F, Unit] def modify[B](f: A => (A, B)): Txn[F, B] + def getAndSet(a: A): Txn[F, A] } object TRef { diff --git a/stm/shared/src/test/scala/dev/tauri/choam/stm/TxnSpec.scala b/stm/shared/src/test/scala/dev/tauri/choam/stm/TxnSpec.scala index 9b1189ea..f2263336 100644 --- a/stm/shared/src/test/scala/dev/tauri/choam/stm/TxnSpec.scala +++ b/stm/shared/src/test/scala/dev/tauri/choam/stm/TxnSpec.scala @@ -223,6 +223,14 @@ trait TxnSpec[F[_]] extends TxnBaseSpec[F] { this: McasImplSpec => _ <- assertResultF(r.get.commit, 1) } yield () } + + test("TRef#getAndSet") { + for { + r <- TRef[F, Int](0).commit + _ <- assertResultF(r.getAndSet(42).commit, 0) + _ <- assertResultF(r.get.commit, 42) + } yield () + } } trait TxnSpecTicked[F[_]] extends TxnBaseSpec[F] with TestContextSpec[F] { this: McasImplSpec =>