diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index a8419b9..66051f9 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -19,7 +19,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Build wheels - uses: pypa/cibuildwheel@v2.21.3 + uses: pypa/cibuildwheel@v2.23.3 env: CIBW_SOME_OPTION: value with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b73968c..dab68d1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -24,7 +24,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python_version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python_version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.13t"] exclude: # The 3.9/3.10 arm64 Python binaries that `setup-python` tries to use # don't work on macOS 15 anymore, so skip those. diff --git a/README.md b/README.md index 9e21837..13cdd09 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,12 @@ pip install -U pip setuptools wheel pip install cymem ``` +### Free threading + +`cymem` has support for being built and run under free-threaded CPython. +Currently `Pool` is not thread safe when used from multiple threads at once; +**please avoid sharing a single** `Pool` instance between threads. + ## Example Use Case: An array of structs Let's say we want a sequence of sparse matrices. We need fast access, and a @@ -160,7 +166,7 @@ cdef class MatrixArray: self.length = len(py_matrices) self.matrices = self.mem.alloc(self.length, sizeof(SparseMatrix*)) for i, py_matrix in enumerate(py_matrices): - self.matrices[i] = sparse_matrix_init(self.mem, py_matrix) + self.matrices[i] = sparse_matrix_init_cymem(self.mem, py_matrix) cdef SparseMatrix* sparse_matrix_init_cymem(Pool mem, list py_matrix) except NULL: sm = mem.alloc(1, sizeof(SparseMatrix)) diff --git a/pyproject.toml b/pyproject.toml index ab36d78..f4f0898 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,9 +7,9 @@ build-backend = "setuptools.build_meta" [tool.cibuildwheel] build = "*" -skip = "pp* cp36* cp37* cp38*" +skip = "pp* cp36* cp37* cp38* *t*_i686" test-skip = "" -free-threaded-support = false +enable = ["cpython-freethreading"] archs = ["native"] diff --git a/setup.py b/setup.py index df40294..8a7b87e 100755 --- a/setup.py +++ b/setup.py @@ -8,11 +8,17 @@ from setuptools.command.build_ext import build_ext from sysconfig import get_path from Cython.Build import cythonize +from Cython.Compiler.Version import version as cython_version +from packaging.version import Version PACKAGES = find_packages() MOD_NAMES = ["cymem.cymem"] +compiler_directives = dict() + +if Version(cython_version) >= Version("3.1.0"): + compiler_directives["freethreading_compatible"] = True # By subclassing build_extensions we have the actual compiler that will be used which is really known only after finalize_options # http://stackoverflow.com/questions/724664/python-distutils-how-to-get-a-compiler-that-is-going-to-be-used @@ -100,7 +106,8 @@ def setup_package(): version=about["__version__"], url=about["__uri__"], license=about["__license__"], - ext_modules=cythonize(ext_modules, language_level=2), + ext_modules=cythonize(ext_modules, language_level=3, + compiler_directives=compiler_directives), setup_requires=["cython>=0.25"], classifiers=[ "Environment :: Console",