Name | pyatomix JSON |
Version |
0.1.2
JSON |
| download |
home_page | None |
Summary | Cross platform atomic int for Python |
upload_time | 2025-02-10 09:16:20 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.7 |
license | BSD |
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"
}