Godot-proposals: Rename Threads class to Forks

Created on 29 Jun 2020  路  7Comments  路  Source: godotengine/godot-proposals

Describe the project you are working on:
Irrelevant to the proposed change.

Describe the problem or limitation you are having in your project:
Misrepresentation of Godot Threads causes untold frustration about understanding the inner workings of a program.
In Godot under the hood, Threads class is not instantiating another thread, it is forking the main process and creating
a subprocess. It is important to use correct words when describing classes, because the use of incorrect names causes confusion when working with external components written in another programming languages (python).
In python (and other languages), "threading" means switching execution threads in the same process, while forking means creating another process with its own thread pool. There are even separate modules in python: multiprocessing and multithreading.
In Godot, "multithreading" is already automatically realized through Nodes, as each script attached to a node has it's own thread, while "multiprocessing" is realized through the Threads class, which is just stupid and confusing.
When you try to run OS.execute(java --classpath myclass.jar) in a Godot "thread", it even throws ""ERR_CANT_FORK" error!
For what reason is the forking of the main process to a subprocess misrepresented in Godot as Threads?

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
Representing Godot threads with the correct name helps to properly understand the program internals and
create efficient workflows with external components written in other languages, which use the correct terms.
If one wishes to write efficient code (needs to access tensorflow for example), one needs to understand WTF is
going on with threads and cores to maximise the use of system resources.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
Rename Threads class to Forks

If this enhancement will not be used often, can it be worked around with a few lines of script?:
Technically, I could write a wrapper for Threads to use the word Fork, but that's just bad practice.

Is there a reason why this should be core and not an add-on in the asset library?:
Because this is about renaming a core class.

archived core

Most helpful comment

ERR_CANT_FORK

Wrong, Godot has permissive license! 馃槤

All 7 comments

Misrepresentation of Godot Threads causes untold frustration about understanding the inner workings of a program.
In Godot under the hood, Threads class is not instantiating another thread, it is forking the main process and creating
a subprocess.

What makes you believe that ? I had a look to the code, and creating a thread is done by calling those functions for those platform:

Unix:

Thread *ThreadPosix::create_func_posix(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
    ThreadPosix *tr = memnew(ThreadPosix);
    tr->callback = p_callback;
    tr->user = p_user;
    pthread_attr_init(&tr->pthread_attr);
    pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
    pthread_attr_setstacksize(&tr->pthread_attr, 256 * 1024);

    pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);

    return tr;
}

Windows:

Thread *ThreadWindows::create_func_windows(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
    ThreadWindows *tr = memnew(ThreadWindows);
    tr->callback = p_callback;
    tr->user = p_user;
    tr->handle = CreateEvent(nullptr, TRUE, FALSE, nullptr);

    QueueUserWorkItem(thread_callback, tr, WT_EXECUTELONGFUNCTION); //Note: this is the method for windows ThreadPool in System.Threading 

    return tr;
}

Android:

Thread *ThreadAndroid::create_func_jandroid(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
    ThreadAndroid *tr = memnew(ThreadAndroid);
    tr->callback = p_callback;
    tr->user = p_user;
    pthread_attr_init(&tr->pthread_attr);
    pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);

    pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);

    return tr;
}

All of those use the respective standard OS way to a create a thread, not a fork.

@groud If what you say is true, then how come Godot Documentation on threads talks about "Threads are used to balance processing power across CPUs and cores." Are you telling me, that threads are being automatically distributed among the available cores by the OS? I have understood that threads are executed on a single core and processes are distributed among the cores, where a process executes all its threads on that core its running on. Am I then mistaken, or is it the documentation?
This confusion about how Godot uses multithreading and multiprocessing should just not exist. How am I supposed to guarantee the most efficient use of my system resources, if the documentation and implementation are contradictory to one another?

Or did I get the "ERR_CANT_FORK" error because of executing "OS.execute(java --classpath myclass.jar)", regardless of threading?
So Godot threads is multithreading, but OS.execute is multiprocessing (in python terms)?

Are you telling me, that threads are being automatically distributed among the available cores by the OS?

Yes exactly, that's the definition of a thread. Threads can run concurrently, each of them on a different core if needed.
It's also the case for processes, but unlike threads, processes do not share the same memory space. Processes are separated in significantly stricter way than threads (which does make sense, as you don't want a process to interfere with another).

You took the example of python, but python is an unusual case. It does provide threads, but each threads needs access to a single object called the Global Interpreter Lock (GIL) to run the code. So basically, you cannot have two threads running at once, so threading is pretty inefficient there.

Or did I get the "ERR_CANT_FORK" error because of executing "OS.execute(java --classpath myclass.jar)", regardless of threading?
So Godot threads is multithreading, but OS.execute is multiprocessing (in python terms)?

Yes, the error come exclusively from executing "OS.execute(java --classpath myclass.jar)", regardless of threading. OS.execute ask the OS to spawn a subprocess. Internally, this is made by forking (creating a copy in memory) of the calling program. This is how things work with most OS. So, yes, this function creates another process.

Just have a look to linux's system() function reference, which is used to execute a subprocess: https://linux.die.net/man/3/system

You can read : "The value returned is -1 on error (e.g., fork(2) failed), and the return status of the command otherwise."

@groud Thank you Gilles for providing the perfect explanation. I understand completely.
Your explanation should be put into the Godot official documentation, as it would improve
the explanation about Godot threads and interworking with python components astronomically.

ERR_CANT_FORK

Wrong, Godot has permissive license! 馃槤

Just to clarify c++ uses os threads, which at least on major operating systems are just subprocesses ("fork" is the common terminology in posix systems). These os threads, like any other process, is multiplexed across all cpu cores by the cpu scheduler.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rainlizard picture rainlizard  路  3Comments

regakakobigman picture regakakobigman  路  3Comments

WilliamTambellini picture WilliamTambellini  路  3Comments

lupoDharkael picture lupoDharkael  路  3Comments

PLyczkowski picture PLyczkowski  路  3Comments