From: Jonas Ådahl Date: Sat, 7 Dec 2013 15:41:43 +0000 (+0100) Subject: Reference count event target struct when applicable X-Git-Tag: 0.1.0~146 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=758e5536451e4ea1073ea0de0a3ed92581c510d3;p=platform%2Fupstream%2Flibinput.git Reference count event target struct when applicable If the target of an event is a reference counted object, such as libinput_seat and libinput_device, make events own its own reference to the object, releasing it when destroyed. In order to do this, a new API requirement and function are introduced; libinput_event_destroy(). The user is required to use libinput_event_destroy() instead of free() after having retrieved an event using libinput_get_event(). This fixes a race that would be triggered if a device or seat would be added and removed before the user calling libinput_get_event(). Signed-off-by: Jonas Ådahl --- diff --git a/src/libinput.c b/src/libinput.c index 239b85c..34c794e 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -35,6 +35,12 @@ #include "evdev.h" #include "udev-seat.h" +enum libinput_event_class { + LIBINPUT_EVENT_CLASS_BASE, + LIBINPUT_EVENT_CLASS_SEAT, + LIBINPUT_EVENT_CLASS_DEVICE, +}; + struct libinput_source { libinput_source_dispatch_t dispatch; void *user_data; @@ -116,6 +122,48 @@ libinput_destroy(struct libinput *libinput) free(libinput); } +static enum libinput_event_class +libinput_event_get_class(struct libinput_event *event) +{ + switch (event->type) { + case LIBINPUT_EVENT_ADDED_SEAT: + case LIBINPUT_EVENT_REMOVED_SEAT: + case LIBINPUT_EVENT_ADDED_DEVICE: + case LIBINPUT_EVENT_REMOVED_DEVICE: + return LIBINPUT_EVENT_CLASS_BASE; + + case LIBINPUT_EVENT_DEVICE_REGISTER_CAPABILITY: + case LIBINPUT_EVENT_DEVICE_UNREGISTER_CAPABILITY: + case LIBINPUT_EVENT_KEYBOARD_KEY: + case LIBINPUT_EVENT_POINTER_MOTION: + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + case LIBINPUT_EVENT_POINTER_BUTTON: + case LIBINPUT_EVENT_POINTER_AXIS: + case LIBINPUT_EVENT_TOUCH_TOUCH: + return LIBINPUT_EVENT_CLASS_DEVICE; + } + + /* We should never end up here. */ + abort(); +} + +LIBINPUT_EXPORT void +libinput_event_destroy(struct libinput_event *event) +{ + switch (libinput_event_get_class(event)) { + case LIBINPUT_EVENT_CLASS_BASE: + break; + case LIBINPUT_EVENT_CLASS_SEAT: + libinput_seat_unref(event->target.seat); + break; + case LIBINPUT_EVENT_CLASS_DEVICE: + libinput_device_unref(event->target.device); + break; + } + + free(event); +} + int open_restricted(struct libinput *libinput, const char *path, int flags) @@ -546,6 +594,17 @@ libinput_post_event(struct libinput *libinput, libinput->events_len = events_len; } + switch (libinput_event_get_class(event)) { + case LIBINPUT_EVENT_CLASS_BASE: + break; + case LIBINPUT_EVENT_CLASS_SEAT: + libinput_seat_ref(event->target.seat); + break; + case LIBINPUT_EVENT_CLASS_DEVICE: + libinput_device_ref(event->target.device); + break; + } + libinput->events_count = events_count; events[libinput->events_in] = event; libinput->events_in = (libinput->events_in + 1) % libinput->events_len; diff --git a/src/libinput.h b/src/libinput.h index 5ea260c..4994830 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -296,7 +296,8 @@ libinput_dispatch(struct libinput *libinput); * * Retrieve the next event from libinput's internal event queue. * - * After handling the retrieved event, the caller must free it using free(). + * After handling the retrieved event, the caller must destroy it using + * libinput_event_destroy(). * * @param libinput A previously initialized libinput context * @return The next available event, or NULL if no event is available. @@ -351,6 +352,20 @@ void libinput_destroy(struct libinput *libinput); /** + * @defgroup event Acessing and destruction of events + */ + +/** + * @ingroup event + * + * Destroy the event. + * + * @param event An event retrieved by libinput_get_event(). + */ +void +libinput_event_destroy(struct libinput_event *event); + +/** * @defgroup seat Initialization and manipulation of seats */