Iteratees是否可以安全地管理资源?

时间:2014-07-26 22:35:23

标签: scala playframework-2.1 iterate resource-management

假设我正在阅读InputStream

我通常如何做到这一点:

val inputStream = ...
try {
    doStuff(inputStream)
} finally {
    inputStream.close()
}

doStuff是否会引发异常,我们会关闭InputStream


我将如何使用iteratees:

val inputStream ...
Enumerator.fromStream(inputStream)(Iteratee.foreach(doStuff))

InputStream是否会被关闭(即使doStuff会引发异常)?

一点点测试:

val inputStream = new InputStream() { // returns 10, 9, ... 0, -1
    private var i = 10
    def read() = {
       i = math.max(0, i) - 1
       i
    }
    override def close() = println("closed") // looking for this
}
Enumerator.fromStream(inputStream)(Iteratee.foreach(a => 1 / 0)).onComplete(println)

我们只看到:

Failure(java.lang.ArithmeticException: / by zero)

流从未关闭过。将1 / 0替换为1 / 1,您会看到该流已关闭。

当然,我可以保留对原始流的引用并在发生故障时关闭它,但AFAIK使用iteratees的想法是创建可组合迭代而不必这样做。


  1. 这是预期的行为吗?

  2. 有没有办法使用iteratees,所以资源总是正确处理?

1 个答案:

答案 0 :(得分:2)

Iteratees专为安全资源管理而设计。请参阅 Iteratee IO: safe, practical, declarative input processing 的第一句话:

  

Iteratee IO是一种增量输入处理方式,具有精确的资源控制。

这个想法是,当你的资源只能通过iteratees访问时,拥有资源的代码可以准确地告诉iteratee何时完成资源并立即关闭它。另一方面,当手动管理迭代时(与传统的InputStream一样),资源的用户负责关闭它。这可能导致泄漏。

说,Play 2.1中有一个错误fromStream没有管理其底层InputStream的关闭!这个错误已在Play 2.2中修复。

您可以看到fromStream code,以便在迭代完成后使用Enumerator关闭资源来查看onDoneEnumerating是如何修复的。