Skip to content

Thread-safe atomic counters #124366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
colesbury opened this issue Sep 23, 2024 · 2 comments
Open

Thread-safe atomic counters #124366

colesbury opened this issue Sep 23, 2024 · 2 comments
Labels
topic-free-threading type-feature A feature request or enhancement

Comments

@colesbury
Copy link
Contributor

colesbury commented Sep 23, 2024

Feature or enhancement

Python doesn't currently have a thread-safe atomic counter. CPython currently internally uses a few different patterns to implement thread-safe counters. For example, some test code uses appends to a shared list because the implementation of list.append() is atomic.

We should provide a counter that is explicitly thread-safe so that people don't have to rely on other idioms. The minimum initial API should provide:

  • atomic increment
  • get value (i.e., inspect)

The threading module may be a good place for it.

cc @rhettinger

@colesbury colesbury added type-feature A feature request or enhancement topic-free-threading labels Sep 23, 2024
@rhettinger
Copy link
Contributor

rhettinger commented Sep 23, 2024

Possible reference implementation:

from threading import Lock

class AtomicCounter:

    def __init__(self, start=0) -> None:
        self.count = start
        self.lock = Lock()

    def increment(self) -> int:
        "Update and return the new count."
        with self.lock:
            self.count += 1
            return self.count

    def inspect(self) -> int:
        "May be out of date by the time the result is returned."
        with self.lock:   
            return self.count

    def __repr__(self) -> str:
        return f'{type(self).__name__}(start={self.count})'

API note: Unlike other mutating methods, the atomic increment operation returns the new count instead of None. This lets the caller avoid a race condition to determine the new count.

Also, we should consider having a public C_API for accessing this object.

@Yiling-J
Copy link

Yiling-J commented Nov 3, 2024

How about implementing general atomic types instead of a specific counter if counter is simply a wrapper of atomic? For example atomic.int and atomic.bool, each with methods like load, store, and swap.

On the other hand, if the counter has additional functionality beyond atomic operations, a dedicated counter type could be useful. For example in Go, I use xsync counter, which is an optimized concurrent counter. Even so, I believe adding atomic types would still be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-free-threading type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants