[gnome-music/wip/mschraal/file-exists-async: 29/30] asyncqueue: Dispatch tasks on a timer
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/file-exists-async: 29/30] asyncqueue: Dispatch tasks on a timer
- Date: Sat, 4 Sep 2021 21:53:52 +0000 (UTC)
commit f00e084acc2edbea53d3717eee8d099ee8fea441
Author: Marinus Schraal <mschraal gnome org>
Date: Sat Sep 4 23:09:00 2021 +0200
asyncqueue: Dispatch tasks on a timer
Previously Asyncqueue used a recursive call to queue more tasks, in rare
cases this could lead to hitting the Python recursion depth.
To avoid this, use timeout based scheduling.
gnomemusic/asyncqueue.py | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
---
diff --git a/gnomemusic/asyncqueue.py b/gnomemusic/asyncqueue.py
index 125b2145f..bb8710566 100644
--- a/gnomemusic/asyncqueue.py
+++ b/gnomemusic/asyncqueue.py
@@ -25,7 +25,7 @@
from typing import Any, Dict, Optional, Tuple
import time
-from gi.repository import GObject
+from gi.repository import GObject, GLib
from gnomemusic.musiclogger import MusicLogger
@@ -60,6 +60,8 @@ class AsyncQueue(GObject.GObject):
self._max_async = 4
self._queue_name = queue_name if queue_name else self
+ self._timeout_id = 0
+
def queue(self, *args: Any) -> None:
"""Queue an async call
@@ -68,16 +70,17 @@ class AsyncQueue(GObject.GObject):
to the `start` call of the given class.
See the class doc for more information.
"""
- async_obj = args[0]
- async_obj_id = id(async_obj)
- result_id = 0
+ async_obj_id = id(args[0])
if (async_obj_id not in self._async_pool
and async_obj_id not in self._async_active_pool):
self._async_pool[async_obj_id] = (args)
- else:
- return
+ if self._timeout_id == 0:
+ self_timeout_id = GLib.timeout_add(250, self._dispatch)
+
+ def _dispatch(self) -> bool:
+ result_id = 0
tick = time.time()
def on_async_finished(obj, *signal_args):
@@ -97,10 +100,15 @@ class AsyncQueue(GObject.GObject):
args = self._async_pool.pop(key)
self.queue(*args)
- if len(self._async_active_pool) < self._max_async:
- async_task_args = self._async_pool.pop(async_obj_id)
+ if len(self._async_pool) == 0:
+ self._timeout_id = 0
+ return GLib.SOURCE_REMOVE
+ elif len(self._async_active_pool) < self._max_async:
+ async_obj_id, async_task_args = self._async_pool.popitem()
async_obj = async_task_args[0]
self._async_active_pool[async_obj_id] = async_task_args
result_id = async_obj.connect("finished", on_async_finished)
async_obj.start(*async_task_args[1:])
+
+ return GLib.SOURCE_CONTINUE
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]