diff options
author | Jan D <jan.h.d@swipnet.se> | 2010-09-26 18:20:01 +0200 |
---|---|---|
committer | Jan D <jan.h.d@swipnet.se> | 2010-09-26 18:20:01 +0200 |
commit | 3fad2ad22ee508b6926c71fb87d53728bbc8f240 (patch) | |
tree | eaa1219476afef2e98a481aaa95c00d21436d86d /src/dbusbind.c | |
parent | 6303aba12277fcac6a597908fb047560cf7c0c3e (diff) | |
download | emacs-3fad2ad22ee508b6926c71fb87d53728bbc8f240.tar.gz |
Add fd handling with callbacks to select, dbus needs it for async operation.
* src/dbusbind.c: Include process.h.
(dbus_fd_cb, xd_find_watch_fd, xd_toggle_watch)
(xd_read_message_1): New functions.
(xd_add_watch, xd_remove_watch): Call xd_find_watch_fd. Handle
watch for both read and write.
(Fdbus_init_bus): Also register xd_toggle_watch.
(Fdbus_call_method_asynchronously, Fdbus_method_return_internal)
(Fdbus_method_error_internal, Fdbus_send_signal): Remove call
to dbus_connection_flush.
(xd_read_message): Move most of the code to xd_read_message_1.
Call xd_read_message_1 until status is COMPLETE.
* src/keyboard.c (readable_events, gobble_input): Remove DBUS code.
* src/process.c (gpm_wait_mask, max_gpm_desc): Remove.
(write_mask): New variable.
(max_input_desc): Renamed from max_keyboard_desc.
(fd_callback_info): New variable.
(add_read_fd, delete_read_fd, add_write_fd, delete_write_fd): New
functions.
(Fmake_network_process): FD_SET write_mask.
(deactivate_process): FD_CLR write_mask.
(wait_reading_process_output): Connecting renamed to Writeok.
check_connect removed. check_write is new. Remove references to
gpm. Use Writeok/check_write unconditionally (i.e. no #ifdef
NON_BLOCKING_CONNECT) instead of Connecting.
Loop over file descriptors and call callbacks in fd_callback_info
if file descriptor is ready for I/O.
(add_gpm_wait_descriptor): Just call add_keyboard_wait_descriptor.
(delete_gpm_wait_descriptor): Just call delete_keyboard_wait_descriptor.
(keyboard_bit_set): Use max_input_desc.
(add_keyboard_wait_descriptor, delete_keyboard_wait_descriptor): Remove
#ifdef subprocesses. Use max_input_desc.
(init_process): Initialize write_mask and fd_callback_info.
* src/process.h (add_read_fd, delete_read_fd, add_write_fd)
(delete_write_fd): Declare.
Diffstat (limited to 'src/dbusbind.c')
-rw-r--r-- | src/dbusbind.c | 170 |
1 files changed, 98 insertions, 72 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c index 3b6f0e543bb..a8db1c510c7 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "frame.h" #include "termhooks.h" #include "keyboard.h" +#include "process.h" /* Subroutines. */ @@ -799,71 +800,93 @@ xd_initialize (Lisp_Object bus, int raise_error) return connection; } +/* Callback called when something is read to read ow write. */ -/* Add connection file descriptor to input_wait_mask, in order to - let select() detect, whether a new message has been arrived. */ -dbus_bool_t -xd_add_watch (DBusWatch *watch, void *data) +static void +dbus_fd_cb (int fd, void *data, int for_read) +{ + xd_read_queued_messages (); +} + +/* Return the file descriptor for WATCH, -1 if not found. */ + +static int +xd_find_watch_fd (DBusWatch *watch) { - /* We check only for incoming data. */ - if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE) - { #if HAVE_DBUS_WATCH_GET_UNIX_FD - /* TODO: Reverse these on Win32, which prefers the opposite. */ - int fd = dbus_watch_get_unix_fd(watch); - if (fd == -1) - fd = dbus_watch_get_socket(watch); + /* TODO: Reverse these on Win32, which prefers the opposite. */ + int fd = dbus_watch_get_unix_fd (watch); + if (fd == -1) + fd = dbus_watch_get_socket (watch); #else - int fd = dbus_watch_get_fd(watch); + int fd = dbus_watch_get_fd (watch); #endif - XD_DEBUG_MESSAGE ("fd %d", fd); + return fd; +} - if (fd == -1) - return FALSE; - /* Add the file descriptor to input_wait_mask. */ - add_keyboard_wait_descriptor (fd); - } +/* Start monitoring WATCH for possible I/O. */ - /* Return. */ +static dbus_bool_t +xd_add_watch (DBusWatch *watch, void *data) +{ + unsigned int flags = dbus_watch_get_flags (watch); + int fd = xd_find_watch_fd (watch); + + XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d", + fd, flags & DBUS_WATCH_WRITABLE, + dbus_watch_get_enabled (watch)); + + if (fd == -1) + return FALSE; + + if (dbus_watch_get_enabled (watch)) + { + if (flags & DBUS_WATCH_WRITABLE) + add_write_fd (fd, dbus_fd_cb, NULL); + if (flags & DBUS_WATCH_READABLE) + add_read_fd (fd, dbus_fd_cb, NULL); + } return TRUE; } -/* Remove connection file descriptor from input_wait_mask. DATA is - the used bus, either a string or QCdbus_system_bus or +/* Stop monitoring WATCH for possible I/O. + DATA is the used bus, either a string or QCdbus_system_bus or QCdbus_session_bus. */ -void + +static void xd_remove_watch (DBusWatch *watch, void *data) { - /* We check only for incoming data. */ - if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE) - { -#if HAVE_DBUS_WATCH_GET_UNIX_FD - /* TODO: Reverse these on Win32, which prefers the opposite. */ - int fd = dbus_watch_get_unix_fd(watch); - if (fd == -1) - fd = dbus_watch_get_socket(watch); -#else - int fd = dbus_watch_get_fd(watch); -#endif - XD_DEBUG_MESSAGE ("fd %d", fd); + unsigned int flags = dbus_watch_get_flags (watch); + int fd = xd_find_watch_fd (watch); - if (fd == -1) - return; + XD_DEBUG_MESSAGE ("fd %d", fd); + + if (fd == -1) return; - /* Unset session environment. */ - if ((data != NULL) && (data == (void*) XHASH (QCdbus_session_bus))) - { - XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); - unsetenv ("DBUS_SESSION_BUS_ADDRESS"); - } - /* Remove the file descriptor from input_wait_mask. */ - delete_keyboard_wait_descriptor (fd); + /* Unset session environment. */ + if (data != NULL && data == (void*) XHASH (QCdbus_session_bus)) + { + XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); + unsetenv ("DBUS_SESSION_BUS_ADDRESS"); } - /* Return. */ - return; + if (flags & DBUS_WATCH_WRITABLE) + delete_write_fd (fd); + if (flags & DBUS_WATCH_READABLE) + delete_read_fd (fd); +} + +/* Toggle monitoring WATCH for possible I/O. */ + +static void +xd_toggle_watch (DBusWatch *watch, void *data) +{ + if (dbus_watch_get_enabled (watch)) + xd_add_watch (watch, data); + else + xd_remove_watch (watch, data); } DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0, @@ -880,7 +903,8 @@ DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0, if (!dbus_connection_set_watch_functions (connection, xd_add_watch, xd_remove_watch, - NULL, (void*) XHASH (bus), NULL)) + xd_toggle_watch, + (void*) XHASH (bus), NULL)) XD_SIGNAL1 (build_string ("Cannot add watch functions")); /* Add bus to list of registered buses. */ @@ -1288,9 +1312,6 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE result = Qnil; } - /* Flush connection to ensure the message is handled. */ - dbus_connection_flush (connection); - XD_DEBUG_MESSAGE ("Message sent"); /* Cleanup. */ @@ -1379,9 +1400,6 @@ usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */) if (!dbus_connection_send (connection, dmessage, NULL)) XD_SIGNAL1 (build_string ("Cannot send message")); - /* Flush connection to ensure the message is handled. */ - dbus_connection_flush (connection); - XD_DEBUG_MESSAGE ("Message sent"); /* Cleanup. */ @@ -1471,9 +1489,6 @@ usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */) if (!dbus_connection_send (connection, dmessage, NULL)) XD_SIGNAL1 (build_string ("Cannot send message")); - /* Flush connection to ensure the message is handled. */ - dbus_connection_flush (connection); - XD_DEBUG_MESSAGE ("Message sent"); /* Cleanup. */ @@ -1589,9 +1604,6 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */) if (!dbus_connection_send (connection, dmessage, NULL)) XD_SIGNAL1 (build_string ("Cannot send message")); - /* Flush connection to ensure the message is handled. */ - dbus_connection_flush (connection); - XD_DEBUG_MESSAGE ("Signal sent"); /* Cleanup. */ @@ -1645,32 +1657,27 @@ xd_pending_messages (void) return FALSE; } -/* Read queued incoming message of the D-Bus BUS. BUS is either a - Lisp symbol, :system or :session, or a string denoting the bus - address. */ -static Lisp_Object -xd_read_message (Lisp_Object bus) +/* Read one queued incoming message of the D-Bus BUS. + BUS is either a Lisp symbol, :system or :session, or a string denoting + the bus address. */ + +static void +xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) { Lisp_Object args, key, value; struct gcpro gcpro1; struct input_event event; - DBusConnection *connection; DBusMessage *dmessage; DBusMessageIter iter; unsigned int dtype; int mtype, serial; const char *uname, *path, *interface, *member; - /* Open a connection to the bus. */ - connection = xd_initialize (bus, TRUE); - - /* Non blocking read of the next available message. */ - dbus_connection_read_write (connection, 0); dmessage = dbus_connection_pop_message (connection); /* Return if there is no queued message. */ if (dmessage == NULL) - return Qnil; + return; /* Collect the parameters. */ args = Qnil; @@ -1801,7 +1808,26 @@ xd_read_message (Lisp_Object bus) cleanup: dbus_message_unref (dmessage); - RETURN_UNGCPRO (Qnil); + UNGCPRO; +} + +/* Read queued incoming messages of the D-Bus BUS. + BUS is either a Lisp symbol, :system or :session, or a string denoting + the bus address. */ + +static Lisp_Object +xd_read_message (Lisp_Object bus) +{ + /* Open a connection to the bus. */ + DBusConnection *connection = xd_initialize (bus, TRUE); + + /* Non blocking read of the next available message. */ + dbus_connection_read_write (connection, 0); + + while (dbus_connection_get_dispatch_status (connection) + != DBUS_DISPATCH_COMPLETE) + xd_read_message_1 (connection, bus); + return Qnil; } /* Read queued incoming messages from all buses. */ |