Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
pools.py187 linesDownload Raw Back to eventlet
1from __future__ import print_function2 3import collections4from contextlib import contextmanager5 6from eventlet import queue7 8 9__all__ = ['Pool', 'TokenPool']10 11 12class Pool(object):13    """14    Pool class implements resource limitation and construction.15 16    There are two ways of using Pool: passing a `create` argument or17    subclassing. In either case you must provide a way to create18    the resource.19 20    When using `create` argument, pass a function with no arguments::21 22        http_pool = pools.Pool(create=httplib2.Http)23 24    If you need to pass arguments, build a nullary function with either25    `lambda` expression::26 27        http_pool = pools.Pool(create=lambda: httplib2.Http(timeout=90))28 29    or :func:`functools.partial`::30 31        from functools import partial32        http_pool = pools.Pool(create=partial(httplib2.Http, timeout=90))33 34    When subclassing, define only the :meth:`create` method35    to implement the desired resource::36 37        class MyPool(pools.Pool):38            def create(self):39                return MyObject()40 41    If using 2.5 or greater, the :meth:`item` method acts as a context manager;42    that's the best way to use it::43 44        with mypool.item() as thing:45            thing.dostuff()46 47    The maximum size of the pool can be modified at runtime via48    the :meth:`resize` method.49 50    Specifying a non-zero *min-size* argument pre-populates the pool with51    *min_size* items.  *max-size* sets a hard limit to the size of the pool --52    it cannot contain any more items than *max_size*, and if there are already53    *max_size* items 'checked out' of the pool, the pool will cause any54    greenthread calling :meth:`get` to cooperatively yield until an item55    is :meth:`put` in.56    """57 58    def __init__(self, min_size=0, max_size=4, order_as_stack=False, create=None):59        """*order_as_stack* governs the ordering of the items in the free pool.60        If ``False`` (the default), the free items collection (of items that61        were created and were put back in the pool) acts as a round-robin,62        giving each item approximately equal utilization.  If ``True``, the63        free pool acts as a FILO stack, which preferentially re-uses items that64        have most recently been used.65        """66        self.min_size = min_size67        self.max_size = max_size68        self.order_as_stack = order_as_stack69        self.current_size = 070        self.channel = queue.LightQueue(0)71        self.free_items = collections.deque()72        if create is not None:73            self.create = create74 75        for x in range(min_size):76            self.current_size += 177            self.free_items.append(self.create())78 79    def get(self):80        """Return an item from the pool, when one is available.  This may81        cause the calling greenthread to block.82        """83        if self.free_items:84            return self.free_items.popleft()85        self.current_size += 186        if self.current_size <= self.max_size:87            try:88                created = self.create()89            except:90                self.current_size -= 191                raise92            return created93        self.current_size -= 1  # did not create94        return self.channel.get()95 96    @contextmanager97    def item(self):98        """ Get an object out of the pool, for use with with statement.99 100        >>> from eventlet import pools101        >>> pool = pools.TokenPool(max_size=4)102        >>> with pool.item() as obj:103        ...     print("got token")104        ...105        got token106        >>> pool.free()107        4108        """109        obj = self.get()110        try:111            yield obj112        finally:113            self.put(obj)114 115    def put(self, item):116        """Put an item back into the pool, when done.  This may117        cause the putting greenthread to block.118        """119        if self.current_size > self.max_size:120            self.current_size -= 1121            return122 123        if self.waiting():124            try:125                self.channel.put(item, block=False)126                return127            except queue.Full:128                pass129 130        if self.order_as_stack:131            self.free_items.appendleft(item)132        else:133            self.free_items.append(item)134 135    def resize(self, new_size):136        """Resize the pool to *new_size*.137 138        Adjusting this number does not affect existing items checked out of139        the pool, nor on any greenthreads who are waiting for an item to free140        up.  Some indeterminate number of :meth:`get`/:meth:`put`141        cycles will be necessary before the new maximum size truly matches142        the actual operation of the pool.143        """144        self.max_size = new_size145 146    def free(self):147        """Return the number of free items in the pool.  This corresponds148        to the number of :meth:`get` calls needed to empty the pool.149        """150        return len(self.free_items) + self.max_size - self.current_size151 152    def waiting(self):153        """Return the number of routines waiting for a pool item.154        """155        return max(0, self.channel.getting() - self.channel.putting())156 157    def create(self):158        """Generate a new pool item.  In order for the pool to159        function, either this method must be overriden in a subclass160        or the pool must be constructed with the `create` argument.161        It accepts no arguments and returns a single instance of162        whatever thing the pool is supposed to contain.163 164        In general, :meth:`create` is called whenever the pool exceeds its165        previous high-water mark of concurrently-checked-out-items.  In other166        words, in a new pool with *min_size* of 0, the very first call167        to :meth:`get` will result in a call to :meth:`create`.  If the first168        caller calls :meth:`put` before some other caller calls :meth:`get`,169        then the first item will be returned, and :meth:`create` will not be170        called a second time.171        """172        raise NotImplementedError("Implement in subclass")173 174 175class Token(object):176    pass177 178 179class TokenPool(Pool):180    """A pool which gives out tokens (opaque unique objects), which indicate181    that the coroutine which holds the token has a right to consume some182    limited resource.183    """184 185    def create(self):186        return Token()187 
codekingpro/portable-devtools · Team Ai