Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a non-blocking alternative to wait_for_action #36

Open
ssokolow opened this issue Sep 18, 2017 · 12 comments
Open

Add a non-blocking alternative to wait_for_action #36

ssokolow opened this issue Sep 18, 2017 · 12 comments

Comments

@ssokolow
Copy link

From what I could gather by looking at the API docs, the only current alternative to wait_for_action is to reinvent the whole thing as part of another event loop, even if all the user wants to do is listen for a few extra D-Bus signals.

It'd really help if wait_for_action were refactored so that it's not necessary to copy-and-paste the relevant bits into dependent projects which want to run more general event loops.

@hoodie
Copy link
Owner

hoodie commented Sep 18, 2017

Hi there!
Thanks for the input, I had that in the back of my head for a while, but back then there was no such thing as futures yet. AFAIK you would still need a local event loop for that. Wanna help me with that?

@ssokolow
Copy link
Author

Some of the actual use cases I either want to port from Python or implement in Rust from the start if it's not too bothersome include:

  1. A libnotify-based Biff tool, which listens for inotify "a write/append-mode file handle on the mbox file was just closed" events as well as libnotify "The 'open Mutt' action button was clicked" events. I'd like to be able to do this in a single thread, since it's just selecting on FDs at the lowest level.

  2. A libnotify-based update notifier, which uses a timer in the event loop to check for pending updates every so often, and listens for "The 'open apt-get terminal' action button was clicked" events. (In my current Python implementation, I just use a Glib event loop and register both a timer and an FD watcher.)

  3. Various resident things which need to listen for both the action buttons and their own D-Bus APIs... possibly along with other things, like a libxcb FD for XGrabKey global hotkeys. (Again, in existing ones, I just use the integration between the Python D-Bus and Glib bindings and register a Glib watcher on the FD underlying the libxcb handle.)

@hoodie
Copy link
Owner

hoodie commented Sep 18, 2017

I was thinking more along the line of code examples. But I assume you imagine an api like this:

    let notification_future = Notification::new()
        .summary("you got mail")
        .action("clicked", "open Mutt") // IDENTIFIER, LABEL
        .show()
        .unwrap()
        .then({|action|
            match action {
                "clicked"  => {unimplemeted!()},
                "__closed" => println!("the notification was closed"),
                _ => ()
            }
        });

which would not block. You would still have to have your own event loop though.

@ssokolow
Copy link
Author

I was envisioning something broadly like what you propose, combined with some "Handle if this is ours. Otherwise, ignore. Indicate whether it was ours." function that the event loop would call upon receipt of a D-Bus message. (Possibly after ruling out its D-Bus events of its own.)

I'm not very experienced with Rust, compared to GCed languages, so I don't trust myself to design a good API and I'm flexible on what it should look like.

@hoodie
Copy link
Owner

hoodie commented Sep 18, 2017

what do you mean with ours? ATM you could have the blocking api in a thread, thats not that expensive. I can add an optional feature that does what I described here, but it would add a dependency to the futures library for me and the user. Other than e.g. javascript rust doesn't have a runtime with an event loop.

@ssokolow
Copy link
Author

ssokolow commented Sep 18, 2017

ATM you could have the blocking api in a thread, thats not that expensive.

Threads are best suited to working in parallel, not waiting in parallel. As a matter of principle, I try to avoid using them for the latter.

Also, it's bad enough when I have to open more than one X11 socket from the same process (eg. in Python programs where I need XGrabKey and a GUI toolkit that doesn't offer a way to share its FD with XPyB or python-xlib.) I don't want to have to open more than one D-Bus connection from the same process too.

I can add an optional feature that does what I described here, but it would add a dependency to the futures library for me and the user. Other than e.g. javascript rust doesn't have a runtime with an event loop.

I missed the let notification_future when initially reading your API example, so we misunderstood each other.

I didn't mean to ask for futures. All I want is an API which makes it comfortable to call something like Notification::handle_registered_actions(dbus_message) inside the "We received a D-Bus message" handler I hang off my event loop. (Similar to how, with python-xlib, you can add a watcher for the python-xlib FD to your Glib event loop and, whenever it fires, call next_event() on your Xlib.display.Display instance in a loop until it returns None.)

As-is, I'd have to copy-paste an unappealing amount of code from notify-rust to my "We received a D-Bus message" handler.

@ssokolow
Copy link
Author

Oh, as for this...

what do you mean with ours?

in that context, "ours" refers to notify-rust. Here it is rephrased:

I was envisioning something broadly like what you propose, combined with some "Handle if this is a message destined for notify-rust. Otherwise, ignore. Indicate whether it was handled." function that the event loop would call upon receipt of a D-Bus message. (Possibly after ruling out its D-Bus events of its own.)

@hoodie
Copy link
Owner

hoodie commented Sep 18, 2017

I didn't mean to ask for futures. All I want is an API which makes it comfortable to call something like Notification::handle_registered_actions(dbus_message) inside the "We received a D-Bus message" handler I hang off my event loop. (Similar to how, with python-xlib, you can add a watcher for the python-xlib FD to your Glib event loop and, whenever it fires, call next_event() on your Xlib.display.Display instance in a loop until it returns None.)

Do you mean something like this internal function? we could put the body of this loop in an extra function and make that public.
Would you want to try that out and make a PR if it works?

@ssokolow
Copy link
Author

That sounds like it's probably the right approach, but I'm overdue for bed and tiredness has hit me like a ton of bricks, so I'll give you a proper reply after I've slept and can think again.

@ssokolow
Copy link
Author

Sorry about going silent for a couple of days. I woke up to find myself swamped with more pressing concerns that I'm still working to clear out.

I'll leave this tab open and get back to you as soon as I can find a little more time.

@hoodie
Copy link
Owner

hoodie commented Sep 20, 2017

There is no need to apologise or rush at all. Same here

@ssokolow
Copy link
Author

Still, I said "I'll give you a proper reply after I've slept and can think again," which generally implies that one intends to reply in some way the following day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants