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.