Skip to main content

atomics

This library implements a wrapper around the lower level patomic C library (which is provided as part of this library through the build_patomic command in setup.py).

It exposes hardware level lock-free (and address-free) atomic operations on a memory buffer, either internally allocated or externally provided, via a set of atomic classes.

The operations in these classes are both thread-safe and process-safe, meaning that they can be used on a shared memory buffer for interprocess communication (including with other languages such as C/C++).

Table of Contents

Installing

Linux/MacOS:

$ python3 -m pip install atomics

Windows:

$ py -m pip install atomics

This library requires Python3.6+, and has a dependency on the cffi library. While the code here has no dependency on any implementation specific features, the cffi library functions used are likely to not work outside of CPython and PyPy.

Binaries are provided for the following platforms:

  • Windows [x86, amd64]
  • MacOSX [x86_64, universal2]
  • Linux [i686, x86_64, aarch64, ppc64le, s390x] [manylinux2014, musllinux_1_1]
  • Linux [i686, x86_64] [manylinux1]

If you are on one of these platforms and pip tries to build from source or fails to install, make sure that you have the latest version of pip installed. This can be done like so:

Linux/MacOS:

$ python3 -m pip install --upgrade pip

Windows:

$ py -m pip install --upgrade pip

If you need to build from source, check out the Building section as there are additional requirements for that.

Examples

Incorrect

The following example has a data race (ais modified from multiple threads). The program is not correct, and a's value will not equal total at the end.

from threading import Thread


a = 0


def fn(n: int) -> None:
    global a
    for _ in range(n):
        a += 1


if __name__ == "__main__":
    # setup
    total = 10_000_000
    # run threads to completion
    t1 = Thread(target=fn, args=(total // 2,))
    t2 = Thread(target=fn, args=(total // 2,))
    t1.start(), t2.start()
    t1.join(), t2.join()
    # print results
    print(f"a[{a}] != total[{total}]")

Multi-Threading

This example implements the previous example but a is now an AtomicInt which can be safely modified from multiple threads (as opposed to int which can't). The program is correct, and a will equal total at the end.

import atomics
from threading import Thread


def fn(ai: atomics.INTEGRAL, n: int) -> None:
    for _ in range(n):
        ai.inc()


if __name__ == "__main__":
    # setup
    a = atomics.atomic(width=4, atype=atomics.INT)
    total = 10_000
    # run threads to completion
    t1 = Thread(target=fn, args=(a, total // 2))
    t2 = Thread(target=fn, args=(a, total // 2))
    t1.start(), t2.start()
    t1.join(), t2.join()
    # print results
    print(f"a[{a.load()}] == total[{total}]")

Multi-Processing

This example is the counterpart to the above correct code, but using processes to demonstrate that atomic operations are also safe across processes. This program is also correct, and a will equal total at the end. It is also how one might communicate with processes written in other languages such as C/C++.

import atomics
from multiprocessing import Process, shared_memory


def fn(shmem_name: str, width: int, n: int) -> None:
    shmem = shared_memory.SharedMemory(name=shmem_name)
    buf = shmem.buf[:width]
    with atomics.atomicview(buffer=buf, atype=atomics.INT) as a:
        for _ in range(n):
            a.inc()
    del buf
    shmem.close()


if __name__ == "__main__":
    # setup
    width = 4
    shmem = shared_memory.SharedMemory(create=True, size=width)
    buf = shmem.buf[:width]
    total = 10_000
    # run processes to completion
    p1 = Process(target=fn, args=(shmem.name, width, total // 2))
    p2 = Process(target=fn, args=(shmem.name, width, total // 2))
    p1.start(), p2.start()
    p1.join(), p2.join()
    # print results and cleanup
    with atomics.atomicview(buffer=buf, atype=atomics.INT) as a:
        print(f"a[{a.load()}] == total[{total}]")
    del buf
    shmem.close()
    shmem.unlink()

NOTE: Although shared_memory is showcased here, atomicview accepts any type that supports the buffer protocol as its buffer argument, so other sources of shared memory such as mmap could be used instead.

Docs

Types

The following helper (abstract-ish base) types are available in atomics:

  • [ANY, INTEGRAL, BYTES, INT, UINT]

This library provides the following Atomic classes in atomics.base:

  • Atomic --- ANY
  • AtomicIntegral --- INTEGRAL
  • AtomicBytes --- BYTES
  • AtomicInt --- INT
  • AtomicUint --- UINT

These Atomic classes are constructable on their own, but it is strongly suggested using the atomic() function to construct them. Each class corresponds to one of the above helper types (as indicated).

This library also provides Atomic*View (in atomics.view) and Atomic*ViewContext (in atomics.ctx) counterparts to the Atomic* classes, corresponding to the same helper types.

The latter of the two sets of classes can be constructed manually, although it is strongly suggested using the atomicview() function to construct them. The former set of classes cannot be constructed manually with the available types, and should only be obtained by called .__enter__() on a corresponding Atomic*ViewContext object.

Even though you should never need to directly use these classes (apart from the helper types), they are provided to be used in type hinting. The inheritance hierarchies are detailed in the ARCHITECTURE.md file (available on GitHub).

Construction

This library provides the functions atomic and atomicview, along with the types BYTES, INT, and UINT (as well as ANY and INTEGRAL) to construct atomic objects like so:

import atomics

a = atomics.atomic(width=4, atype=atomics.INT)
print(a)  # AtomicInt(value=0, width=4, readonly=False, signed=True)

buf = bytearray(2)
with atomics.atomicview(buffer=buf, atype=atomics.BYTES) as a:
    print(a)  # AtomicBytesView(value=b'\x00\x00', width=2, readonly=True)

You should only need to construct objects with an atype of BYTES, INT, or UINT. Using an atype of ANY or INTGERAL will require additional kwargs, and an atype of ANY will result in an object that doesn't actually expose any atomic operations (only properties, explained in sections further on).

The atomic() function returns a corresponding Atomic* object.

The atomicview() function returns a corresponding Atomic*ViewContext object. You can use this context object in a with statement to obtain an Atomic*View object. The buffer parameter may be any object that supports the buffer protocol.

Construction can raise UnsupportedWidthException and AlignmentError.

NOTE: the width property of Atomic*View objects is derived from the buffer's length as if it were contiguous. It is equivalent to calling memoryview(buf).nbytes.

Lifetime

Objects of Atomic* classes (i.e. objects returned by the atomic() function) have a self-contained buffer which is automatically freed. They can be passed around and stored liked regular variables, and there is nothing special about their lifetime.

Objects of Atomic*ViewContext classes (i.e. objects returned by the atomicview() function) and Atomic*View objects obtained from said objects have a much stricter usage contract.

Contract

The buffer used to construct an Atomic*ViewContext object (either directly or through atomicview()) MUST NOT be invalidated until .release() is called. This is aided by the fact that .release() is called automatically in .__exit__(...) and .__del__(). As long as you immediately use the context object in a with statement, and DO NOT invalidate the buffer inside that with scope, you will always be safe.

The protections implemented are shown in this example:

import atomics


buf = bytearray(4)
ctx = atomics.atomicview(buffer=buf, atype=atomics.INT)

# ctx.release() here will cause ctx.__enter__() to raise:
# ValueError("Cannot open context after calling 'release'.")

with ctx as a:  # this calls ctx.__enter__()
    # ctx.release() here will raise:
    # ValueError("Cannot call 'release' while context is open.")

    # ctx.__enter__() here will raise:
    # ValueError("Cannot open context multiple times.")
    
    print(a.load())  # ok

# ctx.__exit__(...) now called
# we can safely invalidate object 'buf' now

# ctx.__enter__() will raise:
# ValueError("Cannot open context after calling 'release'.")

# accessing object 'a' in any way will also raise an exception

Furthermore, in CPython, all built-in types supporting the buffer protocol will throw a BufferError exception if you try to invalidate them while they're in use (i.e. before calling .release()).

As a last resort, if you absolutely must invalidate the buffer inside the with context (where you can't call .release()), you may call .__exit__(...) manually on the Atomic*ViewContext object. This is to force explicitness about something considered to be bad practice and dangerous.

Where it's allowed, .release() may be called multiple times with no ill-effects. This also applies to .__exit__(...), which has no restrictions on where it can be called.

Alignment

Different platforms may each have their own alignment requirements for atomic operations of given widths. This library provides the Alignment class in atomics to ensure that a given buffer meets these requirements.

from atomics import Alignment

buf = bytearray(8)
align = Alignment(len(buf))
assert align.is_valid(buf)

If an atomic class is constructed from a misaligned buffer, the constructor will raise AlignmentError.

By default, .is_valid calls .is_valid_recommended. The class Alignment also exposes .is_valid_minimum. Currently, no atomic class makes use of the minimum alignment, so checking for it is pointless. Support for it will be added in a future release.

Properties

All Atomic* and Atomic*View classes have the following properties:

  • width: width in bytes of the underlying buffer (as if it were contiguous)
  • readonly: whether the object supports modifying operations
  • ops_supported: a sorted list of OpType enum values representing which operations are supported on the object

Integral Atomic* and Atomic*View classes also have the following property:

  • signed: whether arithmetic operations are signed or unsigned

In both cases, the behaviour on overflow is defined to wraparound.

Operations

Base Atomic and AtomicView objects (corresponding to ANY) expose no atomic operations.

AtomicBytes and AtomicBytesView objects support the following operations:

  • [base]: load, store
  • [xchg]: exchange, cmpxchg_weak, cmpxchg_strong
  • [bitwise]: bit_test, bit_compl, bit_set, bit_reset
  • [binary]: bin_or, bin_xor, bin_and, bin_not
  • [binary]: bin_fetch_or, bin_fetch_xor, bin_fetch_and, bin_fetch_not

Integral Atomic* and Atomic*View classes additionally support the following operations:

  • [arithmetic]: add, sub, inc, dec, neg
  • [arithmetic]: fetch_add, fetch_sub, fetch_inc, fetch_dec, fetch_neg

The usage of (most of) these functions is modelled directly on the C++11 std::atomic implementation found here.

Compare Exchange (cmpxchg_*)

The cmpxchg_* functions return CmpxchgResult. This has the attributes .success: bool which indicates whether the exchange took place, and .expected: T which holds the original value of the atomic object.
The cmpxchg_weak function may fail spuriously, even if expected matches the actual value. It should be used as shown below:

import atomics


def atomic_mul(a: atomics.INTEGRAL, operand: int):
    res = atomics.CmpxchgResult(success=False, expected=a.load())
    while not res:
        desired = res.expected * operand
        res = a.cmpxchg_weak(expected=res.expected, desired=desired)

In a real implementation of atomic_mul, care should be taken to ensure that desired fits in a (i.e. desired.bit_length() < (a.width * 8), assuming 8 bits in a byte).

Exceptions

All operations can raise UnsupportedOperationException (so check .ops_supported if you need to be sure).

Operations load, store, and cmpxchg_* can raise MemoryOrderError if called with an invalid memory order. MemoryOrder enum values expose the functions is_valid_store_order(), is_valid_load_order(), and is_valid_fail_order() to check with.

Special Methods

AtomicBytes and AtomicBytesView implement the __bytes__ special method.

Integral Atomic* and Atomic*View classes implement the __int__ special method. They intentionally do not implement __index__.

There is a notable lack of any classes implementing special methods corresponding to atomic operations; this is intentional. Assignment in Python is not available as a special method, and we do not want to encourage people to use other special methods with this class, lest it lead to them accidentally using assignment when they meant .store(...).

Memory Order

The MemoryOrder enum class is provided in atomics, and the memory orders are directly copied from C++11's std::memory_order documentation found here, except for CONSUME (which would be pointless to expose in this library).

All operations have a default memory order, SEQ_CST. This will enforce sequential consistency, and essentially make your multi-threaded and/or multi-processed program be as correct as if it were to run in a single thread.

IF YOU DO NOT UNDERSTAND THE LINKED DOCUMENTATION, DO NOT USE YOUR OWN MEMORY ORDERS!!! Stick with the defaults to be safe. (And realistically, this is Python, you won't get a noticeable performance boost from using a more lax memory order).

The following helper functions are provided:

  • .is_valid_store_order() (for store op)
  • .is_valid_load_order() ( for load op)
  • .is_valid_fail_order() (for the fail ordering in cmpxchg_* ops)

Passing an invalid memory order to one of these ops will raise MemoryOrderError.

Exceptions

The following exceptions are available in atomics.exc:

  • AlignmentError
  • MemoryOrderError
  • UnsupportedWidthException
  • UnsupportedOperationException

Building

IMPORTANT: Make sure you have the latest version of pip installed.

Using setup.py's build or bdist_wheel commands will run the build_patomic command (which you can also run directly).

This clones the patomic library into a temporary directory, builds it, and then copies the shared library into atomics._clib.

This requires that git be installed on your system (a requirement of the GitPython module). You will also need an ANSI/C90 compliant C compiler (although ideally a more recent compiler should be used). CMake is also required but should be automatically pip install'd if not available.

If you absolutely cannot get build_patomic to work, go to patomic, follow the instructions on building it (making sure to build the shared library version), and then copy-paste the shared library file into atomics._clib manually.

NOTE: Currently, the library builds a dummy extension in order to trick setuptools into building a non-purepython wheel. If you are ok with a purepython wheel, then feel free to remove the code for that from setup.py (at the bottom).
Otherwise, you will need a C99 compliant C compiler, and probably the development libraries/headers for whichever version of Python you're using.

Future Thoughts

  • add docstrings
  • add tests
  • add support for minimum alignment
  • add support for constructing Atomic classes' buffers in shared memory
  • add support for passing Atomic objects to sub-processes and sub-interpreters
  • reimplement in C or Cython for performance gains (preliminary benchmarks put such implementations at 2x the speed of a raw int)

Contributing

I don't have a guide for contributing yet. This section is here to make the following two points:

  • new operations must first be implemented in patomic before this library can be updated
  • new architectures, widths, and existing unsupported operations must be supported in patomic (no change required in this library)

Metadata

Release files for atomics 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for atomics 1.0.3
File Size Uploaded
atomics-1.0.3.tar.gz 44.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for atomics 1.0.3
File
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win_arm64.whl Python 3.11, Python 3.7, Python 3.10, Python 3.9, Python 3.6, Python 3.8 none Windows ARM64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win_amd64.whl Python 3.6, Python 3.11, Python 3.8, Python 3.7, Python 3.10, Python 3.9 none Windows x86-64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win32.whl Python 3.10, Python 3.9, Python 3.11, Python 3.6, Python 3.8, Python 3.7 none Windows x86-32 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_x86_64.whl Python 3.7, Python 3.8, Python 3.9, Python 3.11, Python 3.6, Python 3.10 none Linux musl 1.2+ x86-64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_s390x.whl Python 3.11, Python 3.10, Python 3.8, Python 3.7, Python 3.6, Python 3.9 none Linux musl 1.2+ IBM System/390x Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_ppc64le.whl Python 3.7, Python 3.9, Python 3.10, Python 3.11, Python 3.8, Python 3.6 none Linux musl 1.2+ PowerPC 64-le Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_i686.whl Python 3.11, Python 3.10, Python 3.8, Python 3.6, Python 3.7, Python 3.9 none Linux musl 1.2+ x86-32 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_aarch64.whl Python 3.6, Python 3.8, Python 3.10, Python 3.9, Python 3.11, Python 3.7 none Linux musl 1.2+ ARM64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_s390x.manylinux2014_s390x.whl Python 3.10, Python 3.9, Python 3.11, Python 3.6, Python 3.7, Python 3.8 none Linux glibc 2.17+ IBM System/390x Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl Python 3.6, Python 3.8, Python 3.7, Python 3.10, Python 3.9, Python 3.11 none Linux glibc 2.17+ PowerPC 64-le Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3.10, Python 3.9, Python 3.7, Python 3.11, Python 3.6, Python 3.8 none Linux glibc 2.17+ ARM64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3.6, Python 3.9, Python 3.8, Python 3.11, Python 3.7, Python 3.10 none Linux glibc 2.5+ x86-64, Linux glibc 2.17+ x86-64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl Python 3.11, Python 3.8, Python 3.6, Python 3.7, Python 3.10, Python 3.9 none Linux glibc 2.5+ x86-32, Linux glibc 2.17+ x86-32 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_11_0_arm64.whl Python 3.10, Python 3.9, Python 3.11, Python 3.6, Python 3.8, Python 3.7 none macOS 11.0+ ARM64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_10_9_x86_64.whl Python 3.7, Python 3.9, Python 3.10, Python 3.6, Python 3.11, Python 3.8 none macOS 10.9+ x86-64 Details
atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_10_9_universal2.whl Python 3.9, Python 3.11, Python 3.7, Python 3.6, Python 3.10, Python 3.8 none macOS 10.9+ universal2 (ARM64, x86-64) Details

Total release size: 2.5 MB

Release files / atomics-1.0.3.tar.gz

Download URL atomics-1.0.3.tar.gz
Size 44.2 kB
Tags Source
SHA-256 checksum
How to use checksums
97cb3f7514c1ac6cdf8900891565327b03bcf93e443989433ae0fe3a03187954
BLAKE2b-256 checksum
How to use checksums
e865240802d5c149fbd3ef08f322fc9b072fb1176b6bfca4ed8b16e611998de0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win_arm64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win_arm64.whl
Size 61.2 kB
Tags Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9 Windows ARM64
SHA-256 checksum
How to use checksums
0dd94388b3de1a9191a360d293e14d300ad89d5740801ea91362c5ceeb50de37
BLAKE2b-256 checksum
How to use checksums
09cdc0faecd5482be2cd9e20882478802557be1f69e84f62b8af01fb108b47db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win_amd64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win_amd64.whl
Size 62.4 kB
Tags Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9 Windows x86-64
SHA-256 checksum
How to use checksums
8e9b4d07026e6363d385cf8be767d1f35338e3c63fd44ec1e742734406b5f87d
BLAKE2b-256 checksum
How to use checksums
b66e02eee4fde6ff5fccedbbff8a6b390d32a974aaa1d4518c760a1f4736b55a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win32.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-win32.whl
Size 59.1 kB
Tags Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9 Windows x86-32
SHA-256 checksum
How to use checksums
b0998c0b956c85f2b135f343386359cf63249dc9508e555147fa9a856d42010c
BLAKE2b-256 checksum
How to use checksums
691cb283c14acc0145731e92c6fa86098a6be96fd831680f5695c06fc65f497d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_x86_64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_x86_64.whl
Size 185.7 kB
Tags Linux musl 1.2+ x86-64 Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
7d2e931185ba9fc541b3d2ab0a4c317e16cf57c4246a6842d38764c144a47304
BLAKE2b-256 checksum
How to use checksums
db6fefa448f77bfb4d4c53fe56cbaba98b61480b789da9139e6836df236417c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_s390x.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_s390x.whl
Size 217.2 kB
Tags Linux musl 1.2+ IBM System/390x Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
944d37eff284ea582ad07b0fb06c030d0c82cfabb27a807c5f6abe72a5d93dca
BLAKE2b-256 checksum
How to use checksums
52f686d7c6753647c66ef5103001a0cd6d96eba9f035b6c5df01dea918100a71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_ppc64le.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_ppc64le.whl
Size 200.3 kB
Tags Linux musl 1.2+ PowerPC 64-le Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
c67ea8557d6214656400f8ea2188525677bdb57a91649037fba944f391104bd5
BLAKE2b-256 checksum
How to use checksums
47275df3af055614b5695e3832fc6b5e936b4e9b4f86ad15b682e26175cedf0b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_i686.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_i686.whl
Size 162.2 kB
Tags Linux musl 1.2+ x86-32 Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
bcc1227b5b25fd1770738f6183201456b3777460c9e93f8027e5116c846a951e
BLAKE2b-256 checksum
How to use checksums
3991c466393543396cef27b8277e18c667be094068b59cc42ec1f09acfd73b76
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_aarch64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-musllinux_1_2_aarch64.whl
Size 232.5 kB
Tags Linux musl 1.2+ ARM64 Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
5392357c9da521d7618e6514913cda364fa3314a60c8eccedbeed197616f74f6
BLAKE2b-256 checksum
How to use checksums
463f6a6acb609f23d9836c472ec3c78e05bab5fb406001adfac890cdc3aef086
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_s390x.manylinux2014_s390x.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Size 218.9 kB
Tags Linux glibc 2.17+ IBM System/390x Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
19b4deec2c236d9bd81a2ffa4e45514c64663d5c50a2b028f5b146e209110f39
BLAKE2b-256 checksum
How to use checksums
8377f8251d38d52f9c16c5c5e028afc453f5022b131b3cedf904ba22ac5edd5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Size 202.9 kB
Tags Linux glibc 2.17+ PowerPC 64-le Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
ae378312bf3c7cd978e0322dadfb15582995494ad8bc1195713210491291b1ec
BLAKE2b-256 checksum
How to use checksums
988cdb21c91987bbaf73194c00fc6ef134cc7ff5f9980bc6abee500bb6ae3ac2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 237.2 kB
Tags Linux glibc 2.17+ ARM64 Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
53d5e875baf490b0e5d06578076758bd1257223b6bf4c76969034ffab4e9e5a8
BLAKE2b-256 checksum
How to use checksums
b3d7eebadf02b8ec5779abced24d0cdd53ed092dcfdbcbd1e0ead95d4c25d563
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 191.5 kB
Tags Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
19ed27f1ae3fe3353e9103e6d6f54af83e56a929f78ba061ae2e8e9435101daa
BLAKE2b-256 checksum
How to use checksums
c3ad7844f3e4e33cd3d770dd66dd8c0d091e5ff81851235ff4ccbbda760e7264
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Size 193.0 kB
Tags Linux glibc 2.17+ x86-32 Linux glibc 2.5+ x86-32 Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9
SHA-256 checksum
How to use checksums
0d3b5e05d351e3166088a931d039a953adc2a31a6f75ca553ec32b7b7ce372e3
BLAKE2b-256 checksum
How to use checksums
c8150a881091d36e7b0a536cff684b3b45708940c7d58be4f872b1b79fa01923
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_11_0_arm64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_11_0_arm64.whl
Size 71.2 kB
Tags Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d32c51d74d2f8ffc4554b1431d51c2261493bb7a338dc98dd669c356e1b493dd
BLAKE2b-256 checksum
How to use checksums
a9ed4086d2b88ff42fd756f38d82d78d45ed0faa21dbabbd7eb93cf166e57ebd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_10_9_x86_64.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_10_9_x86_64.whl
Size 70.3 kB
Tags Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
a4262ca6b5cbe167c30ebabc23cca0607c20c6e5293b8555ffbbeb020ecc850b
BLAKE2b-256 checksum
How to use checksums
214fdaed7e3bab85a5d214a17feba7764e90ae5d9be9002780dbf7df49a93397
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_10_9_universal2.whl

Download URL atomics-1.0.3-py36.py37.py38.py39.py310.py311-none-macosx_10_9_universal2.whl
Size 71.5 kB
Tags Python 3.10 Python 3.11 Python 3.6 Python 3.7 Python 3.8 Python 3.9 macOS 10.9+ universal2 (ARM64, x86-64)
SHA-256 checksum
How to use checksums
4a6b7bec9525683e128774916e045462ee9fae848c0fa416692c7ff7e2a7f032
BLAKE2b-256 checksum
How to use checksums
8de7cbc923d1eaf4d922bbc1cf8b76edb18cbfcbcebdf6b6be5f14eee24fc3c0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release history Release notifications | RSS feed

This release

1.0.3 This release

17 release files

1.0.2

15 release files

1.0.1

15 release files

1.0.0

15 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page