Skip to content

Commit

Permalink
Fixes LAFuture.collect/collectAll behaviour for empty list parameter
Browse files Browse the repository at this point in the history
For empty list parameter, were returned future which never been satisfied.
Now is returned future that is immediately satisfied by empty list.
  • Loading branch information
arkadius committed Jan 6, 2015
1 parent 0e9573e commit b994663
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 37 deletions.
82 changes: 45 additions & 37 deletions core/actor/src/main/scala/net/liftweb/actor/LAFuture.scala
Expand Up @@ -330,25 +330,29 @@ object LAFuture {
* collected futures are satisfied
*/
def collect[T](future: LAFuture[T]*): LAFuture[List[T]] = {
val sync = new Object
val len = future.length
val vals = new collection.mutable.ArrayBuffer[Box[T]](len)
// pad array so inserts at random places are possible
for (i <- 0 to len) { vals.insert(i, Empty) }
var gotCnt = 0
val ret = new LAFuture[List[T]]

future.toList.zipWithIndex.foreach {
case (f, idx) =>
f.foreach {
v => sync.synchronized {
vals.insert(idx, Full(v))
gotCnt += 1
if (gotCnt >= len) {
ret.satisfy(vals.toList.flatten)
if (future.isEmpty) {
ret.satisfy(Nil)
} else {
val sync = new Object
val len = future.length
val vals = new collection.mutable.ArrayBuffer[Box[T]](len)
// pad array so inserts at random places are possible
for (i <- 0 to len) { vals.insert(i, Empty) }
var gotCnt = 0

future.toList.zipWithIndex.foreach {
case (f, idx) =>
f.foreach {
v => sync.synchronized {
vals.insert(idx, Full(v))
gotCnt += 1
if (gotCnt >= len) {
ret.satisfy(vals.toList.flatten)
}
}
}
}
}
}

ret
Expand All @@ -362,33 +366,37 @@ object LAFuture {
* returned future with an Empty
*/
def collectAll[T](future: LAFuture[Box[T]]*): LAFuture[Box[List[T]]] = {
val sync = new Object
val len = future.length
val vals = new collection.mutable.ArrayBuffer[Box[T]](len)
// pad array so inserts at random places are possible
for (i <- 0 to len) { vals.insert(i, Empty) }
var gotCnt = 0
val ret = new LAFuture[Box[List[T]]]
if (future.isEmpty) {
ret.satisfy(Full(Nil))
} else {
val sync = new Object
val len = future.length
val vals = new collection.mutable.ArrayBuffer[Box[T]](len)
// pad array so inserts at random places are possible
for (i <- 0 to len) { vals.insert(i, Empty) }
var gotCnt = 0

future.toList.zipWithIndex.foreach {
case (f, idx) =>
f.foreach {
vb => sync.synchronized {
vb match {
case Full(v) => {
vals.insert(idx, Full(v))
gotCnt += 1
if (gotCnt >= len) {
ret.satisfy(Full(vals.toList.flatten))
}
}

future.toList.zipWithIndex.foreach {
case (f, idx) =>
f.foreach {
vb => sync.synchronized {
vb match {
case Full(v) => {
vals.insert(idx, Full(v))
gotCnt += 1
if (gotCnt >= len) {
ret.satisfy(Full(vals.toList.flatten))
case eb: EmptyBox => {
ret.satisfy(eb)
}
}

case eb: EmptyBox => {
ret.satisfy(eb)
}
}
}
}
}
}

ret
Expand Down
37 changes: 37 additions & 0 deletions core/actor/src/test/scala/net/liftweb/actor/LAFutureSpec.scala
@@ -0,0 +1,37 @@
package net.liftweb.actor

import org.specs2.mutable.Specification

class LAFutureSpec extends Specification {
val timeout = 1000L

"LAFuture" should {

"collect one future result" in {
val givenOneResult = 123
val one = LAFuture(() => givenOneResult)
LAFuture.collect(one).get(timeout) shouldEqual List(givenOneResult)
}

"collect more future results in correct order" in {
val givenOneResult = 123
val givenTwoResult = 234
val one = LAFuture(() => givenOneResult)
val two = LAFuture(() => givenTwoResult)
LAFuture.collect(one, two).get shouldEqual List(givenOneResult, givenTwoResult)
}

"collect empty list immediately" in {
val collectResult = LAFuture.collect(Nil: _*)
collectResult.isSatisfied shouldEqual true
collectResult.get shouldEqual Nil
}

"collectAll empty list immediately" in {
val collectResult = LAFuture.collectAll(Nil : _*)
collectResult.isSatisfied shouldEqual true
collectResult.get shouldEqual Nil
}
}

}

0 comments on commit b994663

Please sign in to comment.