Skip to content

Commit

Permalink
Add tornado.locks.BoundedSemaphore.
Browse files Browse the repository at this point in the history
  • Loading branch information
ajdavis committed Feb 27, 2015
1 parent 825eec0 commit a7454fc
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
20 changes: 19 additions & 1 deletion tornado/locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from __future__ import absolute_import, division, print_function, with_statement

__all__ = ['Condition', 'Event', 'Semaphore']
__all__ = ['Condition', 'Event', 'Semaphore', 'BoundedSemaphore']

import collections

Expand Down Expand Up @@ -223,3 +223,21 @@ def __enter__(self):
" 'with semaphore'")

__exit__ = __enter__


class BoundedSemaphore(Semaphore):
"""A semaphore that prevents release() being called too many times.
If `.release` would increment the semaphore's value past the initial
value, it raises `ValueError`. Semaphores are mostly used to guard
resources with limited capacity, so a semaphore released too many times
is a sign of a bug.
"""
def __init__(self, value=1):
super(BoundedSemaphore, self).__init__(value=value)
self._initial_value = value

def release(self):
if self._value >= self._initial_value:
raise ValueError("Semaphore released too many times")
super(BoundedSemaphore, self).release()
15 changes: 15 additions & 0 deletions tornado/test/locks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,5 +349,20 @@ def test_context_manager_misuse(self):
pass


class BoundedSemaphoreTest(AsyncTestCase):
def test_release_unacquired(self):
sem = locks.BoundedSemaphore()
self.assertRaises(ValueError, sem.release)
# Value is 0.
sem.acquire()
# Block on acquire().
future = sem.acquire()
self.assertFalse(future.done())
sem.release()
self.assertTrue(future.done())
# Value is 1.
sem.release()
self.assertRaises(ValueError, sem.release)

if __name__ == '__main__':
unittest.main()

0 comments on commit a7454fc

Please sign in to comment.