Skip to content

Commit

Permalink
Use callbacks for local objects signals
Browse files Browse the repository at this point in the history
This is a more flexible approach and also avoids allocating a dict
for every initialized object. Instead a weakref set will be
allocated for every signal. (maybe optimized later with lazy
allocation)
  • Loading branch information
igo95862 committed Jan 13, 2024
1 parent e7bd8dc commit 25661bd
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 32 deletions.
3 changes: 0 additions & 3 deletions src/sdbus/dbus_common_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
from .sd_bus_internals import is_interface_name_valid, is_member_name_valid

if TYPE_CHECKING:
from asyncio import Queue
from types import FunctionType
from typing import (
Any,
Expand Down Expand Up @@ -336,8 +335,6 @@ def __init__(self) -> None:
self.activated_interfaces: List[SdBusInterface] = []
self.serving_object_path: Optional[str] = None
self.attached_bus: Optional[SdBus] = None
self.local_signal_queues: Dict[
Tuple[str, str], Set[Queue[Any]]] = {}


class DbusClassMeta:
Expand Down
54 changes: 25 additions & 29 deletions src/sdbus/dbus_proxy_async_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
TypeVar,
cast,
)
from weakref import WeakSet

from .dbus_common_elements import (
DbusBindedAsync,
Expand All @@ -52,6 +53,24 @@

class DbusSignalAsync(DbusSomethingAsync, DbusSingalCommon, Generic[T]):

def __init__(
self,
signal_name: Optional[str],
signal_signature: str,
args_names: Sequence[str],
flags: int,
original_method: FunctionType
):
super().__init__(
signal_name,
signal_signature,
args_names,
flags,
original_method,
)

self.local_callbacks: WeakSet[Callable[[T], Any]] = WeakSet()

def __get__(
self,
obj: Optional[DbusInterfaceBaseAsync],
Expand Down Expand Up @@ -162,29 +181,17 @@ def __init__(
self.__doc__ = dbus_signal.__doc__

async def catch(self) -> AsyncIterator[T]:
signal_key = (
self.dbus_signal.interface_name,
self.dbus_signal.signal_name,
)

try:
list_of_queues = self.local_meta.local_signal_queues[
signal_key
]
except KeyError:
list_of_queues = set()
self.local_meta.local_signal_queues[
signal_key] = list_of_queues

new_queue: Queue[T] = Queue()

list_of_queues.add(new_queue)
signal_callbacks = self.dbus_signal.local_callbacks
try:
put_method = new_queue.put_nowait
signal_callbacks.add(put_method)
while True:
next_data = await new_queue.get()
yield next_data
finally:
list_of_queues.remove(new_queue)
signal_callbacks.remove(put_method)

__aiter__ = catch

Expand Down Expand Up @@ -227,19 +234,8 @@ def _emit_dbus_signal(self, args: T) -> None:
def emit(self, args: T) -> None:
self._emit_dbus_signal(args)

signal_key = (
self.dbus_signal.interface_name,
self.dbus_signal.signal_name,
)

try:
list_of_queues = self.local_meta.local_signal_queues[
signal_key]
except KeyError:
return

for local_queue in list_of_queues:
local_queue.put_nowait(args)
for callback in self.dbus_signal.local_callbacks:
callback(args)


class DbusSignalAsyncClassBind(DbusSignalAsyncBaseBind[T]):
Expand Down

0 comments on commit 25661bd

Please sign in to comment.