1

I'm developing a Scala library on top of the Java library LWJGL and I'm wondering what is the best approach to handling "deleting" unmanaged resources. For example, consider a (simplified) interface for managing shader objects:

trait ShaderType {
    val glenum : Int
}

case class VertexShader() extends ShaderType {
    val glenum = GL_VERTEX_SHADER
}

case class FragmentShader() extends ShaderType {
  val glenum = GL_FRAGMENT_SHADER
}

case class Shader[ST <: ShaderType](src: String)(implicit st: ShaderType) {

  public val shaderID: Int = glCreateShader(st.glenum)
  glCompileShader(shaderID)

}

case class ShaderProgram(shaders: List[Shader[ShaderType]]) {
   val programID: Int = glCreateProgram()
   shaders.map(s => glAttachShader(programID, s.id))

   glLinkProgram(programID)

   def bind(): Unit = glUseProgram(programID)
   def unbind(): Unit = glUseProgram(0)

}

We could add a release method to ShaderProgram, for example:

def release(): Unit = {
  unbind()

  // Detach the shaders
  shaders.map(s => glDetachShader(programID, s.id))

  // Delete the program
  glDeleteProgram(programID);
}

We could, of course, also delete the shader objects but this assumes they are not being used in other shader programs. However, the problem I have with this approach is that it replies on the library user "remembering" to call release either at the right time, to avoid leaks, or at all! In a language like C++, using std::shared_ptr combined with destructors, for example, I would be able to automatically manage the GL resources, but it is not clear to me how to do something similar using Scala.

pasternak
  • 103
  • 4

2 Answers2

1

The resources in JVM are automatically released by GC, but it's not recommended to use GC handler as the time of calling GC is not predictable + related handlers may not be called in appropriate order (why). Traditional way to handle such things in Java is:

val resource = getResource()
try { 
  resource.doSomething 
} finally {
  resource.close()
}

In Java7 there is also try with resources construction. There is no analog in scala but traditional scala way is to define DSL:

object managed {
  def apply[T, Q](c: AutoCloseable)(f: (T) => Q): Q = {
    try {
      f(c)
    } finally {
      c.close()
    }
  }
}

Usage:

managed(getResource()){ resource =>
  resource.doSomething()
}

Here is also monadic solution (using external library). Such DSL-like constructions guarantees that resource will be automatically released before going outside of resource argument's scope.

Community
  • 1
  • 1
dk14
  • 22,206
  • 4
  • 51
  • 88
  • 2
    What you are referring to is known as the loan pattern: https://stackoverflow.com/questions/20762240/loan-pattern-in-scala – Justin Pihony Mar 24 '15 at 15:13
  • I don't see why you'd use a structural type when `AutoCloseable` suffices. –  Mar 24 '15 at 16:22
0

If you want a library that can help you with this, I found Scala ARM to be helpful.

Ajay Padala
  • 2,371
  • 16
  • 13