source file: /home/buildslave/tahoe/edgy/build/src/allmydata/util/limiter.py
file stats: 26 lines, 26 executed: 100.0% covered
   1. 
   2. from twisted.internet import defer
   3. from foolscap.eventual import eventually
   4. 
   5. class ConcurrencyLimiter:
   6.     """I implement a basic concurrency limiter. Add work to it in the form of
   7.     (callable, args, kwargs) tuples. No more than LIMIT callables will be
   8.     outstanding at any one time.
   9.     """
  10. 
  11.     def __init__(self, limit=10):
  12.         self.limit = limit
  13.         self.pending = []
  14.         self.active = 0
  15. 
  16.     def add(self, cb, *args, **kwargs):
  17.         d = defer.Deferred()
  18.         task = (cb, args, kwargs, d)
  19.         self.pending.append(task)
  20.         self.maybe_start_task()
  21.         return d
  22. 
  23.     def maybe_start_task(self):
  24.         if self.active >= self.limit:
  25.             return
  26.         if not self.pending:
  27.             return
  28.         (cb, args, kwargs, done_d) = self.pending.pop(0)
  29.         self.active += 1
  30.         d = defer.maybeDeferred(cb, *args, **kwargs)
  31.         d.addBoth(self._done, done_d)
  32. 
  33.     def _done(self, res, done_d):
  34.         self.active -= 1
  35.         eventually(done_d.callback, res)
  36.         self.maybe_start_task()