При работе с запросами без оператора with в качестве контекстного менеджера наблюдается странное поведение, которое приводит к постоянной блокировке ресурсов при использовании стандартного шаблона if req in res и того и другого. условия происходят симулировано следующим образом.
req = resource.request()
result = yield req | env.timeout(5) # req and timeout occurs simultaneously
if req in result:
# DO SOMETHING WITH RESOURCE
resource.release(req)
else:
req.cancel() # Important as req is still in resource queue and can be triggered after timeout, which is another possible cause of a resource being locked permanently
assert not req.triggered # Quirky behaviour here as req can be triggered at this point
После дальнейшего изучения я обнаружил, что в result хранятся только обработанные события, поэтому req может быть запущен, но еще не обработан (хотя я чувствую, что что запуск request() приводит к немедленной обработке, более интуитивно понятен), поэтому мы вводим блок кода else. После выполнения кода в блоке else запрос будет обработан, но поскольку выполнение кода уже прошло блок if, req остается висящим и невыпущенным. .
Изначально я думал, что req.cancel() достаточно, но похоже, что он не отменяет сработавшее событие (поправьте меня, если я ошибаюсь) . Таким образом, я придумал альтернативу, которая, по-видимому, устранила проблему.
# Rest of code
else:
req.cancel()
resource.release(req) # Doesn't feel right
(Я могу ошибаться, поэтому поправьте меня, если необходимо) Если req будет обработан позже, запланировано событие Release или, что эквивалентно, get позже и обязательно освободит ресурс, чтобы он не оставался висящим, и даже если req не было предоставлено, Release(req) не вызовет исключения.
Однако мне не понравился такой подход. По правде говоря, я должен оказаться в блоке if, если получу ресурс в заданное время моделирования, даже если фактическая обработка req происходит «позже» в очереди, что отражает фактическое поведение. Поэтому я попробовал другой метод, который, похоже, тоже работает...
# rest of code
if req.triggered:
# rest of code
else:
req.cancel()
# rest of code
Итак, как следует из названия этого поста, является ли этот последний метод эквивалентным выполнению стандартного шаблона и, следовательно, безопасным? Будет ли при этом какая-либо опасность, поскольку технически я «пропускаю время», рассматривая запрос как обработанный до его фактической обработки (у меня нет случая, когда ресурс используется 0 раз, а затем освобождается , но было бы интересно узнать, может ли это быть проблемой)? Возможно, лучше найти способ переупорядочить события так, чтобы req обрабатывался первым, несмотря на то, что он был помещен в очередь позже, чем событие тайм-аута? Заранее большое спасибо!
Изменить: пример кода, демонстрирующий поведение.
import random
import simpy
def source(env, number, counter):
for i in range(number):
c = customer(env, counter)
env.process(c)
yield env.timeout(1)
def customer(env, counter):
patience = 5
while True:
req = counter.request()
results = yield req | env.timeout(patience)
print(f'req triggered = {req.triggered}, req processed = {req.processed}, req in result = {req in results}')
if req in results:
yield env.timeout(5)
counter.release(req)
break
else:
if req.triggered:
assert 0
req.cancel()
random.seed(42)
env = simpy.Environment()
counter = simpy.Resource(env, capacity=1)
env.process(source(env, 100, counter))
env.run(until=100)
Подробнее здесь: https://stackoverflow.com/questions/793 ... tead-of-if
При получении событий AnyOf безопасно ли использовать if req.triggered вместо if req in res? ⇐ Python
Программы на Python
1735178370
Anonymous
При работе с запросами без оператора with в качестве контекстного менеджера наблюдается странное поведение, которое приводит к постоянной блокировке ресурсов при использовании стандартного шаблона if req in res и того и другого. условия происходят симулировано следующим образом.
req = resource.request()
result = yield req | env.timeout(5) # req and timeout occurs simultaneously
if req in result:
# DO SOMETHING WITH RESOURCE
resource.release(req)
else:
req.cancel() # Important as req is still in resource queue and can be triggered after timeout, which is another possible cause of a resource being locked permanently
assert not req.triggered # Quirky behaviour here as req can be triggered at this point
После дальнейшего изучения я обнаружил, что в result хранятся только обработанные события, поэтому req может быть запущен, но еще не обработан (хотя я чувствую, что что запуск request() приводит к немедленной обработке, более интуитивно понятен), поэтому мы вводим блок кода else. После выполнения кода в блоке else запрос будет обработан, но поскольку выполнение кода уже прошло блок if, req остается висящим и невыпущенным. .
Изначально я думал, что req.cancel() достаточно, но похоже, что он не отменяет сработавшее событие (поправьте меня, если я ошибаюсь) . Таким образом, я придумал альтернативу, которая, по-видимому, устранила проблему.
# Rest of code
else:
req.cancel()
resource.release(req) # Doesn't feel right
(Я могу ошибаться, поэтому поправьте меня, если необходимо) Если req будет обработан позже, запланировано событие Release или, что эквивалентно, get позже и обязательно освободит ресурс, чтобы он не оставался висящим, и даже если req не было предоставлено, Release(req) не вызовет исключения.
Однако мне не понравился такой подход. По правде говоря, я должен оказаться в блоке if, если получу ресурс в заданное время моделирования, даже если фактическая обработка req происходит «позже» в очереди, что отражает фактическое поведение. Поэтому я попробовал другой метод, который, похоже, тоже работает...
# rest of code
if req.triggered:
# rest of code
else:
req.cancel()
# rest of code
Итак, как следует из названия этого поста, является ли этот последний метод эквивалентным выполнению стандартного шаблона и, следовательно, безопасным? Будет ли при этом какая-либо опасность, поскольку технически я «пропускаю время», рассматривая запрос как обработанный до его фактической обработки (у меня нет случая, когда ресурс используется 0 раз, а затем освобождается , но было бы интересно узнать, может ли это быть проблемой)? Возможно, лучше найти способ переупорядочить события так, чтобы req обрабатывался первым, несмотря на то, что он был помещен в очередь позже, чем событие тайм-аута? Заранее большое спасибо!
Изменить: пример кода, демонстрирующий поведение.
import random
import simpy
def source(env, number, counter):
for i in range(number):
c = customer(env, counter)
env.process(c)
yield env.timeout(1)
def customer(env, counter):
patience = 5
while True:
req = counter.request()
results = yield req | env.timeout(patience)
print(f'req triggered = {req.triggered}, req processed = {req.processed}, req in result = {req in results}')
if req in results:
yield env.timeout(5)
counter.release(req)
break
else:
if req.triggered:
assert 0
req.cancel()
random.seed(42)
env = simpy.Environment()
counter = simpy.Resource(env, capacity=1)
env.process(source(env, 100, counter))
env.run(until=100)
Подробнее здесь: [url]https://stackoverflow.com/questions/79304669/when-yielding-anyof-events-is-it-safe-to-use-if-req-triggered-instead-of-if[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия