This vector implementation does is optimized for the case of having only a small number of elements, which are stored directly on the vector object rather than being allocated from the heap. If the capacity exceeds this small number, then a heap allocation is done.
This should improve performance in a couple of cases where vectors typically store 1 element and rarely more than that.
When copying a dirty cycler, don't use two separate lock-grabbing calls to add to the clean set, then remove from clean set and move to dirty set
Short-cut the cdata copy loop for the common case of only 1 stage
init_memory_hook() is no longer required, eliminating static initialization order issues
This required moving the DeletedBufferChain map elsewhere, which now also has a const-initialized array for relatively small allocations.
Also, deletedChain.T has been renamed to deletedChain.I
Fixes#539
Use Sleep(0) instead. Sleep(0) is not guaranteed to yield, which is a problem, but Sleep(1) can easily take up to 16 ms, which is really unacceptable except in very low-priority thread. But really, you shouldn't be relying on force_yield() for anything except with the SIMPLE_THREADS model.
There is also SwitchToThread(), but in fact it is even weaker than Sleep(0).
Speedup is realised by using thread-local variables. Note that on Windows we can't inline get_current_thread, but it's still faster this way than calling TlsGetValue.
In theory the cache line alignment should help avoid false sharing but I have not profiled that extensively.
In particular, these optimize the traversal of nodes that are not in view, which are discarded more efficiently.
This change affects both the cull and collision traversers.
We can't call PyErr_Restore() without a valid thread state, which won't exist in a custom thread if we just called PyGILState_Release(). Not sure how this has ever worked.
This allows using mutices in with-blocks and wraps up the functionality of acquire() and try_acquire() into a single acquire(blocking=True).
Furthermore, the GIL is no longer released in cases of no contention.
The symbols moved aren't used in any headers, so they don't
have to be in the installed dtool_config.h. Removing them
keeps the recompiling to a minimum when an optional feature
is toggled.