Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
View this page
Toggle table of contents sidebar

# The Lifecycle of a ModernGL Object

From moderngl 5.7 we support three different garbage collection modes. This should be configured using the `Context.gc_mode` attribute preferably right after the context is created.

The current supported modes are:

- `None`: (default) No garbage collection is performed. Objects needs to to be manually released like in previous versions of moderngl.

- `"context_gc"`: Dead objects are collected in `Context.objects`. These can periodically be released using `Context.gc()`.

- `"auto"`: Dead objects are destroyed automatically like we would expect in python.

It’s important to realize here that garbage collection is not about the python objects itself, but the underlying OpenGL objects. ModernGL operates in many different environments were garbage collection can be a challenge. This depends on factors like who is controlling the existence of the OpenGL context and challenges around threading in python.

## Standalone / Headless Context

In this instance we control when the context is created and destroyed. Using `"auto"` garbage collection is perfectly reasonable in this situation.

## Context Detection

When detecting an existing context from some window library we have no direct control over the existence of the context. Using `"auto"` mode is dangerous can can cause crashes especially on application exit. The window and context is destroyed and closed, then moderngl will try to destroy resources in a context that no longer exists. Use `"context_gc"` mode to avoid this.

It can be possible to switch the `gc_mode` to `None` when the window is closed. This can still be a problem if you have race conditions due to resources being created in the render loop.

## The Threading Issue

When using threads in python the garbage collector can run in any thread. This is a problem for OpenGL because only the main thread is allowed to interact with the context. When using threads in your application you should be using `"context_gc"` mode and periodically call `Context.gc` for example during every frame swap.

## Manually Releasing Objects

Objects in moderngl don’t automatically release the OpenGL resources when `gc_mode=None` is used. Each type has a `release()` method that needs to be called to properly clean up everything:

    # Create a texture
    texture = ctx.texture((10, 10), 4)

    # Properly release the opengl resources
    texture.release()

## Detecting Released Objects

If you for some reason need to detect if a resource was released it can be done by checking the type of the internal moderngl object (`.mglo` property):

    >> import moderngl
    >> ctx = moderngl.create_standalone_context()
    >> buffer = ctx.buffer(reserve=1024)
    >> type(buffer.mglo)
    <class 'mgl.Buffer'>
    >> buffer.release()
    >> type(buffer.mglo)
    <class '_moderngl.InvalidObject'>
    >> type(buffer.mglo) == moderngl.mgl.InvalidObject
    True