Source-Python-Dev-Team / Source.Python

This plugin aims to use boost::python and create an easily accessible wrapper around the Source Engine API for scripter use.
http://forums.sourcepython.com
GNU General Public License v3.0
164 stars 32 forks source link

Threads updates. #491

Open jordanbriere opened 1 year ago

jordanbriere commented 1 year ago

This branch introduces the following changes:

Test builds (CS:S/CS:GO/Windows/Linux): 1wAeyyUgdGSAENV80BeWSIN0Sy3w4W5Jb

CookStar commented 1 year ago

Is the issue #2787 caused by hibernation or is it a fundamental problem caused by the game?

jordanbriere commented 1 year ago

The long story short is that, the interpreter does not own the process. Therefore, it won't attempt switches unless it is either invoked, explicitly allowed to do so, or catches an interrupt signal coming from the main thread.

In fact, if that was not for delays listening to frames at all time, no progress would be done on threads while the interpreter is in its relaxed state until something is actually interpreted (e.g. commands, events, hooks, etc.). But even then, it's really just relinquishing the remainder of its time slice due to GIL restrictions (except maybe for non-locking I/O stuff, Python threads are not truly parallel and rather fall under concurrency when it involves the CPU) meaning that not much is achieved on a frame-to-frame basis.

To address this, ThreadYielder waits for the main thread to sleep each frame and explicitly allows Python threads to run during that time while making sure to first yield to higher priority tasks so that eventual jobs that may be pending in the engine's pools get a chance to resume and progress beforehand.

It's probably not the most elegant approach, but I believe its the less intrusive and safest one when everything is taken into consideration (timing precision differences/granularity mismatches between OS, inconsistencies between engines where some round up their remaining intervals while others floor them down, without mentioning asynchronous frames/networking tasks that are not equally prioritized on all games, etc).

As for the hibernation issues that affect some games, it's caused by them purposely not running frames at all while waiting for socket updates. We could theoretically run our own frames virtually, but that would be redundant in my opinion.