async def acquire_lock(lock: asyncio.Lock, timeout: float = 1.0) -> bool: # suppress TimeoutError because we'll return False in case of timeout try: await asyncio.wait_for(lock.acquire(), timeout) return True except asyncio.TimeoutError: return False
class Stock: def __init__(self): self.items = [] self.lock = Lock() def get_display_items(self): return [item for item in self.items if (item.state == ItemState.ON_DISPLAY)] # requires lock fo state check and set def fetch_item_from_display(self, item_type): """ Get an item from display, if available :param item_type: the type of item requested :return: The requested item or None """ item = None yield from self.lock.acquire() items = [item for item in self.items if (item.state == ItemState.ON_DISPLAY and item.type == item_type)] if len(items) > 0: item = items[0] item.state = ItemState.IN_CART self.lock.release() yield item # requires lock for id increment def insert_item(self, item): """ Add an item to the warehouse :param item: the item to add :return: the item after added to the warehouse. Now uniquely identified """ assert item.type is not None yield from self.lock.acquire() item.id = len(self.items) item.state = ItemState.ON_DISPLAY self.items.append(item) self.lock.release() yield item
async def _wait_response(lock: asyncio.Lock, queue: asyncio.Queue): """Wait for the direct ACK message, and post False if timeout reached.""" # TODO: Need to consider the risk of this. We may be unlocking a prior send command. # This would mean that the prior command will terminate. What happens when the # prior command returns a direct ACK then this command returns a direct ACK? # Do not believe this is an issue but need to test. if lock.locked(): lock.release() await lock.acquire() try: await asyncio.wait_for(lock.acquire(), TIMEOUT) except asyncio.TimeoutError: if lock.locked(): await queue.put(ResponseStatus.FAILURE) if lock.locked(): lock.release()
class FrameHandler(object): """Handler for incoming frames, also synchronizes the flow.""" def __init__(self, channel): self.channel = channel self.loop = channel.loop self.partial_message = None self.callbacks = {} self.expected_frame = None self.expected_methods = () self.response = None self.lock = Lock(loop=self.loop) def update(self, d): self.callbacks.update(d) @contextmanager def wait_for(self, *expected): """Context manager used to synchronize the flow. Example:: with handler.wait_for(QueueDeclareOK) as fut: channel.queue_declare(*args) yield from fut # Will lock until QueueDeclareOK is recieved """ yield from self.lock.acquire() self.expected_frame = MethodFrame self.expected_methods = expected r = self.response = Future(loop=self.loop) # Some methods may not wait for the reply # In this case the code below will allow to instantly return # when yielding from r if expected[0] is None: r.set_result(None) try: yield r finally: self.expected_frame = None self.expected_methods = () self.response = None self.lock.release() def ready(self, result=None): """Notify synchronizer that the expected method was recieved.""" self.response.set_result(result) def handle(self, frame, payload, *, CONTENT_SPEC=(BasicReturn, BasicDeliver, BasicGetOK)): """Handle incoming frame""" # At first, check if an unexpected frame was received response = self.response if self.expected_frame is not None and frame != self.expected_frame: exc = UnexpectedFrame(UNEXPECTED_FRAME_FMT.format( self.expected_frame, frame )) response.set_exception(exc) # raise exception in the waiter return if frame == MethodFrame: payload, method = frame.unpack(payload) if method.synchronous: # Check of an unexpected method was received if not any(method == cls for cls in self.expected_methods): exc = UnexpectedFrame(UNEXPECTED_FRAME_FMT.format( self.expected_methods, method )) # raise exception in the waiter response.set_exception(exc) return if any(method == cls for cls in CONTENT_SPEC): # Save what we have and wait for the message header self.partial_message = BasicMessage() self.expected_frame = HeaderFrame else: try: callback = self.callbacks[method.method_type] except KeyError: # Recieved reply and there is no handler for it if method.method_type not in METHODS: response.set_exception(UnknownMethod( UNKNOWN_METHOD_FMT.format(method.method_type) )) self.ready(payload) else: # Schedule task to handle the method async(callback(*payload)) elif frame == HeaderFrame: msg = self.partial_message msg._add_header(payload) if msg._ready: # Bodyless message self.partial_message = None response.set_result(msg) else: # Wait for the message body self.expected_frame = BodyFrame elif frame == BodyFrame: msg = self.partial_message msg._add_body_chunk(payload) if msg._ready: self.expected_frame = None self.partial_message = None response.set_result(msg)
class Environment: def __init__(self, world, app_name, screen_size): self.__world = world self.__screen_size = screen_size self.__logger = logging.getLogger(app_name) self.__game = PyGameManager(app_name, screen_size) self.vehicle = None self.camera = None self.collision_sensor = None self.collision = False self.__actors = [] self.__logger.info("Create environment...") self.__init() self.__colliding = Lock() def __init(self): self.vehicle = Vehicle(build_vehicle(self.__world, Actor.TESLA_MODEL_3)) self.vehicle.control(throttle=1.0, steer=0.0) self.__game.vehicle(self.vehicle) location = Location(x=1.1, z=1.2) self.camera = build_camera(self.__world, self.__screen_size, self.vehicle, location) self.camera.listen(self.__game.render) self.collision_sensor = build_collision_sensor(self.__world, self.vehicle, location) self.collision_sensor.listen(lambda event: self.__on_collision(event)) self.__actors = [ self.camera, self.vehicle.wrapped(), self.collision_sensor ] def reset(self): self.__logger.info(f"Relocate {self.vehicle.name()} actor...") self.vehicle.random_location(self.__world) def loop(self, callback): self.__game.loop(lambda game: self.__loop(game, callback)) def __loop(self, game, callback): callback(self) def close(self): self.__destroy_actors() self.__logger.info("Close window...") self.__game.quit() def __destroy_actors(self): for actor in self.__actors: if actor is not None: self.__logger.info(f"Destroy {actor}") actor.destroy() def __on_collision(self, event): try: self.__colliding.acquire() try: self.__logger.info(f"{self.vehicle.name()} vehicle collide...") time.sleep(2) self.reset() finally: self.__colliding.release() except RuntimeError: return
def get(self, **kwargs): a1 = '' a2 = '' u1 = '' u2 = '' text = '' if 'avatar0' in self.params: a1 = kwargs.pop('avatar1', None) if not a1: raise MissingParameterError('avatar1') if 'avatar1' in self.params: a2 = kwargs.pop('avatar2', '') if not a2: raise MissingParameterError('avatar2') if 'username0' in self.params: u1 = kwargs.pop('username1', '') if not u1: raise MissingParameterError('username1') if 'username1' in self.params: u2 = kwargs.pop('username2', '') if not u2: raise MissingParameterError('username2') if 'text' in self.params: text = kwargs.pop('text', '') if not text: raise MissingParameterError('text') params = {"text": str(text), "username1": str(u1), "username2": str(u2), "avatar1": str(a1), "avatar2": str(a2)} for k, v in kwargs.items(): params[k] = v lock = _locks.get(self.name) if not lock: lock = Lock(loop=self._session.loop) _locks[self.name] = lock yield from lock.acquire() with MaybeUnlock(lock) as maybe_lock: for tries in range(5): r = yield from self._session.get('%s/api/%s' % (self.BASE, self.name), headers=self._headers, params=params) remaining = r.headers.get('X-Ratelimit-Remaining') if remaining == '0' and r.status != 429: delta = _parse_ratelimit_header(r) maybe_lock.defer() self._session.loop.call_later(delta, lock.release) if r.status == 429: retry_after = int(r.headers['retry-after']) / 1000 data = yield from r.json() is_global = data.get('global', False) if is_global: self._global_over.clear() yield from sleep(retry_after, loop=self._session.loop) if is_global: self._global_over.set() continue if r.status == 200: result = yield from r.read() return BytesIO(result), r.headers['Content-Type'].split('/')[1] if r.status in (500, 502): yield from sleep(1 + tries * 2, loop=self._session.loop) continue result = yield from r.text() if r.status == 401: raise IncorrectTokenError elif r.status == 403: raise Forbidden elif r.status == 400: raise BadRequest(result) elif r.status == 404: raise NotFound(result) raise HTTPError(result)