port-serial: port mm_port_serial_command() to GTask

Use GTask API in place of the deprecated GSimpleAsyncResult.
This commit is contained in:
Lubomir Rintel
2023-01-08 19:31:38 +01:00
committed by Aleksander Morgado
parent 4e879cbede
commit e1e7bc8de6

View File

@@ -117,9 +117,6 @@ struct _MMPortSerialPrivate {
/* Command */ /* Command */
typedef struct { typedef struct {
MMPortSerial *self;
GSimpleAsyncResult *result;
GCancellable *cancellable;
GByteArray *command; GByteArray *command;
guint32 timeout; guint32 timeout;
gboolean allow_cached; gboolean allow_cached;
@@ -131,17 +128,9 @@ typedef struct {
} CommandContext; } CommandContext;
static void static void
command_context_complete_and_free (CommandContext *ctx, gboolean idle) command_context_free (CommandContext *ctx)
{ {
if (idle)
g_simple_async_result_complete_in_idle (ctx->result);
else
g_simple_async_result_complete (ctx->result);
g_object_unref (ctx->result);
g_byte_array_unref (ctx->command); g_byte_array_unref (ctx->command);
if (ctx->cancellable)
g_object_unref (ctx->cancellable);
g_object_unref (ctx->self);
g_slice_free (CommandContext, ctx); g_slice_free (CommandContext, ctx);
} }
@@ -150,10 +139,7 @@ mm_port_serial_command_finish (MMPortSerial *self,
GAsyncResult *res, GAsyncResult *res,
GError **error) GError **error)
{ {
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) return g_task_propagate_pointer (G_TASK (res), error);
return NULL;
return g_byte_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
} }
void void
@@ -167,21 +153,20 @@ mm_port_serial_command (MMPortSerial *self,
gpointer user_data) gpointer user_data)
{ {
CommandContext *ctx; CommandContext *ctx;
GTask *task;
g_return_if_fail (MM_IS_PORT_SERIAL (self)); g_return_if_fail (MM_IS_PORT_SERIAL (self));
g_return_if_fail (command != NULL); g_return_if_fail (command != NULL);
/* Setup command context */ /* Setup command context */
ctx = g_slice_new0 (CommandContext); ctx = g_slice_new0 (CommandContext);
ctx->self = g_object_ref (self);
ctx->result = g_simple_async_result_new (G_OBJECT (self), task = g_task_new (self, cancellable, callback, user_data);
callback, g_task_set_task_data (task, ctx, (GDestroyNotify)command_context_free);
user_data,
mm_port_serial_command);
ctx->command = g_byte_array_ref (command); ctx->command = g_byte_array_ref (command);
ctx->allow_cached = allow_cached; ctx->allow_cached = allow_cached;
ctx->timeout = timeout_seconds; ctx->timeout = timeout_seconds;
ctx->cancellable = (cancellable ? g_object_ref (cancellable) : NULL);
/* Only accept about 3 seconds of EAGAIN for this command */ /* Only accept about 3 seconds of EAGAIN for this command */
if (self->priv->send_delay && mm_port_get_subsys (MM_PORT (self)) == MM_PORT_SUBSYS_TTY) if (self->priv->send_delay && mm_port_get_subsys (MM_PORT (self)) == MM_PORT_SUBSYS_TTY)
@@ -190,11 +175,11 @@ mm_port_serial_command (MMPortSerial *self,
ctx->eagain_count = 1000; ctx->eagain_count = 1000;
if (self->priv->open_count == 0) { if (self->priv->open_count == 0) {
g_simple_async_result_set_error (ctx->result, g_task_return_new_error (task,
MM_SERIAL_ERROR, MM_SERIAL_ERROR,
MM_SERIAL_ERROR_SEND_FAILED, MM_SERIAL_ERROR_SEND_FAILED,
"Sending command failed: device is not open"); "Sending command failed: device is not open");
command_context_complete_and_free (ctx, TRUE); g_object_unref (task);
return; return;
} }
@@ -205,9 +190,9 @@ mm_port_serial_command (MMPortSerial *self,
/* If requested to run next, push to the head of the queue so that it really is /* If requested to run next, push to the head of the queue so that it really is
* the next one sent */ * the next one sent */
if (run_next) if (run_next)
g_queue_push_head (self->priv->queue, ctx); g_queue_push_head (self->priv->queue, task);
else else
g_queue_push_tail (self->priv->queue, ctx); g_queue_push_tail (self->priv->queue, task);
if (g_queue_get_length (self->priv->queue) == 1) if (g_queue_get_length (self->priv->queue) == 1)
port_serial_schedule_queue_process (self, 0); port_serial_schedule_queue_process (self, 0);
@@ -708,7 +693,7 @@ port_serial_schedule_queue_process (MMPortSerial *self, guint timeout_ms)
static void static void
port_serial_got_response (MMPortSerial *self, port_serial_got_response (MMPortSerial *self,
GByteArray *parsed_response, GByteArray *parsed_response,
const GError *error) GError *error)
{ {
/* Either one or the other, not both */ /* Either one or the other, not both */
g_assert ((parsed_response && !error) || (!parsed_response && error)); g_assert ((parsed_response && !error) || (!parsed_response && error));
@@ -733,30 +718,32 @@ port_serial_got_response (MMPortSerial *self,
* setup runs. */ * setup runs. */
g_object_ref (self); g_object_ref (self);
{ {
CommandContext *ctx; GTask *task;
ctx = (CommandContext *) g_queue_pop_head (self->priv->queue); task = g_queue_pop_head (self->priv->queue);
if (ctx) { if (task) {
/* Complete the command context with the appropriate result */ /* Complete the command context with the appropriate result */
if (error) if (error) {
g_simple_async_result_set_from_error (ctx->result, error); g_task_return_error (task, g_steal_pointer (&error));
else { } else {
CommandContext *ctx;
ctx = g_task_get_task_data (task);
if (ctx->allow_cached) if (ctx->allow_cached)
port_serial_set_cached_reply (self, ctx->command, parsed_response); port_serial_set_cached_reply (self, ctx->command, parsed_response);
g_simple_async_result_set_op_res_gpointer (ctx->result, g_task_return_pointer (task,
g_byte_array_ref (parsed_response), g_byte_array_ref (parsed_response),
(GDestroyNotify) g_byte_array_unref); (GDestroyNotify) g_byte_array_unref);
} }
/* Don't complete in idle. We need the caller remove the response range which g_object_unref (task);
* was processed, and that must be done before processing any new queued command */
command_context_complete_and_free (ctx, FALSE);
} }
if (!g_queue_is_empty (self->priv->queue)) if (!g_queue_is_empty (self->priv->queue))
port_serial_schedule_queue_process (self, 0); port_serial_schedule_queue_process (self, 0);
} }
g_object_unref (self); g_object_unref (self);
g_clear_error (&error);
} }
static gboolean static gboolean
@@ -788,8 +775,6 @@ port_serial_timed_out (gpointer data)
} }
g_object_unref (self); g_object_unref (self);
g_error_free (error);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
@@ -809,7 +794,6 @@ port_serial_response_wait_cancelled (GCancellable *cancellable,
"Waiting for the reply cancelled"); "Waiting for the reply cancelled");
/* Note: may complete last operation and unref the MMPortSerial */ /* Note: may complete last operation and unref the MMPortSerial */
port_serial_got_response (self, NULL, error); port_serial_got_response (self, NULL, error);
g_error_free (error);
} }
static gboolean static gboolean
@@ -817,13 +801,16 @@ port_serial_queue_process (gpointer data)
{ {
MMPortSerial *self = MM_PORT_SERIAL (data); MMPortSerial *self = MM_PORT_SERIAL (data);
CommandContext *ctx; CommandContext *ctx;
GTask *task;
GCancellable *cancellable;
GError *error = NULL; GError *error = NULL;
self->priv->queue_id = 0; self->priv->queue_id = 0;
ctx = (CommandContext *) g_queue_peek_head (self->priv->queue); task = g_queue_peek_head (self->priv->queue);
if (!ctx) if (!task)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
ctx = g_task_get_task_data (task);
if (ctx->allow_cached) { if (ctx->allow_cached) {
const GByteArray *cached; const GByteArray *cached;
@@ -847,7 +834,6 @@ port_serial_queue_process (gpointer data)
if (!port_serial_process_command (self, ctx, &error)) { if (!port_serial_process_command (self, ctx, &error)) {
/* Note: may complete last operation and unref the MMPortSerial */ /* Note: may complete last operation and unref the MMPortSerial */
port_serial_got_response (self, NULL, error); port_serial_got_response (self, NULL, error);
g_error_free (error);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
@@ -861,10 +847,11 @@ port_serial_queue_process (gpointer data)
} }
/* Setup the cancellable so that we can stop waiting for a response */ /* Setup the cancellable so that we can stop waiting for a response */
if (ctx->cancellable) { cancellable = g_task_get_cancellable (task);
if (cancellable) {
gulong cancellable_id; gulong cancellable_id;
self->priv->cancellable = g_object_ref (ctx->cancellable); self->priv->cancellable = g_object_ref (cancellable);
/* If the GCancellable is already cancelled here, the callback will be /* If the GCancellable is already cancelled here, the callback will be
* called right away, and a GError will be propagated as response. In * called right away, and a GError will be propagated as response. In
@@ -873,7 +860,7 @@ port_serial_queue_process (gpointer data)
* So, use an intermediate variable to store the cancellable id, and * So, use an intermediate variable to store the cancellable id, and
* just return without further processing if we're already cancelled. * just return without further processing if we're already cancelled.
*/ */
cancellable_id = g_cancellable_connect (ctx->cancellable, cancellable_id = g_cancellable_connect (cancellable,
(GCallback)port_serial_response_wait_cancelled, (GCallback)port_serial_response_wait_cancelled,
self, self,
NULL); NULL);
@@ -930,7 +917,6 @@ parse_response_buffer (MMPortSerial *self)
self->priv->n_consecutive_timeouts = 0; self->priv->n_consecutive_timeouts = 0;
/* Note: may complete last operation and unref the MMPortSerial */ /* Note: may complete last operation and unref the MMPortSerial */
port_serial_got_response (self, NULL, error); port_serial_got_response (self, NULL, error);
g_error_free (error);
break; break;
case MM_PORT_SERIAL_RESPONSE_NONE: case MM_PORT_SERIAL_RESPONSE_NONE:
/* Nothing to do this time */ /* Nothing to do this time */
@@ -948,6 +934,7 @@ common_input_available (MMPortSerial *self,
gsize bytes_read; gsize bytes_read;
GIOStatus status = G_IO_STATUS_NORMAL; GIOStatus status = G_IO_STATUS_NORMAL;
CommandContext *ctx; CommandContext *ctx;
GTask *task;
GError *error = NULL; GError *error = NULL;
gboolean iterate = TRUE; gboolean iterate = TRUE;
gboolean keep_source = G_SOURCE_CONTINUE; gboolean keep_source = G_SOURCE_CONTINUE;
@@ -967,7 +954,8 @@ common_input_available (MMPortSerial *self,
} }
/* Don't read any input if the current command isn't done being sent yet */ /* Don't read any input if the current command isn't done being sent yet */
ctx = g_queue_peek_nth (self->priv->queue, 0); task = g_queue_peek_nth (self->priv->queue, 0);
ctx = task ? g_task_get_task_data (task) : NULL;
if (ctx && (ctx->started == TRUE) && (ctx->done == FALSE)) if (ctx && (ctx->started == TRUE) && (ctx->done == FALSE))
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
@@ -1438,14 +1426,14 @@ _close_internal (MMPortSerial *self, gboolean force)
/* Clear the command queue */ /* Clear the command queue */
for (i = 0; i < g_queue_get_length (self->priv->queue); i++) { for (i = 0; i < g_queue_get_length (self->priv->queue); i++) {
CommandContext *ctx; GTask *task;
ctx = g_queue_peek_nth (self->priv->queue, i); task = g_queue_peek_nth (self->priv->queue, i);
g_simple_async_result_set_error (ctx->result, g_task_return_new_error (task,
MM_SERIAL_ERROR, MM_SERIAL_ERROR,
MM_SERIAL_ERROR_SEND_FAILED, MM_SERIAL_ERROR_SEND_FAILED,
"Serial port is now closed"); "Serial port is now closed");
command_context_complete_and_free (ctx, TRUE); g_object_unref (task);
} }
g_queue_clear (self->priv->queue); g_queue_clear (self->priv->queue);