gattlib/common/mainloop/gattlib_glib_mainloop.c

91 lines
2.4 KiB
C

/*
* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
*
* Copyright (c) 2021-2024, Olivier Martin <olivier@labapart.org>
*/
/**
* See some Glib mainloop API function usage in this example:
* https://github.com/ImageMagick/glib/blob/main/tests/mainloop-test.c
*/
#include "gattlib_internal.h"
// We make this variable global to be able to exit the main loop
static GMainLoop *m_main_loop;
struct _execute_task_arg {
void* (*task)(void* arg);
void* arg;
};
static void* _execute_task(void* arg) {
struct _execute_task_arg *execute_task_arg = arg;
execute_task_arg->task(execute_task_arg->arg);
g_main_loop_quit(m_main_loop);
return NULL;
}
int gattlib_mainloop(void* (*task)(void* arg), void *arg) {
struct _execute_task_arg execute_task_arg = {
.task = task,
.arg = arg
};
GError* error;
if (m_main_loop != NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Main loop is already running: %s", error->message);
g_error_free(error);
return GATTLIB_BUSY;
}
m_main_loop = g_main_loop_new(NULL, FALSE);
GThread *task_thread = g_thread_try_new("gattlib_task", _execute_task, &execute_task_arg, &error);
g_main_loop_run(m_main_loop);
g_main_loop_unref(m_main_loop);
g_thread_join(task_thread);
g_thread_unref(task_thread);
m_main_loop = NULL;
return GATTLIB_SUCCESS;
}
#if defined(WITH_PYTHON)
struct gattlib_mainloop_handler_python_args {
PyObject *handler;
PyObject *user_data;
};
static void* _gattlib_mainloop_handler_python(void* args) {
struct gattlib_mainloop_handler_python_args* python_args = (struct gattlib_mainloop_handler_python_args*)args;
PyGILState_STATE d_gstate;
PyObject *result;
d_gstate = PyGILState_Ensure();
#if PYTHON_VERSION >= PYTHON_VERSIONS(3, 9)
result = PyObject_Call(python_args->handler, python_args->user_data, NULL);
#else
result = PyEval_CallObject(python_args->handler, python_args->user_data);
#endif
if (result == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Python task handler has raised an exception.");
}
PyGILState_Release(d_gstate);
return result;
}
int gattlib_mainloop_python(PyObject *handler, PyObject *user_data) {
struct gattlib_mainloop_handler_python_args python_args = {
.handler = handler,
.user_data = user_data
};
return gattlib_mainloop(_gattlib_mainloop_handler_python, &python_args);
}
#endif