Make context reference counted
authorJonas Ådahl <jadahl@gmail.com>
Tue, 24 Jun 2014 22:06:58 +0000 (00:06 +0200)
committerPeter Hutterer <peter.hutterer@who-t.net>
Wed, 25 Jun 2014 00:27:03 +0000 (10:27 +1000)
Instead of only allowing one owner keeping a libinput context alive,
make context reference counted, replacing libinput_destroy() with
libinput_unref() while adding another function libinput_ref().

Even though there might not be any current use cases, it doesn't mean we
should hard code this usage model in the API. The old behaviour can be
emulated by never calling libinput_ref() while replacing
libinput_destroy() with libinput_unref().

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
13 files changed:
src/libinput-private.h
src/libinput.c
src/libinput.h
src/udev-seat.c
test/keyboard.c
test/litest.c
test/log.c
test/misc.c
test/path.c
test/pointer.c
test/udev.c
tools/event-debug.c
tools/event-gui.c

index f0bda1f804e2d8bfb59910386595fc69fa9cc668..cfe6535bd258ec466353f2d6990d86a50e510057 100644 (file)
@@ -57,6 +57,7 @@ struct libinput {
        const struct libinput_interface *interface;
        const struct libinput_interface_backend *interface_backend;
        void *user_data;
+       int refcount;
 };
 
 typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat);
index d4d571175ec0c9e42040a31b57baf08a50a063dc..3aeca7dc6b25e6e0466e71f306e88df166990229 100644 (file)
@@ -502,6 +502,7 @@ libinput_init(struct libinput *libinput,
        libinput->interface = interface;
        libinput->interface_backend = interface_backend;
        libinput->user_data = user_data;
+       libinput->refcount = 1;
        list_init(&libinput->source_destroy_list);
        list_init(&libinput->seat_list);
 
@@ -530,15 +531,27 @@ libinput_drop_destroyed_sources(struct libinput *libinput)
        list_init(&libinput->source_destroy_list);
 }
 
-LIBINPUT_EXPORT void
-libinput_destroy(struct libinput *libinput)
+LIBINPUT_EXPORT struct libinput *
+libinput_ref(struct libinput *libinput)
+{
+       libinput->refcount++;
+       return libinput;
+}
+
+LIBINPUT_EXPORT struct libinput *
+libinput_unref(struct libinput *libinput)
 {
        struct libinput_event *event;
        struct libinput_device *device, *next_device;
        struct libinput_seat *seat, *next_seat;
 
        if (libinput == NULL)
-               return;
+               return NULL;
+
+       assert(libinput->refcount > 0);
+       libinput->refcount--;
+       if (libinput->refcount > 0)
+               return libinput;
 
        libinput_suspend(libinput);
 
@@ -562,6 +575,8 @@ libinput_destroy(struct libinput *libinput)
        libinput_drop_destroyed_sources(libinput);
        close(libinput->epoll_fd);
        free(libinput);
+
+       return NULL;
 }
 
 LIBINPUT_EXPORT void
index 3503b76f7ff80fad8c1195ad43f21eb098d3a949..72375f7b054f3055b1316c009073cf8dad990a14 100644 (file)
@@ -793,6 +793,9 @@ struct libinput_interface {
  * device are ignored. Such devices and those that failed to open
  * ignored until the next call to libinput_resume().
  *
+ * The reference count of the context is initialized to 1. See @ref
+ * libinput_unref.
+ *
  * @param interface The callback interface
  * @param user_data Caller-specific data passed to the various callback
  * interfaces.
@@ -818,6 +821,9 @@ libinput_udev_create_for_seat(const struct libinput_interface *interface,
  * The context is fully initialized but will not generate events until at
  * least one device has been added.
  *
+ * The reference count of the context is initialized to 1. See @ref
+ * libinput_unref.
+ *
  * @param interface The callback interface
  * @param user_data Caller-specific data passed to the various callback
  * interfaces.
@@ -967,13 +973,27 @@ libinput_suspend(struct libinput *libinput);
 /**
  * @ingroup base
  *
- * Destroy the libinput context. After this, object references associated with
- * the destroyed context are invalid and may not be interacted with.
+ * Add a reference to the context. A context is destroyed whenever the
+ * reference count reaches 0. See @ref libinput_unref.
+ *
+ * @param libinput A previously initialized valid libinput context
+ * @return The passed libinput context
+ */
+struct libinput *
+libinput_ref(struct libinput *libinput);
+
+/**
+ * @ingroup base
+ *
+ * Dereference the libinput context. After this, the context may have been
+ * destroyed, if the last reference was dereferenced. If so, the context is
+ * invalid and may not be interacted with.
  *
  * @param libinput A previously initialized libinput context
+ * @return NULL if context was destroyed otherwise the passed context
  */
-void
-libinput_destroy(struct libinput *libinput);
+struct libinput *
+libinput_unref(struct libinput *libinput);
 
 /**
  * @ingroup base
index 38a13b72346fce9f30be944fa214f2379da5d43e..5b61dee61efdd4bb1684d0d914f73cec9d23f927 100644 (file)
@@ -358,7 +358,7 @@ libinput_udev_create_for_seat(const struct libinput_interface *interface,
 
        if (udev_input_enable(&input->base) < 0) {
                udev_unref(udev);
-               libinput_destroy(&input->base);
+               libinput_unref(&input->base);
                free(input);
                return NULL;
        }
index a518b66ce98d11fc7ff8f262ced0bbaef460fbb0..83153bb9889558cc6613e6aa9944b8a72d5a4f9a 100644 (file)
@@ -108,7 +108,7 @@ START_TEST(keyboard_seat_key_count)
 
        for (i = 0; i < num_devices; ++i)
                litest_delete_device(devices[i]);
-       libinput_destroy(libinput);
+       libinput_unref(libinput);
 }
 END_TEST
 
index 0a9cc72d646686a5460256ebea03ad23486109c7..55ba678b27083d058ab672bebf74e629ac015251 100644 (file)
@@ -573,7 +573,7 @@ litest_delete_device(struct litest_device *d)
 
        libinput_device_unref(d->libinput_device);
        if (d->owns_context)
-               libinput_destroy(d->libinput);
+               libinput_unref(d->libinput);
        libevdev_free(d->evdev);
        libevdev_uinput_destroy(d->uinput);
        memset(d,0, sizeof(*d));
index a28182072ce64e1d6f8656202d950215750995b5..fe67d68eb57b9a397e3700230a5fab1c81789edf 100644 (file)
@@ -86,7 +86,7 @@ START_TEST(log_handler_invoked)
        ck_assert_int_gt(log_handler_called, 0);
        log_handler_called = 0;
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libinput_log_set_priority(pri);
 }
 END_TEST
@@ -106,7 +106,7 @@ START_TEST(log_userdata_NULL)
        ck_assert_int_gt(log_handler_called, 0);
        log_handler_called = 0;
 
-       libinput_destroy(li);
+       libinput_unref(li);
 
        libinput_log_set_priority(pri);
 }
@@ -127,7 +127,7 @@ START_TEST(log_userdata)
        ck_assert_int_gt(log_handler_called, 0);
        log_handler_called = 0;
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libinput_log_set_priority(pri);
 }
 END_TEST
@@ -148,7 +148,7 @@ START_TEST(log_handler_NULL)
        log_handler_called = 0;
        libinput_log_set_handler(simple_log_handler, NULL);
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libinput_log_set_priority(pri);
 }
 END_TEST
@@ -173,7 +173,7 @@ START_TEST(log_priority)
 
        log_handler_called = 0;
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libinput_log_set_priority(pri);
 }
 END_TEST
index 133bdb601da80e80ac04d05846404f318982290a..ad2e1f66e7d693dee769bd08fc377406d9e2608e 100644 (file)
@@ -133,7 +133,7 @@ START_TEST(event_conversion_device_notify)
                libinput_event_destroy(event);
        }
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libevdev_uinput_destroy(uinput);
 
        ck_assert_int_gt(device_added, 0);
@@ -194,7 +194,7 @@ START_TEST(event_conversion_pointer)
                libinput_event_destroy(event);
        }
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libevdev_uinput_destroy(uinput);
 
        ck_assert_int_gt(motion, 0);
@@ -254,7 +254,7 @@ START_TEST(event_conversion_pointer_abs)
                libinput_event_destroy(event);
        }
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libevdev_uinput_destroy(uinput);
 
        ck_assert_int_gt(motion, 0);
@@ -304,7 +304,7 @@ START_TEST(event_conversion_key)
                libinput_event_destroy(event);
        }
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libevdev_uinput_destroy(uinput);
 
        ck_assert_int_gt(key, 0);
@@ -364,7 +364,7 @@ START_TEST(event_conversion_touch)
                libinput_event_destroy(event);
        }
 
-       libinput_destroy(li);
+       libinput_unref(li);
        libevdev_uinput_destroy(uinput);
 
        ck_assert_int_gt(touch, 0);
index 24f60e01e116d41181530e6b4e6e111616e17c16..99b474eb629f020bf284eee626365048825b26bc 100644 (file)
@@ -65,7 +65,7 @@ START_TEST(path_create_NULL)
        ck_assert(li == NULL);
        li = libinput_path_create_context(&simple_interface, NULL);
        ck_assert(li != NULL);
-       libinput_destroy(li);
+       libinput_unref(li);
 
        ck_assert_int_eq(open_func_count, 0);
        ck_assert_int_eq(close_func_count, 0);
@@ -92,7 +92,7 @@ START_TEST(path_create_invalid)
        ck_assert_int_eq(open_func_count, 0);
        ck_assert_int_eq(close_func_count, 0);
 
-       libinput_destroy(li);
+       libinput_unref(li);
        ck_assert_int_eq(close_func_count, 0);
 
        open_func_count = 0;
@@ -126,7 +126,7 @@ START_TEST(path_create_destroy)
        ck_assert_int_eq(open_func_count, 1);
 
        libevdev_uinput_destroy(uinput);
-       libinput_destroy(li);
+       libinput_unref(li);
        ck_assert_int_eq(close_func_count, 1);
 
        open_func_count = 0;
@@ -372,7 +372,7 @@ START_TEST(path_suspend)
        libinput_resume(li);
 
        libevdev_uinput_destroy(uinput);
-       libinput_destroy(li);
+       libinput_unref(li);
 
        open_func_count = 0;
        close_func_count = 0;
@@ -406,7 +406,7 @@ START_TEST(path_double_suspend)
        libinput_resume(li);
 
        libevdev_uinput_destroy(uinput);
-       libinput_destroy(li);
+       libinput_unref(li);
 
        open_func_count = 0;
        close_func_count = 0;
@@ -440,7 +440,7 @@ START_TEST(path_double_resume)
        libinput_resume(li);
 
        libevdev_uinput_destroy(uinput);
-       libinput_destroy(li);
+       libinput_unref(li);
 
        open_func_count = 0;
        close_func_count = 0;
@@ -523,7 +523,7 @@ START_TEST(path_add_device_suspend_resume)
 
        libevdev_uinput_destroy(uinput1);
        libevdev_uinput_destroy(uinput2);
-       libinput_destroy(li);
+       libinput_unref(li);
 
        open_func_count = 0;
        close_func_count = 0;
@@ -614,7 +614,7 @@ START_TEST(path_add_device_suspend_resume_fail)
        ck_assert_int_eq(nevents, 2);
 
        libevdev_uinput_destroy(uinput2);
-       libinput_destroy(li);
+       libinput_unref(li);
 
        open_func_count = 0;
        close_func_count = 0;
@@ -704,7 +704,7 @@ START_TEST(path_add_device_suspend_resume_remove_device)
        ck_assert_int_eq(nevents, 1);
 
        libevdev_uinput_destroy(uinput1);
-       libinput_destroy(li);
+       libinput_unref(li);
 
        open_func_count = 0;
        close_func_count = 0;
@@ -790,7 +790,7 @@ START_TEST(path_seat_recycle)
 
        ck_assert(found == 1);
 
-       libinput_destroy(li);
+       libinput_unref(li);
 
        libevdev_uinput_destroy(uinput);
 }
index 346e59b73ac14dd807b7251014a28f6b7616c0a5..7d5668f86fe6ad459af6980e329054ead615445c 100644 (file)
@@ -292,7 +292,7 @@ START_TEST(pointer_seat_button_count)
 
        for (i = 0; i < num_devices; ++i)
                litest_delete_device(devices[i]);
-       libinput_destroy(libinput);
+       libinput_unref(libinput);
 }
 END_TEST
 
index 6af2cb08dcdf94907d054f03c359e6338db619f3..09c2a94f92b8140c5884cc2214fc5c1ff4c12f4e 100644 (file)
@@ -97,7 +97,7 @@ START_TEST(udev_create_seat0)
        ck_assert(event != NULL);
 
        libinput_event_destroy(event);
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
@@ -124,7 +124,7 @@ START_TEST(udev_create_empty_seat)
        ck_assert(event == NULL);
 
        libinput_event_destroy(event);
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
@@ -169,7 +169,7 @@ START_TEST(udev_added_seat_default)
 
        ck_assert(default_seat_found);
 
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
@@ -200,7 +200,7 @@ START_TEST(udev_double_suspend)
        libinput_resume(li);
 
        libinput_event_destroy(event);
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
@@ -231,7 +231,7 @@ START_TEST(udev_double_resume)
        libinput_resume(li);
 
        libinput_event_destroy(event);
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
@@ -289,7 +289,7 @@ START_TEST(udev_suspend_resume)
        process_events_count_devices(li, &num_devices);
        ck_assert_int_gt(num_devices, 0);
 
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
@@ -322,7 +322,7 @@ START_TEST(udev_device_sysname)
                libinput_event_destroy(ev);
        }
 
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
@@ -396,7 +396,7 @@ START_TEST(udev_seat_recycle)
 
        ck_assert(found == 1);
 
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 }
 END_TEST
index 34acfce28b1b01ca7a4f5f88b6348361f904f04a..95e76286a94c7ff0dd7c61a0347584e509945936 100644 (file)
@@ -163,7 +163,7 @@ open_device(struct libinput **li, const char *path)
        device = libinput_path_add_device(*li, path);
        if (!device) {
                fprintf(stderr, "Failed to initialized device %s\n", path);
-               libinput_destroy(*li);
+               libinput_unref(*li);
                return 1;
        }
 
@@ -478,7 +478,7 @@ main(int argc, char **argv)
 
        mainloop(li);
 
-       libinput_destroy(li);
+       libinput_unref(li);
        if (udev)
                udev_unref(udev);
 
index 9554093658d6773927d83ab4531aa6d9120ee5d3..9c39c2132bdf743e4b67340be0d542e3388f1cfa 100644 (file)
@@ -467,7 +467,7 @@ main(int argc, char *argv[])
 
        gtk_main();
 
-       libinput_destroy(li);
+       libinput_unref(li);
        udev_unref(udev);
 
        return 0;