utils: implement g_cancellable_new_with_timeout

This commit is contained in:
Dirk-Jan C. Binnema 2023-04-29 00:52:37 +03:00
parent 2c69a6d84b
commit e4af910d04
2 changed files with 61 additions and 0 deletions

View File

@ -178,6 +178,55 @@ Mu::runtime_path(Mu::RuntimePath path, const std::string& muhome)
}
}
static gpointer
cancel_wait(gpointer data)
{
guint timeout, deadline;
GCancellable *cancel;
cancel = (GCancellable*)data;
timeout = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(cancel), "timeout"));
deadline = g_get_monotonic_time() + 1000 * timeout;
while (g_get_monotonic_time() < deadline && !g_cancellable_is_cancelled(cancel)) {
g_usleep(50 * 1000); /* 50 ms */
g_thread_yield();
}
g_cancellable_cancel(cancel);
return NULL;
}
static void
cancel_wait_free(gpointer data)
{
GThread *thread;
GCancellable *cancel;
cancel = (GCancellable*)data;
thread = (GThread*)g_object_get_data(G_OBJECT(cancel), "thread");
g_cancellable_cancel(cancel);
g_thread_join(thread);
}
GCancellable*
Mu::g_cancellable_new_with_timeout(guint timeout)
{
GCancellable *cancel;
cancel = g_cancellable_new();
g_object_set_data(G_OBJECT(cancel), "timeout", GUINT_TO_POINTER(timeout));
g_object_set_data(G_OBJECT(cancel), "thread",
g_thread_new("cancel-wait", cancel_wait, cancel));
g_object_set_data_full(G_OBJECT(cancel), "cancel", cancel, cancel_wait_free);
return cancel;
}
#ifdef BUILD_TESTS

View File

@ -24,6 +24,7 @@
#include <cinttypes>
#include <sys/stat.h>
#include <gio/gio.h>
#include <utils/mu-option.hh>
#include <utils/mu-regex.hh>
@ -157,6 +158,17 @@ std::string join_paths(S&& s, Args...args) {
}
/**
* Like g_cancellable_new(), but automatically cancels itself
* after timeout
*
* @param timeout timeout in millisecs
*
* @return A GCancellable* instances; free with g_object_unref() when
* no longer needed.
*/
GCancellable* g_cancellable_new_with_timeout(guint timeout);
} // namespace Mu
#endif /* MU_UTILS_FILE_HH__ */