Since the underlying issues with the Python bindings are now fixed,
in most cases we can safely default to allowing an algorithm to
run in a background thread!!
So now we make this the default, and require individual algorithms
which are NOT thread safe to declare this. This includes algorithms
which directly manipulate the current project or layers (such as
setting layer styles), alter the selections in layers, or which
rely on 3rd party libraries (for now, SAGA and GRASS algorithms
are marked as not thread safe... TODO - someone more familiar with
these libraries can investigate and remove the flag if appropriate).
Also models are marked as non-thread safe. TODO: only flag an
individual model as thread-unsafe if any of its child algorithms
report this flag.
And make this support opt-out, since the vast majority of providers
are based on QGIS API and don't have external dependencies which would
restrict use of memory layers/etc.
Plus, I'd rather see non-compliant providers expose this support when
they can't use non-file-based-outputs (and make this the bug which
needs fixing) then have to rely on plugin providers to discover and
explicitly expose this support.
Switches on the sip "-g" switch, which forces sip to release the
Python Global Interpreter Lock before calling a qgis c++ method,
and reacquire it after.
While this flag is not a default sip flag, it is used when building
the PyQt API, so can't forsee any issues from enabling it.
The benefit however is extreme for PyQGIS based scripts which
rely on threads, potentially resulting in massive performance
boosts.
Without this switch, calling an expensive c++ method (say,
building a QgsSpatialIndex using a QgsFeatureIterator) would lock
the Python GIL for the duration of the c++ call... which could
potentially take minutes or more. With the switch, the lock
is released before all calls, so other Python threads are free
to merrily grab the lock and do other processing while the
original thread chugs away in c++ land.
Benchtests of worst-case scenarios (single thread calling
thousands of very inexpensive PyQGIS methods (simple getters))
regressed from mean of 154 seconds to 158 with this flag. But
that's worst case (and as Intel have recently demonstrated...
we can't take yesterday's computing speed as the benchmark
for todays ;). Given that best case scenarious (multi-threaded
operations calling slow c++ methods) will benefit so greatly
from this change, I think it's an acceptable trade off.
*This is a step toward potentially re-enabling background
execution of python based Processing algorithms, and also
should greatly improve QGIS responsiveness when using
python based renderers/symbols.
I wanted to add the test for gpkg subsetstring even if
it was not bugged, while testing that, I hit an assert
in Qt core that pointed me to double unlocked locks.