Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Lib/test/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -2339,6 +2339,30 @@ def run_last():
self.assertIn("RuntimeError: can't register atexit after shutdown",
err.decode())

class TestAtomicCounter(unittest.TestCase):
def setUp(self):
self.counter = threading.AtomicCounter()

def test_initial_value(self):
self.assertEqual(self.counter.get(), 0)

def test_increment(self):
self.counter.inc()
self.assertEqual(self.counter.get(), 1)
self.counter.inc(5)
self.assertEqual(self.counter.get(), 6)

def test_decrement(self):
self.counter.dec()
self.assertEqual(self.counter.get(), -1)
self.counter.dec(5)
self.assertEqual(self.counter.get(), -6)

def test_increment_and_decrement(self):
self.counter.inc(10)
self.counter.dec(3)
self.assertEqual(self.counter.get(), 7)


if __name__ == "__main__":
unittest.main()
27 changes: 26 additions & 1 deletion Lib/threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
'Barrier', 'BrokenBarrierError', 'Timer', 'ThreadError',
'setprofile', 'settrace', 'local', 'stack_size',
'excepthook', 'ExceptHookArgs', 'gettrace', 'getprofile',
'setprofile_all_threads','settrace_all_threads']
'setprofile_all_threads','settrace_all_threads', 'AtomicCounter']

# Rename some stuff so "from threading import *" is safe
_start_joinable_thread = _thread.start_joinable_thread
Expand Down Expand Up @@ -857,6 +857,31 @@ def _newname(name_template):
_dangling = WeakSet()


class AtomicCounter:
"""Threadsafe counter.

Returns the value after inc/dec operations.
"""

def __init__(self, initial=0):
self._value = initial
self._lock = Lock()

def inc(self, n=1):
with self._lock:
self._value += n
return self._value

def dec(self, n=1):
with self._lock:
self._value -= n
return self._value

def get(self):
with self._lock:
return self._value


# Main class for threads

class Thread:
Expand Down
Loading