/* * Copyright (C) 2011 Igalia S.L. * * Contact: Iago Toral Quiroga * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "grl-operation.h" #include "grl-operation-priv.h" #include "grl-log.h" typedef struct { GrlOperationCancelCb cancel_cb; GDestroyNotify destroy_cb; gpointer private_data; gpointer user_data; GDestroyNotify user_data_destroy_func; } OperationData; static guint operations_id; static GHashTable *operations; static void operation_data_free (OperationData *data) { if (data->user_data_destroy_func && data->user_data) { data->user_data_destroy_func (data->user_data); data->user_data = NULL; } if (data->destroy_cb) { data->destroy_cb (data->private_data); } g_slice_free (OperationData, data); } void grl_operation_init (void) { static gboolean initialized = FALSE; if (G_LIKELY (initialized)) return; initialized = TRUE; operations = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) operation_data_free); operations_id = 1; } guint grl_operation_generate_id (void) { guint operation_id = operations_id++; OperationData *data = g_slice_new0 (OperationData); g_hash_table_insert (operations, GUINT_TO_POINTER (operation_id), data); return operation_id; } void grl_operation_set_private_data (guint operation_id, gpointer private_data, GrlOperationCancelCb cancel_cb, GDestroyNotify destroy_cb) { OperationData *data = g_hash_table_lookup (operations, GUINT_TO_POINTER (operation_id)); g_return_if_fail (data != NULL); data->cancel_cb = cancel_cb; data->destroy_cb = destroy_cb; data->private_data = private_data; } /** * grl_operation_get_private_data: (skip) * @operation_id: operation identifier */ gpointer grl_operation_get_private_data (guint operation_id) { OperationData *data = g_hash_table_lookup (operations, GUINT_TO_POINTER (operation_id)); g_return_val_if_fail (data != NULL, NULL); return data->private_data; } void grl_operation_remove (guint operation_id) { g_hash_table_remove (operations, GUINT_TO_POINTER (operation_id)); } /*** PUBLIC API ***/ /** * grl_operation_cancel: * @operation_id: the identifier of a running operation * * Cancel an operation. */ void grl_operation_cancel (guint operation_id) { OperationData *data = g_hash_table_lookup (operations, GUINT_TO_POINTER (operation_id)); if (!data) { GRL_WARNING ("Invalid operation %u", operation_id); return; } g_return_if_fail (data != NULL); if (data->cancel_cb) { data->cancel_cb (data->private_data); } } /** * grl_operation_get_data: * @operation_id: the identifier of a running operation * * Obtains the previously attached data * * Returns: (transfer none): The previously attached data. */ gpointer grl_operation_get_data (guint operation_id) { OperationData *data = g_hash_table_lookup (operations, GUINT_TO_POINTER (operation_id)); if (!data) { GRL_WARNING ("Invalid operation %u", operation_id); return NULL; } return data->user_data; } /** * grl_operation_set_data: * @operation_id: the identifier of a running operation * @user_data: the data to attach * * Attach a pointer to the specific operation. */ void grl_operation_set_data (guint operation_id, gpointer user_data) { grl_operation_set_data_full (operation_id, user_data, NULL); } /** * grl_operation_set_data_full: * @operation_id: the identifier of a running operation * @user_data: (allow-none): the data to attach * @destroy_func: (allow-none): function to release @user_data when the operation terminates * * Attach a pointer to the specific operation. * * Note that the @destroy_func callback is not called if @user_data is %NULL. * * Since: 0.2.7 */ void grl_operation_set_data_full (guint operation_id, gpointer user_data, GDestroyNotify destroy_func) { OperationData *data = g_hash_table_lookup (operations, GUINT_TO_POINTER (operation_id)); if (!data) { GRL_WARNING ("Invalid operation %u", operation_id); } else { if (data->user_data_destroy_func && data->user_data) data->user_data_destroy_func (data->user_data); data->user_data = user_data; data->user_data_destroy_func = destroy_func; } }