Задача такая. Нужно реализовать функцию, которая будет перебирать какой-то общедоступный список и уничтожать сама себя(вместе с потоком), в случае, если этот список вдруг стал пустым. Потом, при добавлении нового элемента в этот список, нужно как-то вызывать эту функцию, делающую тоже самое.
Функцию, я называю чистильщиком
Пример куска кода того, как делал я:
(импортирование модулей и прочие подробности я опустил, чтобы показать только суть)
# Обработчик WebSocket соединений
class WSHandler(tornado.websocket.WebSocketHandler):
def open(self):
pass
def on_close(self):
# Узнаем остановлен ли чистильщик
startCleaner = False
if len(app.SessionsRestore) < 1:
startCleaner = True
# Временно сохраняем сессию в хранилище
app.SessionsRestore.append({
"sid":self.sid,
"time_of_dead":datetime.now() + timedelta(minutes=5),
})
# Запускаем чистильщик сессий, если он был остановлен
if startCleaner:
app.clear_sessions_restore()
def on_message(self,data):
#Тут делаем разнообразные операции, не зависимо от чистильщика и т.п.
pass
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/ws", WSHandler),
]
# Это список, который должен перебирать чистильщик
self.SessionsRestore = list()
tornado.web.Application.__init__(self, handlers)
# Чистильщик, работающий асинхронно
# Следит за тем, чтобы сессии не лежали в этом хранилище слишком долго
@tornado.web.asynchronous
def clear_sessions_restore(self):
while True:
# Останавливаем чистильщик, если чистить нечего
if len(self.SessionsRestore) < 1:
break
# Уменьшаем количество проходов в секунду
time.sleep(5)
# Осуществляем проход по хранилищу сессий
for session in self.SessionsRestore:
if session['time_of_dead'] > datetime.now():
self.SessionsRestore.remove(session)
# И примерно такой запуск серва
if __name__ == "__main__":
tornado.options.parse_command_line()
app = Application()
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Так вот, думал что использование декоратора
@tornado.web.asynchronous сделает метод асинхронным, но не тут то было. На строчке, где вызывается этот метод, выполнение кода виснет до тех пор, пока не закончится "вечный" цикл внутри этого метода. В связи с этим не вижу ничего, кроме как писать все "ручками", используя модуль threading и т.п. Сделать это не составит труда, но хотелось бы сделать это ресурсами tornado . И не прибегать к велосипедам.
Веду разработку из Windows. Может из-за этого все проблемы и на *nix все будет окей? Если так, то подскажите, как можно реализовать пусть непроизводительную, но без ковыряния кода самого проекта нормальную поддержку асинхронности.