internal/atlas: refactoring

This commit is contained in:
Hajime Hoshi 2023-11-03 14:52:19 +09:00
parent 258f0fd941
commit 97d1e073e2

View File

@ -542,17 +542,13 @@ func (i *Image) readPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte
return i.backend.restorable.ReadPixels(graphicsDriver, pixels, region.Add(r.Min)) return i.backend.restorable.ReadPixels(graphicsDriver, pixels, region.Add(r.Min))
} }
// MarkDisposed marks the image as disposed. The actual operation is deferred. // MarkDisposed marks the image as disposed.
// MarkDisposed can be called from finalizers.
//
// A function from finalizer must not be blocked, but disposing operation can be blocked.
// Defer this operation until it becomes safe. (#913)
func (i *Image) MarkDisposed() { func (i *Image) MarkDisposed() {
// As MarkDisposed can be invoked from finalizers, backendsM should not be used. backendsM.Lock()
appendDeferred(func() { defer backendsM.Unlock()
i.deallocate()
runtime.SetFinalizer(i, nil) i.deallocate()
}) runtime.SetFinalizer(i, nil)
} }
func (i *Image) deallocate() { func (i *Image) deallocate() {
@ -619,7 +615,14 @@ func (i *Image) allocate(forbiddenBackends []*backend, asSource bool) {
panic("atlas: the image is already allocated") panic("atlas: the image is already allocated")
} }
runtime.SetFinalizer(i, (*Image).MarkDisposed) runtime.SetFinalizer(i, func(img *Image) {
// A function from finalizer must not be blocked, but disposing operation can be blocked.
// Defer this operation until it becomes safe. (#913)
appendDeferred(func() {
i.deallocate()
runtime.SetFinalizer(i, nil)
})
})
if i.imageType == ImageTypeScreen { if i.imageType == ImageTypeScreen {
if asSource { if asSource {