You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
2.1 KiB
76 lines
2.1 KiB
2 years ago
|
"""Resource Manager."""
|
||
|
|
||
|
import logging
|
||
|
import time
|
||
|
|
||
|
from threading import Condition
|
||
|
from threading import Lock
|
||
|
from threading import Thread
|
||
|
|
||
|
|
||
|
LOGGER = logging.getLogger(__name__)
|
||
|
|
||
|
|
||
|
class Resource:
|
||
|
def __init__(self, manager, resources: int):
|
||
|
self._manager = manager
|
||
|
self._resources = resources
|
||
|
|
||
|
def release(self):
|
||
|
LOGGER.debug("Resource of %d will be returned", self._resources)
|
||
|
self._manager.release(self._resources)
|
||
|
|
||
|
@property
|
||
|
def resources(self):
|
||
|
return self._resources
|
||
|
|
||
|
|
||
|
class ResourceManager:
|
||
|
def __init__(self, total_resources: int):
|
||
|
self._total_resources = total_resources
|
||
|
self._cond = Condition(Lock())
|
||
|
LOGGER.debug("Created a manager with %d resources", self._total_resources)
|
||
|
|
||
|
def grab(self, resources: int):
|
||
|
"""Grab a number of resources; if there are not enough resources
|
||
|
available, blocks till they become available.
|
||
|
"""
|
||
|
LOGGER.debug("Requesting %d resources; %d avaialble", resources, self._total_resources)
|
||
|
with self._cond:
|
||
|
self._cond.wait_for(lambda : self._total_resources >= resources)
|
||
|
self._total_resources -= resources
|
||
|
return Resource(self, resources)
|
||
|
|
||
|
def release(self, resources: int):
|
||
|
"""Return the number of resources to the pool."""
|
||
|
with self._cond:
|
||
|
self._total_resources += resources
|
||
|
self._cond.notify()
|
||
|
LOGGER.debug("%d resources returned, %d available", resources, self._total_resources)
|
||
|
|
||
|
|
||
|
def worker(pid, resources):
|
||
|
LOGGER.debug("Thread %d is holding %d resources", pid, resources.resources)
|
||
|
time.sleep(10)
|
||
|
LOGGER.debug("Thread %d finished, releasing %d resources", pid, resources.resources)
|
||
|
resources.release()
|
||
|
|
||
|
|
||
|
def main():
|
||
|
logging.basicConfig(level=logging.DEBUG)
|
||
|
manager = ResourceManager(10)
|
||
|
threads = []
|
||
|
|
||
|
for i in range(10):
|
||
|
resources = manager.grab(i+1)
|
||
|
w = Thread(target=worker, args=[i, resources])
|
||
|
threads.append(w)
|
||
|
w.start()
|
||
|
|
||
|
for t in threads:
|
||
|
t.join()
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|