X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgcancellable.c;h=258b88da56a8c9260a6ef422772c999da54d3ad3;hb=7e5e3e142f856ac80e83a9a5110b51aa4b5b0821;hp=fc56b87ce350e202be5f8cda5e57ba41ed1bbc83;hpb=8d0e0c6fcca845659ae54f8a4c1508826ed36963;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gcancellable.c b/gio/gcancellable.c index fc56b87..258b88d 100644 --- a/gio/gcancellable.c +++ b/gio/gcancellable.c @@ -13,9 +13,7 @@ * 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., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Author: Alexander Larsson */ @@ -92,16 +90,14 @@ g_cancellable_class_init (GCancellableClass *klass) * * Note that disconnecting from this signal (or any signal) in a * multi-threaded program is prone to race conditions. For instance - * it is possible that a signal handler may be invoked even - * after a call to - * g_signal_handler_disconnect() for that handler has already - * returned. + * it is possible that a signal handler may be invoked even after + * a call to g_signal_handler_disconnect() for that handler has + * already returned. * - * There is also a problem when cancellation happen - * right before connecting to the signal. If this happens the - * signal will unexpectedly not be emitted, and checking before - * connecting to the signal leaves a race condition where this is - * still happening. + * There is also a problem when cancellation happens right before + * connecting to the signal. If this happens the signal will + * unexpectedly not be emitted, and checking before connecting to + * the signal leaves a race condition where this is still happening. * * In order to make it safe and easy to connect handlers there * are two helper functions: g_cancellable_connect() and @@ -109,13 +105,13 @@ g_cancellable_class_init (GCancellableClass *klass) * like this. * * An example of how to us this: - * |[ - * /* Make sure we don't do any unnecessary work if already cancelled */ - * if (g_cancellable_set_error_if_cancelled (cancellable)) + * |[ + * // Make sure we don't do unnecessary work if already cancelled + * if (g_cancellable_set_error_if_cancelled (cancellable, error)) * return; * - * /* Set up all the data needed to be able to - * * handle cancellation of the operation */ + * // Set up all the data needed to be able to handle cancellation + * // of the operation * my_data = my_data_new (...); * * id = 0; @@ -124,12 +120,12 @@ g_cancellable_class_init (GCancellableClass *klass) * G_CALLBACK (cancelled_handler) * data, NULL); * - * /* cancellable operation here... */ + * // cancellable operation here... * * g_cancellable_disconnect (cancellable, id); * - * /* cancelled_handler is never called after this, it - * * is now safe to free the data */ + * // cancelled_handler is never called after this, it is now safe + * // to free the data * my_data_free (my_data); * ]| * @@ -225,8 +221,8 @@ g_cancellable_pop_current (GCancellable *cancellable) * * Gets the top cancellable from the stack. * - * Returns: (transfer none): a #GCancellable from the top of the stack, or %NULL - * if the stack is empty. + * Returns: (nullable) (transfer none): a #GCancellable from the top + * of the stack, or %NULL if the stack is empty. **/ GCancellable * g_cancellable_get_current (void) @@ -248,6 +244,13 @@ g_cancellable_get_current (void) * * If cancellable is currently in use by any cancellable operation * then the behavior of this function is undefined. + * + * Note that it is generally not a good idea to reuse an existing + * cancellable for more operations after it has been cancelled once, + * as this function might tempt you to do. The recommended practice + * is to drop the reference to a cancellable after cancelling it, + * and let it die with the outstanding async operations. You should + * create a fresh cancellable for further async operations. **/ void g_cancellable_reset (GCancellable *cancellable) @@ -535,6 +538,11 @@ g_cancellable_cancel (GCancellable *cancellable) * * See #GCancellable::cancelled for details on how to use this. * + * Since GLib 2.40, the lock protecting @cancellable is not held when + * @callback is invoked. This lifts a restriction in place for + * earlier GLib versions which now makes it easier to write cleanup + * code that unconditionally invokes e.g. g_cancellable_cancel(). + * * Returns: The id of the signal handler or 0 if @cancellable has already * been cancelled. * @@ -557,6 +565,8 @@ g_cancellable_connect (GCancellable *cancellable, void (*_callback) (GCancellable *cancellable, gpointer user_data); + g_mutex_unlock (&cancellable_mutex); + _callback = (void *)callback; id = 0; @@ -571,9 +581,10 @@ g_cancellable_connect (GCancellable *cancellable, callback, data, (GClosureNotify) data_destroy_func, 0); + + g_mutex_unlock (&cancellable_mutex); } - g_mutex_unlock (&cancellable_mutex); return id; } @@ -711,7 +722,9 @@ static GSourceFuncs cancellable_source_funcs = * For convenience, you can call this with a %NULL #GCancellable, * in which case the source will never trigger. * - * Return value: (transfer full): the new #GSource. + * The new #GSource will hold a reference to the #GCancellable. + * + * Returns: (transfer full): the new #GSource. * * Since: 2.28 */ @@ -728,11 +741,16 @@ g_cancellable_source_new (GCancellable *cancellable) if (cancellable) { cancellable_source->cancellable = g_object_ref (cancellable); + + /* We intentionally don't use g_cancellable_connect() here, + * because we don't want the "at most once" behavior. + */ cancellable_source->cancelled_handler = - g_cancellable_connect (cancellable, - G_CALLBACK (cancellable_source_cancelled), - source, - NULL); + g_signal_connect (cancellable, "cancelled", + G_CALLBACK (cancellable_source_cancelled), + source); + if (g_cancellable_is_cancelled (cancellable)) + g_source_set_ready_time (source, 0); } return source;