mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-28 08:48:53 +00:00
41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
|
|
from twisted.internet import defer
|
|
from foolscap.api import eventually
|
|
|
|
class ConcurrencyLimiter:
|
|
"""I implement a basic concurrency limiter. Add work to it in the form of
|
|
(callable, args, kwargs) tuples. No more than LIMIT callables will be
|
|
outstanding at any one time.
|
|
"""
|
|
|
|
def __init__(self, limit=10):
|
|
self.limit = limit
|
|
self.pending = []
|
|
self.active = 0
|
|
|
|
def __repr__(self):
|
|
return "<Limiter with %d/%d/%d>" % (self.active, len(self.pending),
|
|
self.limit)
|
|
|
|
def add(self, cb, *args, **kwargs):
|
|
d = defer.Deferred()
|
|
task = (cb, args, kwargs, d)
|
|
self.pending.append(task)
|
|
self.maybe_start_task()
|
|
return d
|
|
|
|
def maybe_start_task(self):
|
|
if self.active >= self.limit:
|
|
return
|
|
if not self.pending:
|
|
return
|
|
(cb, args, kwargs, done_d) = self.pending.pop(0)
|
|
self.active += 1
|
|
d = defer.maybeDeferred(cb, *args, **kwargs)
|
|
d.addBoth(self._done, done_d)
|
|
|
|
def _done(self, res, done_d):
|
|
self.active -= 1
|
|
eventually(done_d.callback, res)
|
|
eventually(self.maybe_start_task)
|