释放非托管资源

时间:2015-03-24 13:52:46

标签: scala

我正在Java库LWJGL之上开发一个Scala库,我想知道处理"删除"的最佳方法是什么?非托管资源。例如,考虑一个(简化的)界面来管理着色器对象:

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)

}

我们可以向ShaderProgram添加一个释放方法,例如:

def release(): Unit = {
  unbind()

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

  // Delete the program
  glDeleteProgram(programID);
}

当然,我们也可以删除着色器对象,但这假设它们没有在其他着色器程序中使用。但是,我对这种方法的问题是它回复了库用户&#34;记住&#34;在正确的时间呼叫释放,以避免泄漏,或者根本没有!例如,在像C ++这样的语言中,使用std :: shared_ptr与析构函数相结合,我将能够自动管理GL资源,但我不清楚如何使用Scala做类似的事情。

2 个答案:

答案 0 :(得分:1)

JVM中的资源由GC自动释放,但是not recommended使用GC处理程序,因为调用GC的时间不可预测+可能无法以适当的顺序调用相关的处理程序(why) 。在Java中处理此类事物的传统方法是:

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

在Java7中,还有try with resources构造。 scala中没有模拟,但传统的scala方式是定义DSL:

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

用法:

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

Here也是monadic解决方案(使用外部库)。这种类似DSL的结构保证资源在超出resource参数范围之前自动释放。

答案 1 :(得分:0)

如果您想要一个可以帮助您解决此问题的图书馆,我发现Scala ARM会对您有所帮助。