mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-04-08 02:30:37 +02:00
This wraps around ei_connection.sync to allow a C API user to add synchronization points. Closes #69 Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/316>
124 lines
3.4 KiB
C
124 lines
3.4 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
/*
|
|
* Copyright © 2024 Red Hat, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "util-mem.h"
|
|
#include "util-macros.h"
|
|
#include "util-object.h"
|
|
#include "util-list.h"
|
|
#include "brei-shared.h"
|
|
|
|
#include "libei-private.h"
|
|
#include "libei-connection.h"
|
|
|
|
struct ei_ping {
|
|
struct object object;
|
|
uint64_t id;
|
|
void *user_data;
|
|
|
|
struct ei *context;
|
|
bool is_pending;
|
|
bool is_done;
|
|
};
|
|
|
|
static void
|
|
ei_ping_destroy(struct ei_ping *ping)
|
|
{
|
|
if (!ping->is_pending)
|
|
ei_unref(ping->context);
|
|
}
|
|
|
|
static
|
|
OBJECT_IMPLEMENT_CREATE(ei_ping);
|
|
|
|
_public_
|
|
OBJECT_IMPLEMENT_REF(ei_ping);
|
|
_public_
|
|
OBJECT_IMPLEMENT_UNREF_CLEANUP(ei_ping);
|
|
_public_
|
|
OBJECT_IMPLEMENT_GETTER(ei_ping, id, uint64_t);
|
|
_public_
|
|
OBJECT_IMPLEMENT_GETTER(ei_ping, user_data, void*);
|
|
_public_
|
|
OBJECT_IMPLEMENT_SETTER(ei_ping, user_data, void*);
|
|
static
|
|
OBJECT_IMPLEMENT_GETTER(ei_ping, context, struct ei*);
|
|
|
|
_public_ struct ei_ping *
|
|
ei_new_ping(struct ei *ei)
|
|
{
|
|
static uint64_t id = 0;
|
|
|
|
struct ei_ping *ping = ei_ping_create(NULL);
|
|
ping->id = ++id;
|
|
/* Ref our context while it's pending (i.e. only the caller has the ref).
|
|
* Once it's pending we no longer need the ref.
|
|
*/
|
|
ping->context = ei_ref(ei);
|
|
ping->is_pending = false;
|
|
ping->is_done = false;
|
|
|
|
return ping;
|
|
}
|
|
|
|
static void
|
|
on_pong(struct ei_connection_sync_callback *callback)
|
|
{
|
|
struct ei_ping *ping = ei_connection_sync_callback_get_user_data(callback);
|
|
ping->is_done = true;
|
|
|
|
struct ei *ei = ei_connection_sync_callback_get_context(callback);
|
|
ei_queue_pong_event(ei, ping);
|
|
/* ei_ping ref is removed in on_destroy */
|
|
}
|
|
|
|
static void
|
|
on_destroy(struct ei_connection_sync_callback *callback)
|
|
{
|
|
/* This is only called if we never received a pong */
|
|
_unref_(ei_ping) *ping = ei_connection_sync_callback_get_user_data(callback);
|
|
|
|
/* We never got a pong because we got disconnected. Queue a fake pong event */
|
|
if (!ping->is_done) {
|
|
struct ei *ei = ei_connection_sync_callback_get_context(callback);
|
|
ei_queue_pong_event(ei, ping);
|
|
}
|
|
}
|
|
|
|
_public_ void
|
|
ei_ping(struct ei_ping *ping)
|
|
{
|
|
struct ei *ei = ei_ping_get_context(ping);
|
|
|
|
ei_unref(ping->context);
|
|
ping->context = ei;
|
|
ping->is_pending = true;
|
|
|
|
_unref_(ei_connection_sync_callback) *cb = ei_connection_sync_callback_new(ei,
|
|
on_pong,
|
|
on_destroy,
|
|
ei_ping_ref(ping));
|
|
ei_connection_sync(ei->connection, cb);
|
|
}
|