我正在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做类似的事情。
答案 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会对您有所帮助。