Any difference between main thread and other threads? Any difference between main thread and other threads? multithreading multithreading

Any difference between main thread and other threads?


The question refers to an old GLFW API and FAQ, please see the updated GLFW FAQ, and GLFW thread safety documentation.

Some constraints remain, and many GLFW calls must be made from the main thread. The difference between the main thread and other threads depends on platform specific behaviour for window creation, events etc which GLFW handles. For more detail please see this post on the official GLFW forum.

Once an OpenGL window has been created, the context can be made current on another thread and OpenGL calls can be made from that thread.


The statement

"Is … thread safe? No. However, neither is OpenGL."

is wrong. OpenGL is of course thread safe.

Here's the deal: For each thread either one or no OpenGL context can be bound to a drawable (made current). OpenGL calls operate on the context that is active in the thread the calls are made from. It is perfectly possible to transfer a OpenGL context between threads. For this the context to be transfered first must be unbound, then it can be rebound in another thread.

Each OpenGL context manages its own set of state variable and objects (textures, buffers). However context can be "entangled", i.e. share their object space. State is still individual though.

A single drawable (window, PBuffer) can have multiple contexts from different threads being bound to. If contexts from different threads draw to the same drawable a race condition occours and the results are undefined. However in the case of depth tested drawing the outcome should be reasonable. However simultanous drawing to a single drawable will strongly impair performance, so it better is avoided.

The main use for multiple OpenGL contexts in multiple threads is to share their objects so that one thread can load and update data for the other context. It makes sense to bind the helper contexts to off-screen or hidden drawables to prevent race conditions to happen.

There's no technical difference between the threads. From a programming point of view each thread will have a slightly different semantic, which is imposed by the programm running, not by the system architecture. In the case of most OpenGL applications the conventional semantics are, that the main thread will create the window, draw all elements visible to the user (including OpenGL operations) and collect user input. The threads launched from the main thread are worker threads without direct user interaction. However this task distribution is purely by choice and because it turned out to work well. But it's perfectly possible, and sometimes advisable, to use a different scheme. And like already said, there is no technical difference about the threads within a program. All threads are equal rights citizens within a process.


The documentation is maybe worded in a slightly misleading way. A better wording would be:

It is strongly recommended that all OpenGL and GLFW calls (except for thread management and synchronization calls) are made from a single thread, preferrably the same one that called glfwInit and glfwOpenWindow, which should not be a big problem since only a single window is supported. This method is also compatible with the future direction of GLFW.

The reason for that is that OpenGL has the concept of a "current thread" for its contexts, which is the one thread that may legitimate modify or use that context at a given time. A context initially belongs to the thread that created it. You can make it "current" in some other thread by calling wglMakeCurrent or glxMakeCurrent, which unlike GLFW is not portable (but GLFW might have a wrapper for that, I'm not sure).

It is of course very well possible to have several independent contexts, and it is possible to access the same context from several threads by making the same context current in each thread prior to using it. And lastly, it is possible to have several contexts in several threads that share state.
However, none of these options is the regular case, as it either involves non-neglegible synchronization overhead or is not suitable for the common usage of OpenGL. Any other thing than "one thread, one context" usually, with very few exceptions, doesn't offer any advantage, but comes with needless complexity.

The regular case is therefore to have exactly one context that is used by exactly one thread, and optionally some worker threeads that help with shuffling data into mapped buffers.

As for "main thread" versus "any thread", there is no difference. The main thread is just incidentially the one that initializes GLFW (and thus OpenGL), most of the time.