GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-124397: Add threading.iter_locked by eendebakpt · Pull Request #133908 · python/cpython Conversation
|
|
@serhiy-storchaka, what was the rationale behind putting this in the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| The ``iter_locked`` makes non-atomic iterators atomic:: | ||
|
|
||
| class non_atomic_iterator: |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure non_atomic_iterator is a good example of something that exists in the wild, because it's not thread-safe on GIL-ful builds either. The thread can arbitrarily switch during execution of Python code, so this would need a lock anyway if concurrent iteration were a use case. For free-threading, __next__ itself should have its own locking to prevent races. How was this design reached?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The iter_locked allows the non_atomic_iterator to be used in a threaded-setting, whether in the normal or FT build. Do you have suggestions for other tests?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| def __next__(self): | ||
| a = next(self.it) | ||
| b = next(self.it) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Add time.sleep(0) (or with small non-zero argument) or Event.wait() with a timeout to force or significantly increase the chance of concurrent access.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| iter_locked_object *lz = iter_locked_object_CAST(op); | ||
| PyObject *result = NULL; | ||
|
|
||
| Py_BEGIN_CRITICAL_SECTION(op); // lock on op or lz->it? |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Isn't it a no-op in the GIL build?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Good catch, it is indeed a no-op. The Py_BEGIN_CRITICAL_SECTION is defined using _PyCriticalSection_BeginMutex, but that is not available in the normal build. So we should either add it to the normal build, or use another lock implementation.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| Py_BEGIN_CRITICAL_SECTION(op); // lock on op or lz->it? | ||
| PyObject *it = lz->it; | ||
| result = PyIter_Next(it); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Let's use PyIter_NextItem, PyIter_Next has a weird return value.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Why a simple Python implementation is not good enough?
What will happen if self-lock an iterator? Is there a way to forcefully unlock it ot prevent self-locking by raising an exception?
def g(): yield next(it) it = iter_locked(g()) next(it)
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Originally I wrote the
There was a deadlock, with no way to get out. I changed to a recursive lock and added 2 tests. The behaviour is now similar to the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This PR is stale because it has been open for 30 days with no activity. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Has been superseded |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.