pyatomix


Namepyatomix JSON
Version 0.1.2 PyPI version JSON
download
home_pageNone
SummaryCross platform atomic int for Python
upload_time2025-02-10 09:16:20
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseBSD
keywords atomic atomics free-threading no-gil
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ## pyatomix provides std::atomic_flag and std::atomic<int64_t> for Python

Compatible with Python 3.13 free-threaded.
Windows users will need to have Visual Studio (or VS Build Tools) installed to build this.
It uses Pybind11 and pip/setuptools will build it automatically.  It's been tested on Windows and Linux.

Linux users will need the Python dev package installed for their Python version to install atomix, for instance: python3.13-dev

## Installation

```
pip install -U pyatomix
-or-
git clone https://github.com/0xDEADFED5/pyatomix.git
pip install -U ./pyatomix
```

## Usage

```python
from pyatomix import AtomicInt, AtomicFlag
x = AtomicInt(7)     # initial value of 7
x += 1               # now it's 8, this is atomic
y = AtomicFlag()     # y == False
z = y.test_and_set() # z == False, y == True
y.clear()            # y == False
```
the API is exactly the same as std::atomic and std::atomic_flag.
all the math operators except **, >>, <<=, >>, >>= are overridden for AtomicInt.

atomic assignment operators: +=, -=, &=, |=, ^= (using these are an atomic operation)

other assignment operators like %=,/=,//=,*= first load the value, then store the modified value. those operators are thread-safe, but not atomic.

## Performance

Depending on compiler and OS, AtomicInt increment is 4-6x slower than a standard increment, which is still pretty fast.
1 million atomic increments in a for loop takes me 160ms in Linux, while incrementing a regular int 1 million times takes 40ms.

## To run the tests

```python
from pyatomix import AtomicTest
x = AtomicTest()
x.run()
```

NOTE: the AtomicFlag test will hang unless you're running a free-threaded build of Python

## API list, all these are atomic

```python
AtomicInt.is_lock_free() -> bool   : returns True if it's lock free, should be True for most
AtomicInt.store(value) -> None     : assign value, doesn't return anything
AtomicInt.load() -> int            : read value
AtomicInt.fetch_add(value) -> int  : add to current value, return previous value
AtomicInt.fetch_sub(value) -> int  : subtract from current value, return previous value
AtomicInt.exchange(value) -> int   : assign value, return previous value
AtomicInt.compare_exchange(expected, value) -> bool : 
    if current value == expected, replace it with value. returns True on success.
AtomicInt.compare_exchange_weak(expected, value) -> bool : 
    same as compare_exchange, but may fail spuriously. faster on some platforms, use in a loop.

AtomicFlag.clear() -> None        : set value to False
AtomicFlag.test_and_set() -> bool : set value to True and return previous value
AtomicFlag.test() -> bool         : read value
AtomicFlag.wait(bool cmp) -> bool : if current value == cmp, wait until signaled
AtomicFlag.notify_one() -> None   : notify one or more threads that the value has changed
AtomicFlag.notify_all() -> None   : notify all threads that the value has changed
```

## AtomicFlag overloaded operators: 

`==,!=` (will work with "falsy" types too)

## AtomicInt overloaded operators:

`==,!=,-,~,+,+=,-=,*,*=,/,/=,//,//=,|,|=,%,%=,&,&=,^,^=,>,>=,<,<=`

(trying to use anything other than an int with these will fail)


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pyatomix",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "0xDEADFED5 <admin@terminoid.com>",
    "keywords": "atomic, atomics, free-threading, no-GIL",
    "author": null,
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/49/c4/86cc5abf5cecdfb7646dcb81ff2e42e984b0d8d386fbbf53ab5125817f04/pyatomix-0.1.2.tar.gz",
    "platform": null,
    "description": "## pyatomix provides std::atomic_flag and std::atomic<int64_t> for Python\r\n\r\nCompatible with Python 3.13 free-threaded.\r\nWindows users will need to have Visual Studio (or VS Build Tools) installed to build this.\r\nIt uses Pybind11 and pip/setuptools will build it automatically.  It's been tested on Windows and Linux.\r\n\r\nLinux users will need the Python dev package installed for their Python version to install atomix, for instance: python3.13-dev\r\n\r\n## Installation\r\n\r\n```\r\npip install -U pyatomix\r\n-or-\r\ngit clone https://github.com/0xDEADFED5/pyatomix.git\r\npip install -U ./pyatomix\r\n```\r\n\r\n## Usage\r\n\r\n```python\r\nfrom pyatomix import AtomicInt, AtomicFlag\r\nx = AtomicInt(7)     # initial value of 7\r\nx += 1               # now it's 8, this is atomic\r\ny = AtomicFlag()     # y == False\r\nz = y.test_and_set() # z == False, y == True\r\ny.clear()            # y == False\r\n```\r\nthe API is exactly the same as std::atomic and std::atomic_flag.\r\nall the math operators except **, >>, <<=, >>, >>= are overridden for AtomicInt.\r\n\r\natomic assignment operators: +=, -=, &=, |=, ^= (using these are an atomic operation)\r\n\r\nother assignment operators like %=,/=,//=,*= first load the value, then store the modified value. those operators are thread-safe, but not atomic.\r\n\r\n## Performance\r\n\r\nDepending on compiler and OS, AtomicInt increment is 4-6x slower than a standard increment, which is still pretty fast.\r\n1 million atomic increments in a for loop takes me 160ms in Linux, while incrementing a regular int 1 million times takes 40ms.\r\n\r\n## To run the tests\r\n\r\n```python\r\nfrom pyatomix import AtomicTest\r\nx = AtomicTest()\r\nx.run()\r\n```\r\n\r\nNOTE: the AtomicFlag test will hang unless you're running a free-threaded build of Python\r\n\r\n## API list, all these are atomic\r\n\r\n```python\r\nAtomicInt.is_lock_free() -> bool   : returns True if it's lock free, should be True for most\r\nAtomicInt.store(value) -> None     : assign value, doesn't return anything\r\nAtomicInt.load() -> int            : read value\r\nAtomicInt.fetch_add(value) -> int  : add to current value, return previous value\r\nAtomicInt.fetch_sub(value) -> int  : subtract from current value, return previous value\r\nAtomicInt.exchange(value) -> int   : assign value, return previous value\r\nAtomicInt.compare_exchange(expected, value) -> bool : \r\n    if current value == expected, replace it with value. returns True on success.\r\nAtomicInt.compare_exchange_weak(expected, value) -> bool : \r\n    same as compare_exchange, but may fail spuriously. faster on some platforms, use in a loop.\r\n\r\nAtomicFlag.clear() -> None        : set value to False\r\nAtomicFlag.test_and_set() -> bool : set value to True and return previous value\r\nAtomicFlag.test() -> bool         : read value\r\nAtomicFlag.wait(bool cmp) -> bool : if current value == cmp, wait until signaled\r\nAtomicFlag.notify_one() -> None   : notify one or more threads that the value has changed\r\nAtomicFlag.notify_all() -> None   : notify all threads that the value has changed\r\n```\r\n\r\n## AtomicFlag overloaded operators: \r\n\r\n`==,!=` (will work with \"falsy\" types too)\r\n\r\n## AtomicInt overloaded operators:\r\n\r\n`==,!=,-,~,+,+=,-=,*,*=,/,/=,//,//=,|,|=,%,%=,&,&=,^,^=,>,>=,<,<=`\r\n\r\n(trying to use anything other than an int with these will fail)\r\n\r\n",
    "bugtrack_url": null,
    "license": "BSD",
    "summary": "Cross platform atomic int for Python",
    "version": "0.1.2",
    "project_urls": {
        "Github": "https://github.com/0xDEADFED5/pyatomix",
        "Homepage": "https://github.com/0xDEADFED5/pyatomix"
    },
    "split_keywords": [
        "atomic",
        " atomics",
        " free-threading",
        " no-gil"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a54785f1c1da06cc7658d257d7d31d26d48e861ec8d30c107c46e8eab783864b",
                "md5": "6a7e69c729cc7f94f7a055a213f4c9d0",
                "sha256": "eb78d26ffbfd8e5a58c398d0ea31a203ade84ebf0f0351e59e95e324893805a2"
            },
            "downloads": -1,
            "filename": "pyatomix-0.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "6a7e69c729cc7f94f7a055a213f4c9d0",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 4813,
            "upload_time": "2025-02-10T09:16:18",
            "upload_time_iso_8601": "2025-02-10T09:16:18.752388Z",
            "url": "https://files.pythonhosted.org/packages/a5/47/85f1c1da06cc7658d257d7d31d26d48e861ec8d30c107c46e8eab783864b/pyatomix-0.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "49c486cc5abf5cecdfb7646dcb81ff2e42e984b0d8d386fbbf53ab5125817f04",
                "md5": "146523b967f656dfae75eb2475830bfd",
                "sha256": "d31cab740a5c450609d95b39ee235630aebed3b402e26ce1ee49470eb40912df"
            },
            "downloads": -1,
            "filename": "pyatomix-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "146523b967f656dfae75eb2475830bfd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 4959,
            "upload_time": "2025-02-10T09:16:20",
            "upload_time_iso_8601": "2025-02-10T09:16:20.551315Z",
            "url": "https://files.pythonhosted.org/packages/49/c4/86cc5abf5cecdfb7646dcb81ff2e42e984b0d8d386fbbf53ab5125817f04/pyatomix-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-10 09:16:20",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "0xDEADFED5",
    "github_project": "pyatomix",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pyatomix"
}
        
Elapsed time: 1.80598s