Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Andrei-Pozolotin/34722d939a32ca4ac792eb92306aac27 to your computer and use it in GitHub Desktop.
Save Andrei-Pozolotin/34722d939a32ca4ac792eb92306aac27 to your computer and use it in GitHub Desktop.
Scoped Implicit Lifetimes

Scoped Implicit Lifetimes

All things considered, our experience in Scala Native has shown that resource management in Scala is way harder than it should be. This gist presents a simple design pattern that makes it resource management absolutely hassle-free: scoped implicit lifetimes.

The main idea behind it is to encode resource lifetimes through a concept of an implicit scope. Scopes are necessary to acquire resources. They are responsible for disposal of the resources once the evaluation exits the demarkated block in the source code.

Use cases

  • File handles
  • Network connections
  • Locks
  • Off-heap memory allocations
  • Thread pools
  • Actor systems
  • OpenGL Contexts
  • ...
import java.io.Closeable
import Resourceful._
object Resourceful {
type Resource = AutoCloseable
@annotation.implicitNotFound(msg = "Resource acquisition requires a scope.")
final class Scope extends Resource {
private[this] var resources: List[Resource] = Nil
final def acquire(res: Resource): Unit = {
resources ::= res
}
final def close(): Unit = resources match {
case Nil =>
()
case first :: rest =>
resources = rest
try first.close()
finally close()
}
}
object Scope {
def apply[T](f: Scope => T): T = {
val scope = new Scope
try f(scope)
finally scope.close()
}
}
def acquire[R <: Resource](res: R)(implicit in: Scope): R = {
in.acquire(res)
res
}
}
class SafeWriter(path: String)(implicit in: Scope) extends Resource {
acquire(this)
println(s"acquired $path")
private val writer = new java.io.PrintWriter(path)
def write(value: String) = writer.write(value)
def close(): Unit = { println(s"releasing $path"); writer.close() }
}
object MyApp extends App {
Scope { implicit in =>
val w1 = new SafeWriter("file1.txt")
w1.write("hello, world!")
val w2 = new SafeWriter("file2.txt")
w2.write("hello, world!")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment