--- server/dispatcher.h | 140 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 24 deletions(-) diff --git a/server/dispatcher.h b/server/dispatcher.h index 862fc46b9..058032dbb 100644 --- a/server/dispatcher.h +++ b/server/dispatcher.h @@ -35,6 +35,18 @@ typedef struct Dispatcher Dispatcher; typedef struct DispatcherClass DispatcherClass; typedef struct DispatcherPrivate DispatcherPrivate; +/* A Dispatcher provides inter-thread communication by serializing messages. + * Currently the Dispatcher uses a unix socket (socketpair) for dispatching the + * messages. + * + * Message types are identified by a unique integer value must first by + * registered with the class (see dispatcher_register_handler()) before they + * can be sent. Sending threads can send a message using the + * dispatcher_send_message() function. The receiving thread can monitor the + * dispatcher's 'receive' file descriptor (see dispatcher_get_recv_fd()) for + * activity and should call dispatcher_handle_recv_read() to process incoming + * messages. + */ struct Dispatcher { GObject parent; @@ -49,88 +61,168 @@ struct DispatcherClass GType dispatcher_get_type(void) G_GNUC_CONST; +/* dispatcher_new + * + * Create a new Dispatcher object + * + * @max_message_type: indicates the number of unique message types that can + * be handled by this dispatcher. Each message type is + * identified by an integer value between 0 and + * max_message_type-1. + * @opaque: an arbitrary pointer that will be passed as the first + * argument to any registered handler functions + */ Dispatcher *dispatcher_new(size_t max_message_type, void *opaque); +/* The function signature for handlers of a specific message type */ typedef void (*dispatcher_handle_message)(void *opaque, void *payload); +/* The signature for a function that handles all messages (see + * dispatcher_register_universal_handler()) */ typedef void (*dispatcher_handle_any_message)(void *opaque, uint32_t message_type, void *payload); +/* The signature of a function that handles async done notifcations for all + * messages that are registered with DISPATCHER_FLAG_ASYNC flag. See + * dispatcher_register_async_done_callback() and dispatcher_register_handler() + * for more information. */ typedef void (*dispatcher_handle_async_done)(void *opaque, uint32_t message_type, void *payload); -/* - * dispatcher_send_message +/* dispatcher_send_message + * + * Sends a message to the receiving thread. The message type must have been + * registered first (see dispatcher_register_handler()). @payload must be a + * buffer of the same size as the size registered for @message_type + * + * If the sent message is a message type that was registered with a flag of + * DISPATCHER_FLAG_ACK, this function will block until it receives an ACK from + * the receiving thread. + * * @message_type: message type * @payload: payload */ void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type, void *payload); +/* A flag that specifies the behavior of the dispatcher when a given message + * type is received. This flag is specified when a message type is registered + * with the Dispatcher (see dispatcher_register_handler()). The possible values + * are as follows: + * + * DISPATCHER_FLAG_NONE: when a message is received, only the registered + * message handler is called + * + * DISPATCHER_FLAG_ACK: When a message is received, the message handler is + * called and the dispatcher will send an ACK response to the sender. This also + * changes the behavior of dispatcher_send_message() for a given message type + * since the sender will block until it receives the ACK. This is useful when + * the sender wants to ensure that the receiver has handled the message before + * proceeding. + * + * DISPATCHER_FLAG_ASYNC - When a message is received, the message handler is + * called and then the dispatcher will call the registered async_done handler. + * See dispatcher_register_async_done_callback() for more information + */ typedef enum { DISPATCHER_FLAG_NONE = 0, DISPATCHER_FLAG_ACK, DISPATCHER_FLAG_ASYNC } DispatcherFlag; -/* - * dispatcher_register_handler +/* dispatcher_register_handler + * + * This function registers a message type with the dispatcher, and registers + * @handler as the function that will handle incoming messages of this type. + * Based on the value of @flag, the dispatcher may also take additional actions + * after the message has been passed to the handler. You can only register a + * given message type once. For example, you cannot register two different + * handlers for the same message type with different @flag values. + * * @dispatcher: dispatcher * @messsage_type: message type * @handler: message handler * @size: message size. Each type has a fixed associated size. - * @flag: One of DISPATCHER_FLAG_NONE, DISPATCHER_FLAG_ACK, DISPATCHER_FLAG_ASYNC. - * DISPATCHER_FLAG_NONE - only send the message - * DISPATCHER_FLAG_ACK - send an ack after the message - * DISPATCHER_FLAG_ASYNC - call send an ack. This is per message type - you can't send the - * same message type with and without. Register two different - * messages if that is what you want. + * @flag: A flag that controls the behavior of this message type. See + * DispatcherFlag for more information. */ void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t message_type, dispatcher_handle_message handler, size_t size, DispatcherFlag flag); -/* - * dispatcher_register_async_done_callback +/* dispatcher_register_async_done_callback + * + * register an async_done callback for this dispatcher. For all message types + * that were registered with a DISPATCHER_FLAG_ASYNC flag, this function will + * be called after the normal message handler, and the message will be passed + * to this function. Note that this function will execute within the receiving + * thread. + * * @dispatcher: dispatcher * @handler: callback on the receiver side called *after* the - * message callback in case ack == DISPATCHER_ASYNC. + * message callback in case flag == DISPATCHER_FLAG_ASYNC. */ void dispatcher_register_async_done_callback( Dispatcher *dispatcher, dispatcher_handle_async_done handler); -/* - * Hack to allow red_record to see the message being sent so it can record - * it to file. +/* dispatcher_register_universal_handler + * + * Register a universal handler that will be called when *any* message is + * recieved by the dispatcher. When a message is received, this handler will be + * called first. If the received message type was registered via + * dispatcher_register_handler(), the message-specific handler will then be + * called. Only one universal handler can be registered. This feature can be + * used to record all messages to a file for replay and debugging. + * + * @dispatcher: dispatcher + * @handler: a handler function */ void dispatcher_register_universal_handler(Dispatcher *dispatcher, dispatcher_handle_any_message handler); -/* - * dispatcher_handle_recv_read - * @dispatcher: Dispatcher instance +/* dispatcher_handle_recv_read + * + * A convenience function that is intended to be called by the receiving thread + * to handle all incoming messages and execute any handlers for those messages. + * This function will handle all incoming messages until there is no more data + * to read, so multiple handlers may be executed from a single call to + * dispatcher_handle_recv_read(). + * + * @dispatcher: Dispatcher instance */ void dispatcher_handle_recv_read(Dispatcher *); -/* - * dispatcher_get_recv_fd - * @return: receive file descriptor of the dispatcher +/* dispatcher_get_recv_fd + * + * This function returns the fd that is used by the receiving thread to listen + * for incoming messages. You should not read or write directly to this fd, but + * should only use it to watch for read events. When there is a read event, you + * should use dispatcher_handle_recv_read() to handle the incoming messages. + * + * @return: receive file descriptor of the dispatcher */ int dispatcher_get_recv_fd(Dispatcher *); -/* - * dispatcher_set_opaque +/* dispatcher_set_opaque + * + * This 'opaque' pointer is user-defined data that will be passed as the first + * argument to all handler functions. + * * @dispatcher: Dispatcher instance * @opaque: opaque to use for callbacks */ void dispatcher_set_opaque(Dispatcher *dispatcher, void *opaque); +/* dispatcher_get_thread_id + * + * Returns the id of the thread that created this Dispatcher object + */ pthread_t dispatcher_get_thread_id(Dispatcher *self); #endif /* DISPATCHER_H_ */ -- 2.13.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel