From 800840719f54e67ce25e59ff7fc691ff6055e478 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 27 Apr 2011 16:52:19 +0200 Subject: [PATCH] Making it impossible to complete a future after it`s expired, and not run onComplete callbacks if it hasn`t been completed before expiry, fixing ticket #811 --- .../src/test/scala/akka/dispatch/FutureSpec.scala | 14 ++++++++++++++ .../src/main/scala/akka/dispatch/Future.scala | 8 +++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala b/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala index bc60f7762f..7ec397025e 100644 --- a/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala @@ -343,6 +343,20 @@ class FutureSpec extends JUnitSuite { } } + @Test def shouldNotAddOrRunCallbacksAfterFailureToBeCompletedBeforeExpiry { + val latch = new StandardLatch + val f = new DefaultCompletableFuture[Int](0) + Thread.sleep(25) + f.onComplete( _ => latch.open ) //Shouldn't throw any exception here + + assert(f.isExpired) //Should be expired + + f.complete(Right(1)) //Shouldn't complete the Future since it is expired + + assert(f.value.isEmpty) //Shouldn't be completed + assert(!latch.isOpen) //Shouldn't run the listener + } + @Test def lesslessIsMore { import akka.actor.Actor.spawn val dataflowVar, dataflowVar2 = new DefaultCompletableFuture[Int](Long.MaxValue) diff --git a/akka-actor/src/main/scala/akka/dispatch/Future.scala b/akka-actor/src/main/scala/akka/dispatch/Future.scala index a2d5a63697..1f2c8d63e4 100644 --- a/akka-actor/src/main/scala/akka/dispatch/Future.scala +++ b/akka-actor/src/main/scala/akka/dispatch/Future.scala @@ -664,7 +664,7 @@ class DefaultCompletableFuture[T](timeout: Long, timeunit: TimeUnit) extends Com def complete(value: Either[Throwable, T]): DefaultCompletableFuture[T] = { _lock.lock val notifyTheseListeners = try { - if (_value.isEmpty) { + if (_value.isEmpty && !isExpired) { //Only complete if we aren't expired _value = Some(value) val existingListeners = _listeners _listeners = Nil @@ -685,8 +685,10 @@ class DefaultCompletableFuture[T](timeout: Long, timeunit: TimeUnit) extends Com _lock.lock val notifyNow = try { if (_value.isEmpty) { - _listeners ::= func - false + if(!isExpired) { //Only add the listener if the future isn't expired + _listeners ::= func + false + } else false //Will never run the callback since the future is expired } else true } finally { _lock.unlock