Skip to content

Commit 04a8f9d

Browse files
committed
getters and setters using atomics
1 parent fb6212a commit 04a8f9d

File tree

2 files changed

+184
-119
lines changed

2 files changed

+184
-119
lines changed

Lib/test/test_array.py

Lines changed: 96 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,7 @@ def test_empty(self):
105105
class ArrayReconstructorTest(unittest.TestCase):
106106

107107
def setUp(self):
108-
if (not support.Py_GIL_DISABLED or
109-
any('"parallel_threads": null' in a for a in sys.argv) or
110-
all('parallel_threads' not in a for a in sys.argv)):
111-
self.enterContext(warnings.catch_warnings())
108+
self.enterContext(warnings.catch_warnings())
112109
warnings.filterwarnings(
113110
"ignore",
114111
message="The 'u' type code is deprecated and "
@@ -224,10 +221,7 @@ class BaseTest:
224221
# minitemsize: the minimum guaranteed itemsize
225222

226223
def setUp(self):
227-
if (not support.Py_GIL_DISABLED or
228-
any('"parallel_threads": null' in a for a in sys.argv) or
229-
all('parallel_threads' not in a for a in sys.argv)):
230-
self.enterContext(warnings.catch_warnings())
224+
self.enterContext(warnings.catch_warnings())
231225
warnings.filterwarnings(
232226
"ignore",
233227
message="The 'u' type code is deprecated and "
@@ -1696,6 +1690,29 @@ class FreeThreadingTest(unittest.TestCase):
16961690
# Non-deterministic, but at least one of these things will fail if
16971691
# array module is not free-thread safe.
16981692

1693+
def setUp(self):
1694+
self.enterContext(warnings.catch_warnings())
1695+
warnings.filterwarnings(
1696+
"ignore",
1697+
message="The 'u' type code is deprecated and "
1698+
"will be removed in Python 3.16",
1699+
category=DeprecationWarning)
1700+
1701+
def check(self, funcs, a=None, *args):
1702+
if a is None:
1703+
a = array.array('i', [1])
1704+
1705+
barrier = threading.Barrier(len(funcs))
1706+
threads = []
1707+
1708+
for func in funcs:
1709+
thread = threading.Thread(target=func, args=(barrier, a, *args))
1710+
1711+
threads.append(thread)
1712+
1713+
with threading_helper.start_threads(threads):
1714+
pass
1715+
16991716
@unittest.skipUnless(support.Py_GIL_DISABLED, 'this test can only possibly fail with GIL disabled')
17001717
@threading_helper.reap_threads
17011718
@threading_helper.requires_working_threading()
@@ -1889,67 +1906,81 @@ def iter_reduce(b, a, it):
18891906
c = it.__reduce__()
18901907
assert not c[1] or 0xdd not in c[1][0]
18911908

1892-
def check(funcs, a=None, *args):
1893-
if a is None:
1894-
a = array.array('i', [1])
1895-
1896-
barrier = threading.Barrier(len(funcs))
1897-
threads = []
1898-
1899-
for func in funcs:
1900-
thread = threading.Thread(target=func, args=(barrier, a, *args))
1901-
1902-
threads.append(thread)
1903-
1904-
with threading_helper.start_threads(threads):
1905-
pass
1906-
1907-
check([pop1] * 10)
1908-
check([pop1] + [subscr0] * 10)
1909-
check([append1] * 10)
1910-
check([insert1] * 10)
1911-
check([pop1] + [index1] * 10)
1912-
check([pop1] + [contains1] * 10)
1913-
check([insert1] + [repeat2] * 10)
1914-
check([pop1] + [repr1] * 10)
1915-
check([inplace_repeat2] * 10)
1916-
check([byteswap] * 10)
1917-
check([insert1] + [clear] * 10)
1918-
check([pop1] + [count1] * 10)
1919-
check([remove1] * 10)
1920-
check([clear] + [copy] * 10, array.array('B', b'0' * 0x400000))
1921-
check([pop1] + [reduce_ex2] * 10)
1922-
check([clear] + [reduce_ex3] * 10, array.array('B', b'0' * 0x400000))
1923-
check([pop1] + [tobytes] * 10)
1924-
check([pop1] + [tolist] * 10)
1925-
check([clear, tounicode] * 10, array.array('w', 'a'*10000))
1926-
check([clear, tofile] * 10, array.array('w', 'a'*10000))
1927-
check([clear] + [extend] * 10)
1928-
check([clear] + [inplace_concat] * 10)
1929-
check([clear] + [concat] * 10, array.array('w', 'a'*10000))
1930-
check([fromunicode] * 10, array.array('w', 'a'))
1931-
check([frombytes] * 10)
1932-
check([fromlist] * 10)
1933-
check([clear] + [richcmplhs] * 10, array.array('i', [1]*10000))
1934-
check([clear] + [richcmprhs] * 10, array.array('i', [1]*10000))
1935-
check([clear, ass0] * 10, array.array('i', [1]*10000)) # to test array_ass_item must disable Py_mp_ass_subscript
1936-
check([clear] + [new] * 10, array.array('w', 'a'*10000))
1937-
check([clear] + [repr_] * 10, array.array('B', b'0' * 0x40000))
1938-
check([clear] + [repr_] * 10, array.array('B', b'0' * 0x40000))
1939-
check([clear] + [irepeat] * 10, array.array('B', b'0' * 0x40000))
1940-
check([clear] + [iter_reduce] * 10, a := array.array('B', b'0' * 0x400), iter(a))
1909+
self.check([pop1] * 10)
1910+
self.check([pop1] + [subscr0] * 10)
1911+
self.check([append1] * 10)
1912+
self.check([insert1] * 10)
1913+
self.check([pop1] + [index1] * 10)
1914+
self.check([pop1] + [contains1] * 10)
1915+
self.check([insert1] + [repeat2] * 10)
1916+
self.check([pop1] + [repr1] * 10)
1917+
self.check([inplace_repeat2] * 10)
1918+
self.check([byteswap] * 10)
1919+
self.check([insert1] + [clear] * 10)
1920+
self.check([pop1] + [count1] * 10)
1921+
self.check([remove1] * 10)
1922+
self.check([clear] + [copy] * 10, array.array('B', b'0' * 0x400000))
1923+
self.check([pop1] + [reduce_ex2] * 10)
1924+
self.check([clear] + [reduce_ex3] * 10, array.array('B', b'0' * 0x400000))
1925+
self.check([pop1] + [tobytes] * 10)
1926+
self.check([pop1] + [tolist] * 10)
1927+
self.check([clear, tounicode] * 10, array.array('w', 'a'*10000))
1928+
self.check([clear, tofile] * 10, array.array('w', 'a'*10000))
1929+
self.check([clear] + [extend] * 10)
1930+
self.check([clear] + [inplace_concat] * 10)
1931+
self.check([clear] + [concat] * 10, array.array('w', 'a'*10000))
1932+
self.check([fromunicode] * 10, array.array('w', 'a'))
1933+
self.check([frombytes] * 10)
1934+
self.check([fromlist] * 10)
1935+
self.check([clear] + [richcmplhs] * 10, array.array('i', [1]*10000))
1936+
self.check([clear] + [richcmprhs] * 10, array.array('i', [1]*10000))
1937+
self.check([clear, ass0] * 10, array.array('i', [1]*10000)) # to test array_ass_item must disable Py_mp_ass_subscript
1938+
self.check([clear] + [new] * 10, array.array('w', 'a'*10000))
1939+
self.check([clear] + [repr_] * 10, array.array('B', b'0' * 0x40000))
1940+
self.check([clear] + [repr_] * 10, array.array('B', b'0' * 0x40000))
1941+
self.check([clear] + [irepeat] * 10, array.array('B', b'0' * 0x40000))
1942+
self.check([clear] + [iter_reduce] * 10, a := array.array('B', b'0' * 0x400), iter(a))
19411943

19421944
# make sure we handle non-self objects correctly
1943-
check([clear] + [newi] * 10, [2] * random.randint(0, 100))
1944-
check([fromlistlclear] + [fromlistl] * 10, array.array('i', [1]), [2] * random.randint(0, 100))
1945-
check([clear2] + [concat2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1946-
check([clear2] + [inplace_concat2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1947-
check([clear2] + [extend2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1948-
check([clear2] + [ass_subscr2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1949-
check([clear2] + [frombytes2] * 10, array.array('w', 'a'*10000), array.array('B', b'a'*10000))
1945+
self.check([clear] + [newi] * 10, [2] * random.randint(0, 100))
1946+
self.check([fromlistlclear] + [fromlistl] * 10, array.array('i', [1]), [2] * random.randint(0, 100))
1947+
self.check([clear2] + [concat2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1948+
self.check([clear2] + [inplace_concat2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1949+
self.check([clear2] + [extend2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1950+
self.check([clear2] + [ass_subscr2] * 10, array.array('w', 'a'*10000), array.array('w', 'a'*10000))
1951+
self.check([clear2] + [frombytes2] * 10, array.array('w', 'a'*10000), array.array('B', b'a'*10000))
19501952

19511953
# iterator stuff
1952-
check([clear] + [iter_next] * 10, a := array.array('i', [1] * 10), iter(a))
1954+
self.check([clear] + [iter_next] * 10, a := array.array('i', [1] * 10), iter(a))
1955+
1956+
@unittest.skipUnless(support.check_sanitizer(thread=True), 'meant for tsan')
1957+
def test_free_threading_tsan(self):
1958+
def copy_back_and_forth(b, a, count):
1959+
b.wait()
1960+
for _ in range(count):
1961+
a[0] = a[1]
1962+
a[1] = a[0]
1963+
1964+
def extend_range(b, a, count):
1965+
b.wait()
1966+
for _ in range(count):
1967+
a.extend(range(10))
1968+
1969+
def append_and_pop(b, a, count):
1970+
b.wait()
1971+
for _ in range(count):
1972+
a.append(1)
1973+
a.pop()
1974+
1975+
for tc in typecodes:
1976+
if tc in 'uw':
1977+
a = array.array(tc, 'ab')
1978+
else:
1979+
a = array.array(tc, [0, 1])
1980+
1981+
self.check([copy_back_and_forth] * 10, a, 100)
1982+
self.check([append_and_pop] * 10, a, 100)
1983+
self.check([copy_back_and_forth] * 10 + [extend_range], a, 10)
19531984

19541985

19551986
if __name__ == "__main__":

0 commit comments

Comments
 (0)