Compare commits
	
		
			8 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					ccf3e1237c | ||
| 
						 | 
					e02f00fd41 | ||
| 
						 | 
					e45e640f3c | ||
| 
						 | 
					75e8015c43 | ||
| 
						 | 
					2c52fcc156 | ||
| 
						 | 
					dc5b51a41f | ||
| 
						 | 
					d12cee4690 | ||
| 
						 | 
					a74c4ac148 | 
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
VERSION_MAJOR = 1
 | 
			
		||||
VERSION_MINOR = 0
 | 
			
		||||
VERSION_RELEASE = 39
 | 
			
		||||
VERSION_RELEASE = 41
 | 
			
		||||
 | 
			
		||||
# Version for pkg-config
 | 
			
		||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
			
		||||
@@ -79,6 +79,7 @@ SRC = \
 | 
			
		||||
  gbinder_cleanup.c \
 | 
			
		||||
  gbinder_client.c \
 | 
			
		||||
  gbinder_driver.c \
 | 
			
		||||
  gbinder_eventloop.c \
 | 
			
		||||
  gbinder_io_32.c \
 | 
			
		||||
  gbinder_io_64.c \
 | 
			
		||||
  gbinder_ipc.c \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,15 @@
 | 
			
		||||
libgbinder (1.0.41) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Stop using GUtilIdlePool
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Tue, 14 Apr 2020 12:36:54 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.40) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Support integration with non-glib event loops
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 09 Apr 2020 17:22:12 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.39) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Adapted to side-by-side linking
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										194
									
								
								include/gbinder_eventloop.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								include/gbinder_eventloop.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GBINDER_EVENTLOOP_H
 | 
			
		||||
#define GBINDER_EVENTLOOP_H
 | 
			
		||||
 | 
			
		||||
#include "gbinder_types.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/* Since 1.0.40 */
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_eventloop_integration GBinderEventLoopIntegration;
 | 
			
		||||
typedef void (*GBinderEventLoopCallbackFunc)(gpointer data);
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_eventloop_timeout {
 | 
			
		||||
    const GBinderEventLoopIntegration* eventloop;
 | 
			
		||||
} GBinderEventLoopTimeout;
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_eventloop_callback {
 | 
			
		||||
    const GBinderEventLoopIntegration* eventloop;
 | 
			
		||||
} GBinderEventLoopCallback;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Main event loop integration. There is only one main event loop in the
 | 
			
		||||
 * process (by definition).
 | 
			
		||||
 *
 | 
			
		||||
 * By default, GLib event loop is being used for callbacks and timeouts.
 | 
			
		||||
 *
 | 
			
		||||
 * It may be necessary to replace it with e.g. Qt event loop. Quite often
 | 
			
		||||
 * Qt event loop is implemented by QEventDispatcherGlib which is sitting
 | 
			
		||||
 * on top of GLib event and therefore works with the default implementation.
 | 
			
		||||
 * But it won't work with e.g. QEventDispatcherUNIX.
 | 
			
		||||
 *
 | 
			
		||||
 * For Qt programs that use QEventDispatcherUNIX, it needs to be replaced
 | 
			
		||||
 * with the one provided by libqbinder.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct gbinder_eventloop_integration {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * timeout_add
 | 
			
		||||
     *
 | 
			
		||||
     * Sets a function to be called at regular intervals (in milliseconds).
 | 
			
		||||
     * If the function returns G_SOURCE_REMOVE, timeout is automatically
 | 
			
		||||
     * destroyed (you must not call timeout_remove in this case). If the
 | 
			
		||||
     * function returns G_SOURCE_CONTINUE, it will be called again after
 | 
			
		||||
     * the same interval.
 | 
			
		||||
     */
 | 
			
		||||
    GBinderEventLoopTimeout* (*timeout_add)(guint millis, GSourceFunc func,
 | 
			
		||||
        gpointer data);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * timeout_remove
 | 
			
		||||
     *
 | 
			
		||||
     * Removes a pending timeout and destroys it. The caller makes sure that
 | 
			
		||||
     * argument is not NULL. Note that timeout is automatically destroyed if
 | 
			
		||||
     * the callback function returns G_SOURCE_REMOVE.
 | 
			
		||||
     */
 | 
			
		||||
    void (*timeout_remove)(GBinderEventLoopTimeout* timeout);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * callback_new
 | 
			
		||||
     *
 | 
			
		||||
     * Creates a callback object. It returns you a reference, you must
 | 
			
		||||
     * eventually pass the returned object to callback_unref to drop
 | 
			
		||||
     * this reference.
 | 
			
		||||
     *
 | 
			
		||||
     * Note that it doesn't automatically schedule the callback. You
 | 
			
		||||
     * must explicitly call callback_schedule to actually schedule it.
 | 
			
		||||
     * The finalize function is invoked regardless of whether callback
 | 
			
		||||
     * was cancelled or not.
 | 
			
		||||
     */
 | 
			
		||||
    GBinderEventLoopCallback* (*callback_new)(GBinderEventLoopCallbackFunc fun,
 | 
			
		||||
        gpointer data, GDestroyNotify finalize);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * callback_ref
 | 
			
		||||
     *
 | 
			
		||||
     * Increments the reference count. That prevents the object from being
 | 
			
		||||
     * deleted before you drop this reference. The caller makes sure that
 | 
			
		||||
     * argument is not NULL.
 | 
			
		||||
     */
 | 
			
		||||
    void (*callback_ref)(GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * callback_unref
 | 
			
		||||
     *
 | 
			
		||||
     * Decrements the reference count (drops the reference). When reference
 | 
			
		||||
     * count reaches zero, the object gets deleted. The caller makes sure
 | 
			
		||||
     * that argument is not NULL.
 | 
			
		||||
     *
 | 
			
		||||
     * Note that calling callback_schedule temporarily adds an internal
 | 
			
		||||
     * reference until the callback is invoked or callback_cancel is called,
 | 
			
		||||
     * whichever happens first.
 | 
			
		||||
     */
 | 
			
		||||
    void (*callback_unref)(GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * callback_schedule
 | 
			
		||||
     *
 | 
			
		||||
     * Schedules the callback to be invoked in the main loop at some point
 | 
			
		||||
     * in the future (but as soon as possible). The caller makes sure that
 | 
			
		||||
     * argument is not NULL.
 | 
			
		||||
     *
 | 
			
		||||
     * This adds an internal reference to the GBinderEventLoopCallback object
 | 
			
		||||
     * until the callback is invoked or callback_cancel is called, whichever
 | 
			
		||||
     * happens first.
 | 
			
		||||
     */
 | 
			
		||||
    void (*callback_schedule)(GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * callback_cancel
 | 
			
		||||
     *
 | 
			
		||||
     * Makes sure that callback won't be invoked (if it hasn't been
 | 
			
		||||
     * invoked yet) and drops the internal reference. Does nothing
 | 
			
		||||
     * if the callback has already been invoked. The caller makes sure that
 | 
			
		||||
     * argument is not NULL.
 | 
			
		||||
     */
 | 
			
		||||
    void (*callback_cancel)(GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * cleanup
 | 
			
		||||
     *
 | 
			
		||||
     * This function is called when event loop integration is being replaced
 | 
			
		||||
     * with a different one, or libgbinder is being unloaded.
 | 
			
		||||
     */
 | 
			
		||||
    void (*cleanup)(void);
 | 
			
		||||
 | 
			
		||||
    /* Padding for future expansion */
 | 
			
		||||
    void (*_reserved1)(void);
 | 
			
		||||
    void (*_reserved2)(void);
 | 
			
		||||
    void (*_reserved3)(void);
 | 
			
		||||
    void (*_reserved4)(void);
 | 
			
		||||
    void (*_reserved5)(void);
 | 
			
		||||
    void (*_reserved6)(void);
 | 
			
		||||
    void (*_reserved7)(void);
 | 
			
		||||
    void (*_reserved8)(void);
 | 
			
		||||
    void (*_reserved9)(void);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * api_level will remain zero (and ignored) until we run out of
 | 
			
		||||
     * the above placeholders. Hopefully, forever.
 | 
			
		||||
     */
 | 
			
		||||
    int api_level;
 | 
			
		||||
} GBinderEventLoopIntegration;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * gbinder_eventloop_set should be called before libgbinder creates any of
 | 
			
		||||
 * its internal threads. And it must be done from the main thread.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_set(
 | 
			
		||||
    const GBinderEventLoopIntegration* loop);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_EVENTLOOP_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -1,14 +1,16 @@
 | 
			
		||||
Name: libgbinder
 | 
			
		||||
Version: 1.0.39
 | 
			
		||||
Version: 1.0.41
 | 
			
		||||
Release: 0
 | 
			
		||||
Summary: Binder client library
 | 
			
		||||
Group: Development/Libraries
 | 
			
		||||
License: BSD
 | 
			
		||||
URL: https://github.com/mer-hybris/libgbinder
 | 
			
		||||
Source: %{name}-%{version}.tar.bz2
 | 
			
		||||
Requires: libglibutil >= 1.0.35
 | 
			
		||||
 | 
			
		||||
%define libglibutil_version 1.0.35
 | 
			
		||||
 | 
			
		||||
BuildRequires: pkgconfig(glib-2.0)
 | 
			
		||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.35
 | 
			
		||||
BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}
 | 
			
		||||
Requires: libglibutil >= %{libglibutil_version}
 | 
			
		||||
Requires(post): /sbin/ldconfig
 | 
			
		||||
Requires(postun): /sbin/ldconfig
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -14,8 +14,8 @@
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
#include "gbinder_servicemanager_p.h"
 | 
			
		||||
#include "gbinder_rpc_protocol.h"
 | 
			
		||||
#include "gbinder_servicepoll.h"
 | 
			
		||||
#include "gbinder_eventloop_p.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gbinder_client.h>
 | 
			
		||||
@@ -48,7 +49,7 @@ typedef struct gbinder_defaultservicemanager_watch {
 | 
			
		||||
    GBinderServicePoll* poll;
 | 
			
		||||
    char* name;
 | 
			
		||||
    gulong handler_id;
 | 
			
		||||
    guint notify_id;
 | 
			
		||||
    GBinderEventLoopTimeout* notify;
 | 
			
		||||
} GBinderDefaultServiceManagerWatch;
 | 
			
		||||
 | 
			
		||||
typedef GBinderServiceManagerClass GBinderDefaultServiceManagerClass;
 | 
			
		||||
@@ -99,9 +100,9 @@ gbinder_defaultservicemanager_watch_proc(
 | 
			
		||||
        GBinderServiceManager* manager =
 | 
			
		||||
            gbinder_servicepoll_manager(watch->poll);
 | 
			
		||||
 | 
			
		||||
        if (watch->notify_id) {
 | 
			
		||||
            g_source_remove(watch->notify_id);
 | 
			
		||||
            watch->notify_id = 0;
 | 
			
		||||
        if (watch->notify) {
 | 
			
		||||
            gbinder_timeout_remove(watch->notify);
 | 
			
		||||
            watch->notify = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        gbinder_servicemanager_service_registered(manager, name_added);
 | 
			
		||||
    }
 | 
			
		||||
@@ -116,8 +117,8 @@ gbinder_defaultservicemanager_watch_notify(
 | 
			
		||||
    GBinderServiceManager* manager = gbinder_servicepoll_manager(watch->poll);
 | 
			
		||||
    char* name = g_strdup(watch->name);
 | 
			
		||||
 | 
			
		||||
    GASSERT(watch->notify_id);
 | 
			
		||||
    watch->notify_id = 0;
 | 
			
		||||
    GASSERT(watch->notify);
 | 
			
		||||
    watch->notify = NULL;
 | 
			
		||||
    gbinder_servicemanager_service_registered(manager, name);
 | 
			
		||||
    g_free(name);
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
@@ -130,9 +131,7 @@ gbinder_defaultservicemanager_watch_free(
 | 
			
		||||
{
 | 
			
		||||
    GBinderDefaultServiceManagerWatch* watch = user_data;
 | 
			
		||||
 | 
			
		||||
    if (watch->notify_id) {
 | 
			
		||||
        g_source_remove(watch->notify_id);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_timeout_remove(watch->notify);
 | 
			
		||||
    gbinder_servicepoll_remove_handler(watch->poll, watch->handler_id);
 | 
			
		||||
    gbinder_servicepoll_unref(watch->poll);
 | 
			
		||||
    g_free(watch->name);
 | 
			
		||||
@@ -258,8 +257,8 @@ gbinder_defaultservicemanager_watch(
 | 
			
		||||
 | 
			
		||||
    g_hash_table_replace(self->watch_table, watch->name, watch);
 | 
			
		||||
    if (gbinder_servicepoll_is_known_name(watch->poll, name)) {
 | 
			
		||||
        watch->notify_id =
 | 
			
		||||
            g_idle_add(gbinder_defaultservicemanager_watch_notify, watch);
 | 
			
		||||
        watch->notify = gbinder_idle_add
 | 
			
		||||
            (gbinder_defaultservicemanager_watch_notify, watch);
 | 
			
		||||
    }
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										347
									
								
								src/gbinder_eventloop.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								src/gbinder_eventloop.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,347 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_eventloop_p.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
 | 
			
		||||
#define GBINDER_DEFAULT_EVENTLOOP (&gbinder_eventloop_glib)
 | 
			
		||||
 | 
			
		||||
static const GBinderEventLoopIntegration gbinder_eventloop_glib;
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * GLib event loop integration
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_eventloop_glib_timeout {
 | 
			
		||||
    GBinderEventLoopTimeout timeout;
 | 
			
		||||
    guint id;
 | 
			
		||||
    GSourceFunc func;
 | 
			
		||||
    gpointer data;
 | 
			
		||||
} GBinderEventLoopTimeoutGLib;
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_eventloop_glib_callback {
 | 
			
		||||
    GSource source;
 | 
			
		||||
    GBinderEventLoopCallback callback;
 | 
			
		||||
} GBinderEventLoopCallbackGLib;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
inline
 | 
			
		||||
GBinderEventLoopTimeoutGLib*
 | 
			
		||||
gbinder_eventloop_glib_timeout_cast(
 | 
			
		||||
    GBinderEventLoopTimeout* timeout)
 | 
			
		||||
{
 | 
			
		||||
    return G_CAST(timeout,GBinderEventLoopTimeoutGLib,timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
inline
 | 
			
		||||
GSource*
 | 
			
		||||
gbinder_eventloop_glib_callback_source(
 | 
			
		||||
    GBinderEventLoopCallback* callback)
 | 
			
		||||
{
 | 
			
		||||
    return &(G_CAST(callback,GBinderEventLoopCallbackGLib,callback)->source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_eventloop_glib_timeout_callback(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderEventLoopTimeoutGLib* timeout = data;
 | 
			
		||||
 | 
			
		||||
    return timeout->func(timeout->data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_glib_timeout_finalize(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    g_slice_free1(sizeof(GBinderEventLoopTimeoutGLib), data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderEventLoopTimeout*
 | 
			
		||||
gbinder_eventloop_glib_timeout_add(
 | 
			
		||||
    guint interval,
 | 
			
		||||
    GSourceFunc func,
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderEventLoopTimeoutGLib* impl =
 | 
			
		||||
        g_slice_new(GBinderEventLoopTimeoutGLib);
 | 
			
		||||
 | 
			
		||||
    impl->timeout.eventloop = &gbinder_eventloop_glib;
 | 
			
		||||
    impl->func = func;
 | 
			
		||||
    impl->data = data;
 | 
			
		||||
    impl->id = g_timeout_add_full(G_PRIORITY_DEFAULT, interval,
 | 
			
		||||
        gbinder_eventloop_glib_timeout_callback, impl,
 | 
			
		||||
        gbinder_eventloop_glib_timeout_finalize);
 | 
			
		||||
    return &impl->timeout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_glib_timeout_remove(
 | 
			
		||||
    GBinderEventLoopTimeout* timeout)
 | 
			
		||||
{
 | 
			
		||||
    g_source_remove(gbinder_eventloop_glib_timeout_cast(timeout)->id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_eventloop_glib_callback_prepare(
 | 
			
		||||
    GSource* source,
 | 
			
		||||
    gint* timeout)
 | 
			
		||||
{
 | 
			
		||||
    *timeout = 0;
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_eventloop_glib_callback_check(
 | 
			
		||||
    GSource* source)
 | 
			
		||||
{
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_eventloop_glib_callback_dispatch(
 | 
			
		||||
    GSource* source,
 | 
			
		||||
    GSourceFunc callback,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    ((GBinderEventLoopCallbackFunc)callback)(user_data);
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
gbinder_eventloop_glib_callback_new(
 | 
			
		||||
    GBinderEventLoopCallbackFunc func,
 | 
			
		||||
    gpointer data,
 | 
			
		||||
    GDestroyNotify finalize)
 | 
			
		||||
{
 | 
			
		||||
    static GSourceFuncs callback_funcs = {
 | 
			
		||||
        gbinder_eventloop_glib_callback_prepare,
 | 
			
		||||
        gbinder_eventloop_glib_callback_check,
 | 
			
		||||
        gbinder_eventloop_glib_callback_dispatch
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    GBinderEventLoopCallbackGLib* impl = (GBinderEventLoopCallbackGLib*)
 | 
			
		||||
        g_source_new(&callback_funcs, sizeof(GBinderEventLoopCallbackGLib));
 | 
			
		||||
 | 
			
		||||
    impl->callback.eventloop = &gbinder_eventloop_glib;
 | 
			
		||||
    g_source_set_callback(&impl->source, (GSourceFunc) func, data, finalize);
 | 
			
		||||
    return &impl->callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_glib_callback_ref(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    g_source_ref(gbinder_eventloop_glib_callback_source(cb));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_glib_callback_unref(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    g_source_unref(gbinder_eventloop_glib_callback_source(cb));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_glib_callback_schedule(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    static GMainContext* context = NULL;
 | 
			
		||||
 | 
			
		||||
    if (!context) context = g_main_context_default();
 | 
			
		||||
    g_source_attach(gbinder_eventloop_glib_callback_source(cb), context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_glib_callback_cancel(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    g_source_destroy(gbinder_eventloop_glib_callback_source(cb));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_glib_cleanup(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const GBinderEventLoopIntegration gbinder_eventloop_glib = {
 | 
			
		||||
    gbinder_eventloop_glib_timeout_add,
 | 
			
		||||
    gbinder_eventloop_glib_timeout_remove,
 | 
			
		||||
    gbinder_eventloop_glib_callback_new,
 | 
			
		||||
    gbinder_eventloop_glib_callback_ref,
 | 
			
		||||
    gbinder_eventloop_glib_callback_unref,
 | 
			
		||||
    gbinder_eventloop_glib_callback_schedule,
 | 
			
		||||
    gbinder_eventloop_glib_callback_cancel,
 | 
			
		||||
    gbinder_eventloop_glib_cleanup
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal interface
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static const GBinderEventLoopIntegration* gbinder_eventloop =
 | 
			
		||||
    GBINDER_DEFAULT_EVENTLOOP;
 | 
			
		||||
 | 
			
		||||
GBinderEventLoopTimeout*
 | 
			
		||||
gbinder_timeout_add(
 | 
			
		||||
    guint interval,
 | 
			
		||||
    GSourceFunc function,
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_eventloop->timeout_add(interval, function, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderEventLoopTimeout*
 | 
			
		||||
gbinder_idle_add(
 | 
			
		||||
    GSourceFunc function,
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_eventloop->timeout_add(0, function, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_timeout_remove(
 | 
			
		||||
    GBinderEventLoopTimeout* timeout)
 | 
			
		||||
{
 | 
			
		||||
    if (timeout) {
 | 
			
		||||
        timeout->eventloop->timeout_remove(timeout);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
gbinder_idle_callback_new(
 | 
			
		||||
    GBinderEventLoopCallbackFunc func,
 | 
			
		||||
    gpointer data,
 | 
			
		||||
    GDestroyNotify finalize)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_eventloop->callback_new(func, data, finalize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
gbinder_idle_callback_schedule_new(
 | 
			
		||||
    GBinderEventLoopCallbackFunc func,
 | 
			
		||||
    gpointer data,
 | 
			
		||||
    GDestroyNotify finalize)
 | 
			
		||||
{
 | 
			
		||||
    GBinderEventLoopCallback* cb =
 | 
			
		||||
        gbinder_eventloop->callback_new(func, data, finalize);
 | 
			
		||||
 | 
			
		||||
    gbinder_idle_callback_schedule(cb);
 | 
			
		||||
    return cb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
gbinder_idle_callback_ref(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    if (cb) {
 | 
			
		||||
        cb->eventloop->callback_ref(cb);
 | 
			
		||||
        return cb;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_unref(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    if (cb) {
 | 
			
		||||
        cb->eventloop->callback_unref(cb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_schedule(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    if (cb) {
 | 
			
		||||
        cb->eventloop->callback_schedule(cb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_cancel(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    if (cb) {
 | 
			
		||||
        cb->eventloop->callback_cancel(cb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_destroy(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    if (cb) {
 | 
			
		||||
        const GBinderEventLoopIntegration* eventloop = cb->eventloop;
 | 
			
		||||
 | 
			
		||||
        eventloop->callback_cancel(cb);
 | 
			
		||||
        eventloop->callback_unref(cb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_eventloop_set(
 | 
			
		||||
    const GBinderEventLoopIntegration* loop)
 | 
			
		||||
{
 | 
			
		||||
    if (!loop) loop = GBINDER_DEFAULT_EVENTLOOP;
 | 
			
		||||
    if (gbinder_eventloop != loop) {
 | 
			
		||||
        const GBinderEventLoopIntegration* prev = gbinder_eventloop;
 | 
			
		||||
 | 
			
		||||
        gbinder_eventloop = loop;
 | 
			
		||||
        prev->cleanup();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										103
									
								
								src/gbinder_eventloop_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/gbinder_eventloop_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GBINDER_EVENTLOOP_PRIVATE_H
 | 
			
		||||
#define GBINDER_EVENTLOOP_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "gbinder_eventloop.h"
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
GBinderEventLoopTimeout*
 | 
			
		||||
gbinder_timeout_add(
 | 
			
		||||
    guint millis,
 | 
			
		||||
    GSourceFunc func,
 | 
			
		||||
    gpointer data);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
GBinderEventLoopTimeout*
 | 
			
		||||
gbinder_idle_add(
 | 
			
		||||
    GSourceFunc func,
 | 
			
		||||
    gpointer data);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
void
 | 
			
		||||
gbinder_timeout_remove(
 | 
			
		||||
    GBinderEventLoopTimeout* timeout);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
gbinder_idle_callback_new(
 | 
			
		||||
    GBinderEventLoopCallbackFunc func,
 | 
			
		||||
    gpointer data,
 | 
			
		||||
    GDestroyNotify destroy);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
gbinder_idle_callback_schedule_new(
 | 
			
		||||
    GBinderEventLoopCallbackFunc func,
 | 
			
		||||
    gpointer data,
 | 
			
		||||
    GDestroyNotify destroy);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
gbinder_idle_callback_ref(
 | 
			
		||||
    GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_unref(
 | 
			
		||||
    GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_schedule(
 | 
			
		||||
    GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_cancel(
 | 
			
		||||
    GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
G_GNUC_INTERNAL
 | 
			
		||||
void
 | 
			
		||||
gbinder_idle_callback_destroy(
 | 
			
		||||
    GBinderEventLoopCallback* cb);
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_EVENTLOOP_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -43,10 +43,10 @@
 | 
			
		||||
#include "gbinder_remote_object_p.h"
 | 
			
		||||
#include "gbinder_remote_reply_p.h"
 | 
			
		||||
#include "gbinder_remote_request_p.h"
 | 
			
		||||
#include "gbinder_eventloop_p.h"
 | 
			
		||||
#include "gbinder_writer.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_idlepool.h>
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@@ -60,7 +60,6 @@ struct gbinder_ipc_priv {
 | 
			
		||||
    GBinderIpc* self;
 | 
			
		||||
    GThreadPool* tx_pool;
 | 
			
		||||
    GHashTable* tx_table;
 | 
			
		||||
    GMainContext* context;
 | 
			
		||||
    char* key;
 | 
			
		||||
    GBinderObjectRegistry object_registry;
 | 
			
		||||
 | 
			
		||||
@@ -175,7 +174,7 @@ typedef struct gbinder_ipc_tx_priv {
 | 
			
		||||
    GBinderIpcTxPrivFunc fn_exec;
 | 
			
		||||
    GBinderIpcTxPrivFunc fn_done;
 | 
			
		||||
    GBinderIpcTxPrivFunc fn_free;
 | 
			
		||||
    GSource* completion;
 | 
			
		||||
    GBinderEventLoopCallback* completion;
 | 
			
		||||
} GBinderIpcTxPriv;
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_ipc_tx_internal {
 | 
			
		||||
@@ -406,7 +405,7 @@ gbinder_ipc_looper_unref(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_looper_tx_handle(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
@@ -480,7 +479,6 @@ gbinder_ipc_looper_tx_handle(
 | 
			
		||||
    if (write(tx->pipefd[1], &done, sizeof(done)) <= 0) {
 | 
			
		||||
        GWARN("Failed to wake up the looper");
 | 
			
		||||
    }
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -593,13 +591,11 @@ gbinder_ipc_looper_transact(
 | 
			
		||||
        GBinderIpcPriv* priv = ipc->priv;
 | 
			
		||||
        struct pollfd fds[2];
 | 
			
		||||
        guint8 done = 0;
 | 
			
		||||
        GSource* source = g_idle_source_new();
 | 
			
		||||
        gboolean was_blocked = FALSE;
 | 
			
		||||
 | 
			
		||||
        /* Let GBinderLocalObject handle the transaction on the main thread */
 | 
			
		||||
        g_source_set_callback(source, gbinder_ipc_looper_tx_handle,
 | 
			
		||||
            gbinder_ipc_looper_tx_ref(tx), gbinder_ipc_looper_tx_done);
 | 
			
		||||
        g_source_attach(source, priv->context);
 | 
			
		||||
        GBinderEventLoopCallback* callback =
 | 
			
		||||
            gbinder_idle_callback_schedule_new(gbinder_ipc_looper_tx_handle,
 | 
			
		||||
                gbinder_ipc_looper_tx_ref(tx), gbinder_ipc_looper_tx_done);
 | 
			
		||||
 | 
			
		||||
        /* Wait for either transaction completion or looper shutdown */
 | 
			
		||||
        memset(fds, 0, sizeof(fds));
 | 
			
		||||
@@ -685,8 +681,7 @@ gbinder_ipc_looper_transact(
 | 
			
		||||
            gbinder_ipc_looper_tx_unref(tx, FALSE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        g_source_destroy(source);
 | 
			
		||||
        g_source_unref(source);
 | 
			
		||||
        gbinder_idle_callback_destroy(callback);
 | 
			
		||||
 | 
			
		||||
        if (was_blocked) {
 | 
			
		||||
            guint n;
 | 
			
		||||
@@ -1197,7 +1192,7 @@ gbinder_ipc_tx_free(
 | 
			
		||||
    GBinderIpc* self = pub->ipc;
 | 
			
		||||
    GBinderIpcPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    g_source_unref(tx->completion);
 | 
			
		||||
    gbinder_idle_callback_unref(tx->completion);
 | 
			
		||||
    g_hash_table_remove(priv->tx_table, GINT_TO_POINTER(pub->id));
 | 
			
		||||
    tx->fn_free(tx);
 | 
			
		||||
 | 
			
		||||
@@ -1206,7 +1201,7 @@ gbinder_ipc_tx_free(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_tx_done(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
@@ -1216,7 +1211,6 @@ gbinder_ipc_tx_done(
 | 
			
		||||
    if (!pub->cancelled) {
 | 
			
		||||
        tx->fn_done(tx);
 | 
			
		||||
    }
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1247,8 +1241,7 @@ gbinder_ipc_tx_priv_init(
 | 
			
		||||
    priv->fn_exec = fn_exec;
 | 
			
		||||
    priv->fn_done = fn_done;
 | 
			
		||||
    priv->fn_free = fn_free;
 | 
			
		||||
    priv->completion = g_idle_source_new();
 | 
			
		||||
    g_source_set_callback(priv->completion, gbinder_ipc_tx_done, priv,
 | 
			
		||||
    priv->completion = gbinder_idle_callback_new(gbinder_ipc_tx_done, priv,
 | 
			
		||||
        gbinder_ipc_tx_free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1425,8 +1418,6 @@ gbinder_ipc_tx_proc(
 | 
			
		||||
    gpointer object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpcTxPriv* tx = data;
 | 
			
		||||
    GBinderIpc* self = GBINDER_IPC(object);
 | 
			
		||||
    GBinderIpcPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    if (!tx->pub.cancelled) {
 | 
			
		||||
        tx->fn_exec(tx);
 | 
			
		||||
@@ -1435,7 +1426,7 @@ gbinder_ipc_tx_proc(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* The result is handled by the main thread */
 | 
			
		||||
    g_source_attach(tx->completion, priv->context);
 | 
			
		||||
    gbinder_idle_callback_schedule(tx->completion);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
@@ -1641,14 +1632,12 @@ gbinder_ipc_init(
 | 
			
		||||
    g_mutex_init(&priv->looper_mutex);
 | 
			
		||||
    g_mutex_init(&priv->local_objects_mutex);
 | 
			
		||||
    g_mutex_init(&priv->remote_objects_mutex);
 | 
			
		||||
    priv->context = g_main_context_default();
 | 
			
		||||
    priv->tx_table = g_hash_table_new(g_direct_hash, g_direct_equal);
 | 
			
		||||
    priv->tx_pool = g_thread_pool_new(gbinder_ipc_tx_proc, self,
 | 
			
		||||
        GBINDER_IPC_MAX_TX_THREADS, FALSE, NULL);
 | 
			
		||||
    priv->object_registry.f = &object_registry_functions;
 | 
			
		||||
    priv->self = self;
 | 
			
		||||
    self->priv = priv;
 | 
			
		||||
    self->pool = gutil_idle_pool_new();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -1729,7 +1718,6 @@ gbinder_ipc_finalize(
 | 
			
		||||
    }
 | 
			
		||||
    GASSERT(!g_hash_table_size(priv->tx_table));
 | 
			
		||||
    g_hash_table_unref(priv->tx_table);
 | 
			
		||||
    gutil_idle_pool_unref(self->pool);
 | 
			
		||||
    gbinder_driver_unref(self->driver);
 | 
			
		||||
    g_free(priv->key);
 | 
			
		||||
    G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
 | 
			
		||||
@@ -1795,11 +1783,9 @@ gbinder_ipc_exit()
 | 
			
		||||
        }
 | 
			
		||||
        for (k = tx_keys; k; k = k->next) {
 | 
			
		||||
            GBinderIpcTxPriv* tx = g_hash_table_lookup(priv->tx_table, k->data);
 | 
			
		||||
            GSource* source = g_source_ref(tx->completion);
 | 
			
		||||
 | 
			
		||||
            GVERBOSE_("tx %lu", tx->pub.id);
 | 
			
		||||
            g_source_destroy(source);
 | 
			
		||||
            g_source_unref(source);
 | 
			
		||||
            gbinder_idle_callback_cancel(tx->completion);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* The above loop must destroy all uncompleted transactions */
 | 
			
		||||
@@ -1830,6 +1816,7 @@ gbinder_ipc_exit()
 | 
			
		||||
        g_slist_free_full(local_objs, g_object_unref);
 | 
			
		||||
    }
 | 
			
		||||
    g_slist_free_full(ipcs, g_object_unref);
 | 
			
		||||
    gbinder_eventloop_set(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -14,8 +14,8 @@
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -42,7 +42,6 @@ struct gbinder_ipc {
 | 
			
		||||
    GObject object;
 | 
			
		||||
    GBinderIpcPriv* priv;
 | 
			
		||||
    GBinderDriver* driver;
 | 
			
		||||
    GUtilIdlePool* pool;
 | 
			
		||||
    const char* dev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -36,13 +36,13 @@
 | 
			
		||||
#include "gbinder_client_p.h"
 | 
			
		||||
#include "gbinder_local_object_p.h"
 | 
			
		||||
#include "gbinder_remote_object_p.h"
 | 
			
		||||
#include "gbinder_eventloop_p.h"
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_ipc.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gbinder_client.h>
 | 
			
		||||
 | 
			
		||||
#include <gutil_idlepool.h>
 | 
			
		||||
#include <gutil_misc.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
@@ -62,8 +62,10 @@ struct gbinder_servicemanager_priv {
 | 
			
		||||
    GHashTable* watch_table;
 | 
			
		||||
    gulong death_id;
 | 
			
		||||
    gboolean present;
 | 
			
		||||
    guint presence_check_id;
 | 
			
		||||
    GBinderEventLoopTimeout* presence_check;
 | 
			
		||||
    guint presence_check_delay_ms;
 | 
			
		||||
    GBinderEventLoopCallback* autorelease_cb;
 | 
			
		||||
    GSList* autorelease;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
 | 
			
		||||
@@ -275,9 +277,9 @@ gbinder_servicemanager_reanimated(
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    if (priv->presence_check_id) {
 | 
			
		||||
        g_source_remove(priv->presence_check_id);
 | 
			
		||||
        priv->presence_check_id = 0;
 | 
			
		||||
    if (priv->presence_check) {
 | 
			
		||||
        gbinder_timeout_remove(priv->presence_check);
 | 
			
		||||
        priv->presence_check = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    GINFO("Service manager %s has appeared", self->dev);
 | 
			
		||||
    /* Re-arm the watches */
 | 
			
		||||
@@ -317,13 +319,14 @@ gbinder_servicemanager_presense_check_timer(
 | 
			
		||||
    gbinder_servicemanager_ref(self);
 | 
			
		||||
    if (gbinder_remote_object_reanimate(remote)) {
 | 
			
		||||
        /* Done */
 | 
			
		||||
        priv->presence_check_id = 0;
 | 
			
		||||
        priv->presence_check = NULL;
 | 
			
		||||
        gbinder_servicemanager_reanimated(self);
 | 
			
		||||
        result = G_SOURCE_REMOVE;
 | 
			
		||||
    } else if (priv->presence_check_delay_ms < PRESENSE_WAIT_MS_MAX) {
 | 
			
		||||
        priv->presence_check_delay_ms += PRESENSE_WAIT_MS_STEP;
 | 
			
		||||
        priv->presence_check_id = g_timeout_add(priv->presence_check_delay_ms,
 | 
			
		||||
            gbinder_servicemanager_presense_check_timer, self);
 | 
			
		||||
        priv->presence_check =
 | 
			
		||||
            gbinder_timeout_add(priv->presence_check_delay_ms,
 | 
			
		||||
                gbinder_servicemanager_presense_check_timer, self);
 | 
			
		||||
        result = G_SOURCE_REMOVE;
 | 
			
		||||
    } else {
 | 
			
		||||
        result = G_SOURCE_CONTINUE;
 | 
			
		||||
@@ -339,9 +342,9 @@ gbinder_servicemanager_presence_check_start(
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    GASSERT(!priv->presence_check_id);
 | 
			
		||||
    GASSERT(!priv->presence_check);
 | 
			
		||||
    priv->presence_check_delay_ms = PRESENSE_WAIT_MS_MIN;
 | 
			
		||||
    priv->presence_check_id = g_timeout_add(PRESENSE_WAIT_MS_MIN,
 | 
			
		||||
    priv->presence_check = gbinder_timeout_add(PRESENSE_WAIT_MS_MIN,
 | 
			
		||||
        gbinder_servicemanager_presense_check_timer, self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -391,6 +394,20 @@ gbinder_servicemanager_sleep_ms(
 | 
			
		||||
        (wait.tv_sec > 0 || wait.tv_nsec > 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_autorelease_cb(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(data);
 | 
			
		||||
    GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
    GSList* list = priv->autorelease;
 | 
			
		||||
 | 
			
		||||
    priv->autorelease_cb = NULL;
 | 
			
		||||
    priv->autorelease = NULL;
 | 
			
		||||
    g_slist_free_full(list, g_object_unref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal interface
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -675,10 +692,15 @@ gbinder_servicemanager_get_service_sync(
 | 
			
		||||
    if (G_LIKELY(self) && name) {
 | 
			
		||||
        obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)->get_service
 | 
			
		||||
            (self, name, status);
 | 
			
		||||
        if (!self->pool) {
 | 
			
		||||
            self->pool = gutil_idle_pool_new();
 | 
			
		||||
        if (obj) {
 | 
			
		||||
            GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
            priv->autorelease = g_slist_prepend(priv->autorelease, obj);
 | 
			
		||||
            if (!priv->autorelease_cb) {
 | 
			
		||||
                priv->autorelease_cb = gbinder_idle_callback_schedule_new
 | 
			
		||||
                    (gbinder_servicemanager_autorelease_cb, self, NULL);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        gutil_idle_pool_add_object(self->pool, obj);
 | 
			
		||||
    } else if (status) {
 | 
			
		||||
        *status = (-EINVAL);
 | 
			
		||||
    }
 | 
			
		||||
@@ -915,12 +937,11 @@ gbinder_servicemanager_finalize(
 | 
			
		||||
    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
 | 
			
		||||
    GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    if (priv->presence_check_id) {
 | 
			
		||||
        g_source_remove(priv->presence_check_id);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_timeout_remove(priv->presence_check);
 | 
			
		||||
    gbinder_remote_object_remove_handler(self->client->remote, priv->death_id);
 | 
			
		||||
    gbinder_idle_callback_destroy(priv->autorelease_cb);
 | 
			
		||||
    g_slist_free_full(priv->autorelease, g_object_unref);
 | 
			
		||||
    g_hash_table_destroy(priv->watch_table);
 | 
			
		||||
    gutil_idle_pool_destroy(self->pool);
 | 
			
		||||
    gbinder_client_unref(self->client);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -14,8 +14,8 @@
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -49,7 +49,6 @@ typedef struct gbinder_servicemanager {
 | 
			
		||||
    GBinderServiceManagerPriv* priv;
 | 
			
		||||
    const char* dev;
 | 
			
		||||
    GBinderClient* client;
 | 
			
		||||
    GUtilIdlePool* pool;
 | 
			
		||||
} GBinderServiceManager;
 | 
			
		||||
 | 
			
		||||
typedef enum gbinder_servicemanager_name_check {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicepoll.h"
 | 
			
		||||
#include "gbinder_servicemanager.h"
 | 
			
		||||
#include "gbinder_eventloop_p.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_strv.h>
 | 
			
		||||
 | 
			
		||||
@@ -46,7 +47,7 @@ struct gbinder_servicepoll {
 | 
			
		||||
    GBinderServiceManager* manager;
 | 
			
		||||
    char** list;
 | 
			
		||||
    gulong list_id;
 | 
			
		||||
    guint timer_id;
 | 
			
		||||
    GBinderEventLoopTimeout* timer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE(GBinderServicePoll, gbinder_servicepoll, G_TYPE_OBJECT)
 | 
			
		||||
@@ -230,7 +231,7 @@ void
 | 
			
		||||
gbinder_servicepoll_init(
 | 
			
		||||
    GBinderServicePoll* self)
 | 
			
		||||
{
 | 
			
		||||
    self->timer_id = g_timeout_add(gbinder_servicepoll_interval_ms,
 | 
			
		||||
    self->timer = gbinder_timeout_add(gbinder_servicepoll_interval_ms,
 | 
			
		||||
        gbinder_servicepoll_timer, self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -241,7 +242,7 @@ gbinder_servicepoll_finalize(
 | 
			
		||||
{
 | 
			
		||||
    GBinderServicePoll* self = GBINDER_SERVICEPOLL(object);
 | 
			
		||||
 | 
			
		||||
    g_source_remove(self->timer_id);
 | 
			
		||||
    gbinder_timeout_remove(self->timer);
 | 
			
		||||
    gbinder_servicemanager_cancel(self->manager, self->list_id);
 | 
			
		||||
    gbinder_servicemanager_unref(self->manager);
 | 
			
		||||
    g_strfreev(self->list);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ all:
 | 
			
		||||
	@$(MAKE) -C unit_cleanup $*
 | 
			
		||||
	@$(MAKE) -C unit_client $*
 | 
			
		||||
	@$(MAKE) -C unit_driver $*
 | 
			
		||||
	@$(MAKE) -C unit_eventloop $*
 | 
			
		||||
	@$(MAKE) -C unit_ipc $*
 | 
			
		||||
	@$(MAKE) -C unit_local_object $*
 | 
			
		||||
	@$(MAKE) -C unit_local_reply $*
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ unit_buffer \
 | 
			
		||||
unit_cleanup \
 | 
			
		||||
unit_client \
 | 
			
		||||
unit_driver \
 | 
			
		||||
unit_eventloop \
 | 
			
		||||
unit_ipc \
 | 
			
		||||
unit_local_object \
 | 
			
		||||
unit_local_reply \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								unit/unit_eventloop/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_eventloop/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_eventloop
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										262
									
								
								unit/unit_eventloop/unit_eventloop.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								unit/unit_eventloop/unit_eventloop.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,262 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "gbinder_eventloop_p.h"
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
static int test_eventloop_timeout_add_called;
 | 
			
		||||
static int test_eventloop_callback_new_called;
 | 
			
		||||
static int test_eventloop_cleanup_called;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_unreached_proc(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return G_SOURCE_CONTINUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Test event loop integration
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderEventLoopTimeout*
 | 
			
		||||
test_eventloop_timeout_add(
 | 
			
		||||
    guint interval,
 | 
			
		||||
    GSourceFunc func,
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    test_eventloop_timeout_add_called++;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_eventloop_timeout_remove(
 | 
			
		||||
    GBinderEventLoopTimeout* timeout)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderEventLoopCallback*
 | 
			
		||||
test_eventloop_callback_new(
 | 
			
		||||
    GBinderEventLoopCallbackFunc func,
 | 
			
		||||
    gpointer data,
 | 
			
		||||
    GDestroyNotify destroy)
 | 
			
		||||
{
 | 
			
		||||
    test_eventloop_callback_new_called++;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_eventloop_callback_ref(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_eventloop_callback_unref(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_eventloop_callback_schedule(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_eventloop_callback_cancel(
 | 
			
		||||
    GBinderEventLoopCallback* cb)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_eventloop_cleanup(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    test_eventloop_cleanup_called++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const GBinderEventLoopIntegration test_eventloop = {
 | 
			
		||||
    test_eventloop_timeout_add,
 | 
			
		||||
    test_eventloop_timeout_remove,
 | 
			
		||||
    test_eventloop_callback_new,
 | 
			
		||||
    test_eventloop_callback_ref,
 | 
			
		||||
    test_eventloop_callback_unref,
 | 
			
		||||
    test_eventloop_callback_schedule,
 | 
			
		||||
    test_eventloop_callback_cancel,
 | 
			
		||||
    test_eventloop_cleanup
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * replace
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_replace(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    test_eventloop_timeout_add_called = 0;
 | 
			
		||||
    test_eventloop_callback_new_called = 0;
 | 
			
		||||
    test_eventloop_cleanup_called = 0;
 | 
			
		||||
 | 
			
		||||
    gbinder_eventloop_set(NULL);
 | 
			
		||||
    gbinder_eventloop_set(&test_eventloop);
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_timeout_add(0, test_unreached_proc, NULL));
 | 
			
		||||
    g_assert_cmpint(test_eventloop_timeout_add_called, == ,1);
 | 
			
		||||
    g_assert(!gbinder_idle_add(test_unreached_proc, NULL));
 | 
			
		||||
    g_assert_cmpint(test_eventloop_timeout_add_called, == ,2);
 | 
			
		||||
    gbinder_timeout_remove(NULL);
 | 
			
		||||
    g_assert(!gbinder_idle_callback_new(NULL, NULL, NULL));
 | 
			
		||||
    g_assert_cmpint(test_eventloop_callback_new_called, == ,1);
 | 
			
		||||
    g_assert(!gbinder_idle_callback_ref(NULL));
 | 
			
		||||
    gbinder_idle_callback_unref(NULL);
 | 
			
		||||
    gbinder_idle_callback_schedule(NULL);
 | 
			
		||||
    gbinder_idle_callback_cancel(NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_eventloop_set(NULL);
 | 
			
		||||
    g_assert_cmpint(test_eventloop_cleanup_called, == ,1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * idle
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_quit_func(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    g_main_loop_quit((GMainLoop*)data);
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_idle(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
    gbinder_eventloop_set(NULL);
 | 
			
		||||
    g_assert(gbinder_idle_add(test_quit_func, loop));
 | 
			
		||||
    test_run(&test_opt, loop);
 | 
			
		||||
    g_main_loop_unref(loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * timeout
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_timeout(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
    gbinder_eventloop_set(NULL);
 | 
			
		||||
    g_assert(gbinder_timeout_add(10, test_quit_func, loop));
 | 
			
		||||
    test_run(&test_opt, loop);
 | 
			
		||||
    g_main_loop_unref(loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * callback
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_quit_cb(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    g_main_loop_quit((GMainLoop*)data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_callback(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderEventLoopCallback* cb;
 | 
			
		||||
 | 
			
		||||
    gbinder_eventloop_set(NULL);
 | 
			
		||||
    cb = gbinder_idle_callback_new(test_quit_cb, loop, NULL);
 | 
			
		||||
    gbinder_idle_callback_schedule(cb);
 | 
			
		||||
    test_run(&test_opt, loop);
 | 
			
		||||
    gbinder_idle_callback_unref(cb);
 | 
			
		||||
    g_main_loop_unref(loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define TEST_(t) "/eventloop/" t
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("replace"), test_replace);
 | 
			
		||||
    g_test_add_func(TEST_("idle"), test_idle);
 | 
			
		||||
    g_test_add_func(TEST_("timeout"), test_timeout);
 | 
			
		||||
    g_test_add_func(TEST_("callback"), test_callback);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
		Reference in New Issue
	
	Block a user