Having input detection in a separate thread, and is reading variables thread safe?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By psear

A bit of a compound question:

  1. Can I move _unhandled_input() to its own thread, and if so, how?
  2. If I have a variable that may be modified at any time by thread A, is it thread-safe to read it at any time from thread B?

The objective is to have an input handling system where I am experimenting with gestures, where there is a singleton which handles touch, and has a variable of various states (e.g pressed, dragging left, dragging right etc.) which can be read at any time by any thread.

Say I call my singleton TouchGesture, so some other part of my game could be

if TouchGesture.state == TouchGesture.states.SWIPE_LEFT:
    move_player_left()

TouchGesture.states may be read at any time by any thread, but will only be written to by either the main thread, or whatever thread is handling unhandled input (question 1).

:bust_in_silhouette: Reply From: Lopy

_unhandled_input(event) is a Node function. As Thread are not nodes, it would not be called automatically inside your Thread. However, you could start a function inside a Thread yourself whenever you recieve an event from one of your Nodes.

Reading a variable is generally safe, as long as it doesn’t matter if it is up to date, it never goes through an invalid State while being updated, and reading it is pure (no side effects). To test thread safety, you can try making a few hundred simultaneous Threads, with a start synced with a Semaphore, all doing your operation a thousand time and asserting that it works well.

However, you seem to want to put Thread in places where they are not really needed and may even detract from you performances. Threads allow you to run very slow functions in parallel, to leverage more cores of your processor. However, launching a Thread itself is not instantaneous, and if you use them for short _unhandled_input(), it may add time instead of removing it.

To see which functions take the most time, Godot has a builtin profiler (Debugger third tab). Also, to see if it is usefull to shave time, you can setup a few Label displaying your favorite Performance.get_monitor() at all time. For more perfomance tips, see the optimisation section of the documentation