#python #simpy
Вопрос:
В моей программе агентам необходимо использовать некоторые определенные ресурсы. Я хочу одновременно вызвать все ресурсы, назначенные агенту, и использовать первый доступный.
Подумайте о 3 серверах и 4 агентах.
agent1
может использовать server1
,
agent2
может использовать server1
и server2
,
agent3
может использовать server2
и server3
,
agent4
может использовать server3
Я создаю запросы, как показано ниже:
{server: server.request() for server in agent_2_server_list}
output:
{<simpy.resources.resource.Resource at 0x7fd091b215e0>: <Request() object at 0x7fd091d51d00>,
<simpy.resources.resource.Resource at 0x7fd091b21700>: <Request() object at 0x7fd091d51b50>}
Я использую env.any_of([request1, request2])
для использования любой из вышеперечисленных запросов. Однако мне нужно знать, какой ресурс используется, чтобы я мог освободить его позже. Как я могу это сделать?
Ответ №1:
env.any_of возвращает список первых событий, которые запустились. Помните, что оба события могут произойти одновременно. Также помните, что если срабатывает только одно событие, второе событие все еще находится в ожидании. Поэтому, если вы хотите, чтобы сработало только одно событие, вам нужно будет проверить, сработали ли оба события, и освободить одно или, если сработало только одно событие, отменить второе событие.
вот пример
"""
example of getting the first avalable resouce from 2 resouce pools
prorammer Michael R. Gibbs
"""
import simpy
def seat(env, id, smokingRes, nonSmokingRes):
"""
Main process of getting the first avaialbe table
from one of two resouce pools (smoking, non smoking)
"""
# make a request from both resouce pools
print(env.now, id, "waiting for a table")
smokeReq = smokingRes.request()
nonSmokeReq = nonSmokingRes.request()
# wait for one of the requests to be filled
seat = yield env.any_of([smokeReq,nonSmokeReq])
seatList = list(seat.keys())
# it is possible that both resources are avaliable
# and both request get filled
seated = seatList[0]
if len(seatList) > 1:
# both requests got filled, need to release one
print(env.now, id, "both were available, releasing one")
if seated == smokeReq:
nonSmokingRes.release(nonSmokeReq)
else:
smokingRes.release(smokeReq)
else:
# only one request was filled, need to cancel the other request
print(env.now, id, 'got a seat, cancel other request')
if smokeReq in seatList:
nonSmokeReq.cancel()
else:
smokeReq.cancel()
yield env.timeout(5)
if seated == smokeReq:
smokingRes.release(seated)
else:
nonSmokingRes.release(seated)
print(env.now, id, "released seat")
def test(env, smokingRes, nonSmokingRes):
"""
test when four people want 2 tables
"""
env.process(seat(env,1,smokingRes,nonSmokingRes))
yield env.timeout(1)
env.process(seat(env,2,smokingRes,nonSmokingRes))
yield env.timeout(1)
env.process(seat(env,3,smokingRes,nonSmokingRes))
yield env.timeout(1)
env.process(seat(env,4,smokingRes,nonSmokingRes))
env = simpy.Environment()
smokingRes = simpy.Resource(env, capacity=1)
nonSmokingRes = simpy.Resource(env, capacity=1)
env.process(test(env,smokingRes,nonSmokingRes))
env.run(until=100)
print ('done')
Комментарии:
1. Это как раз моя проблема. Выход
server_request = yield self.env.any_of(server_requests)
есть<ConditionValue {<Request() object at 0x7fc2e1de54d0>: None}>
. У меня есть словарь для отслеживания ресурсов и запросов сервера. Из этого словаря я пытаюсь найти, какой ресурс используется, но<ConditionValue {<Request() object at 0x7fc2e1de54d0>: None}>
он не дает мне много информации. server_request.events выдает мне запрос типа<Request() object at 0x7fc2e1de54d0>
, но так как я не знаю, какой из них используется, я не могу освободить ни один из них.2. да, server_request-это диктат событий, которые произошли, помните, что одновременно может произойти несколько событий. вы можете преобразовать дикт в список запросов с помощью req_list = list(server_request .keys()). Значение None-это значение, возвращаемое событием при его запуске. запрос ресурсов не использует это, поэтому это не так. Также помните, что вам нужно будет обработать запрос, который вы не используете, либо отпустить его, либо отменить. Я также обновил свой ответ примером any_of
3. Великий Майкл. Спасибо. Я не думаю, что в документации упоминается «когда используется any_of, одновременно может срабатывать более одного события». Я надеюсь, что этот пост сможет объяснить эту концепцию.