[3.13] gh-119247: Add macros to use PySequence_Fast safely in free-threaded build (GH-119315) by miss-islington · Pull Request #119419 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Include/internal/pycore_critical_section.h
75 changes: 75 additions & 0 deletions Lib/test/test_free_threading/test_str.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import sys
import unittest

from itertools import cycle
from threading import Event, Thread
from unittest import TestCase

from test.support import threading_helper

@threading_helper.requires_working_threading()
class TestStr(TestCase):
def test_racing_join_extend(self):
'''Test joining a string being extended by another thread'''
l = []
ITERS = 100
READERS = 10
done_event = Event()
def writer_func():
for i in range(ITERS):
l.extend(map(str, range(i)))
l.clear()
done_event.set()
def reader_func():
while not done_event.is_set():
''.join(l)
writer = Thread(target=writer_func)
readers = []
for x in range(READERS):
reader = Thread(target=reader_func)
readers.append(reader)
reader.start()

writer.start()
writer.join()
for reader in readers:
reader.join()

def test_racing_join_replace(self):
'''
Test joining a string of characters being replaced with ephemeral
strings by another thread.
'''
l = [*'abcdefg']
MAX_ORDINAL = 1_000
READERS = 10
done_event = Event()

def writer_func():
for i, c in zip(cycle(range(len(l))),
map(chr, range(128, MAX_ORDINAL))):
l[i] = c
done_event.set()

def reader_func():
while not done_event.is_set():
''.join(l)
''.join(l)
''.join(l)
''.join(l)

writer = Thread(target=writer_func)
readers = []
for x in range(READERS):
reader = Thread(target=reader_func)
readers.append(reader)
reader.start()

writer.start()
writer.join()
for reader in readers:
reader.join()


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Added ``Py_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST`` and
``Py_END_CRITICAL_SECTION_SEQUENCE_FAST`` macros to make it possible to use
PySequence_Fast APIs safely when free-threaded, and update str.join to work
without the GIL using them.
8 changes: 5 additions & 3 deletions Objects/unicodeobject.c