diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2011-12-20 21:53:23 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2011-12-20 21:53:23 +0000 |
commit | b7faf9bfa883fe32d6a73aae55e833e126dde62f (patch) | |
tree | 1d7bd4a0d307595a9b9c860a03e4bac85f04a5b4 | |
parent | bcced9de5f3fb427124848f61d06cd896a76aa88 (diff) | |
download | libgdata-b7faf9bfa883fe32d6a73aae55e833e126dde62f.tar.gz |
core: Don't use deprecated GLib threading API if we have a recent GLib
If we have GLib ≥ 2.31.0, use the new threading/mutex/condition variable API
to avoid deprecated function warnings.
Note that this doesn't bump our GLib dependency from 2.30.0; if a recent
enough GLib is not available, libgdata should still compile with the old
threading API.
-rw-r--r-- | gdata/gdata-buffer.c | 61 | ||||
-rw-r--r-- | gdata/gdata-buffer.h | 5 | ||||
-rw-r--r-- | gdata/gdata-client-login-authorizer.c | 68 | ||||
-rw-r--r-- | gdata/gdata-download-stream.c | 103 | ||||
-rw-r--r-- | gdata/gdata-oauth1-authorizer.c | 43 | ||||
-rw-r--r-- | gdata/gdata-service.c | 29 | ||||
-rw-r--r-- | gdata/gdata-upload-stream.c | 200 | ||||
-rw-r--r-- | gdata/tests/common.c | 2 | ||||
-rw-r--r-- | gdata/tests/memory.c | 2 | ||||
-rw-r--r-- | gdata/tests/perf.c | 2 | ||||
-rw-r--r-- | gdata/tests/streams.c | 37 |
11 files changed, 531 insertions, 21 deletions
diff --git a/gdata/gdata-buffer.c b/gdata/gdata-buffer.c index 3175ddec..d0292df5 100644 --- a/gdata/gdata-buffer.c +++ b/gdata/gdata-buffer.c @@ -55,8 +55,14 @@ GDataBuffer * gdata_buffer_new (void) { GDataBuffer *buffer = g_slice_new0 (GDataBuffer); + +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_init (&(buffer->mutex)); + g_cond_init (&(buffer->cond)); +#else g_static_mutex_init (&(buffer->mutex)); buffer->cond = g_cond_new (); +#endif return buffer; } @@ -82,8 +88,14 @@ gdata_buffer_free (GDataBuffer *self) g_free (chunk); } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_clear (&(self->cond)); + g_mutex_clear (&(self->mutex)); +#else g_cond_free (self->cond); g_static_mutex_free (&(self->mutex)); +#endif + g_slice_free (GDataBuffer, self); } @@ -113,18 +125,31 @@ gdata_buffer_push_data (GDataBuffer *self, const guint8 *data, gsize length) g_return_val_if_fail (self != NULL, 0); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(self->mutex)); +#else g_static_mutex_lock (&(self->mutex)); +#endif if (G_UNLIKELY (self->reached_eof == TRUE)) { /* If we're marked as having reached EOF, don't accept any more data */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(self->mutex)); +#else g_static_mutex_unlock (&(self->mutex)); +#endif return FALSE; } else if (G_UNLIKELY (data == NULL && length == 0)) { /* If @data is NULL and @length is 0, mark the buffer as having reached EOF, * and signal any waiting threads. */ self->reached_eof = TRUE; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_signal (&(self->cond)); + g_mutex_unlock (&(self->mutex)); +#else g_cond_signal (self->cond); g_static_mutex_unlock (&(self->mutex)); +#endif return FALSE; } @@ -147,9 +172,15 @@ gdata_buffer_push_data (GDataBuffer *self, const guint8 *data, gsize length) self->total_length += length; /* Signal any threads waiting to pop that data is available */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_signal (&(self->cond)); + + g_mutex_unlock (&(self->mutex)); +#else g_cond_signal (self->cond); g_static_mutex_unlock (&(self->mutex)); +#endif return TRUE; } @@ -163,10 +194,17 @@ static void pop_cancelled_cb (GCancellable *cancellable, CancelledData *data) { /* Signal the pop_data function that it should stop blocking and cancel */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(data->buffer->mutex)); + *(data->cancelled) = TRUE; + g_cond_signal (&(data->buffer->cond)); + g_mutex_unlock (&(data->buffer->mutex)); +#else g_static_mutex_lock (&(data->buffer->mutex)); *(data->cancelled) = TRUE; g_cond_signal (data->buffer->cond); g_static_mutex_unlock (&(data->buffer->mutex)); +#endif } /** @@ -227,7 +265,11 @@ gdata_buffer_pop_data (GDataBuffer *self, guint8 *data, gsize length_requested, cancelled_signal = g_cancellable_connect (cancellable, (GCallback) pop_cancelled_cb, &cancelled_data, NULL); } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(self->mutex)); +#else g_static_mutex_lock (&(self->mutex)); +#endif /* Set reached_eof */ if (reached_eof != NULL) @@ -240,8 +282,13 @@ gdata_buffer_pop_data (GDataBuffer *self, guint8 *data, gsize length_requested, /* Block until more data is available */ while (length_requested > self->total_length) { /* If we've already been cancelled, don't wait on @self->cond, since it'll never be signalled again. */ - if (cancelled == FALSE) + if (cancelled == FALSE) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_wait (&(self->cond), &(self->mutex)); +#else g_cond_wait (self->cond, g_static_mutex_get_mutex (&(self->mutex))); +#endif + } /* If the g_cond_wait() returned because it was signalled from the GCancellable callback (rather than from * data being pushed into the buffer), stop blocking for data and make do with what we have so far. */ @@ -303,7 +350,11 @@ gdata_buffer_pop_data (GDataBuffer *self, guint8 *data, gsize length_requested, self->total_length -= return_length; done: +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(self->mutex)); +#else g_static_mutex_unlock (&(self->mutex)); +#endif /* Disconnect from the cancelled signal. Note that this has to be done without @self->mutex held, or deadlock can occur. * (g_cancellable_disconnect() waits for any in-progress signal handler call to finish, which can't happen until the mutex is released.) */ @@ -337,10 +388,18 @@ gdata_buffer_pop_data_limited (GDataBuffer *self, guint8 *data, gsize maximum_le g_return_val_if_fail (maximum_length > 0, 0); /* If there's no data in the buffer, block until some is available */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(self->mutex)); + if (self->total_length == 0 && self->reached_eof == FALSE) { + g_cond_wait (&(self->cond), &(self->mutex)); + } + g_mutex_unlock (&(self->mutex)); +#else g_static_mutex_lock (&(self->mutex)); if (self->total_length == 0 && self->reached_eof == FALSE) g_cond_wait (self->cond, g_static_mutex_get_mutex (&(self->mutex))); g_static_mutex_unlock (&(self->mutex)); +#endif return gdata_buffer_pop_data (self, data, MIN (maximum_length, self->total_length), reached_eof, NULL); } diff --git a/gdata/gdata-buffer.h b/gdata/gdata-buffer.h index 306fae57..63299fc5 100644 --- a/gdata/gdata-buffer.h +++ b/gdata/gdata-buffer.h @@ -43,8 +43,13 @@ typedef struct { gboolean reached_eof; /* set to TRUE only once we've reached EOF */ GDataBufferChunk **tail; /* pointer to the GDataBufferChunk->next field of the current tail chunk */ +#if GLIB_CHECK_VERSION (2, 31, 0) + GMutex mutex; /* mutex protecting the entire structure on push and pop */ + GCond cond; /* a GCond to allow a popping thread to block on data being pushed into the buffer */ +#else GStaticMutex mutex; /* mutex protecting the entire structure on push and pop */ GCond *cond; /* a GCond to allow a popping thread to block on data being pushed into the buffer */ +#endif } GDataBuffer; GDataBuffer *gdata_buffer_new (void) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC; diff --git a/gdata/gdata-client-login-authorizer.c b/gdata/gdata-client-login-authorizer.c index 7f55248e..ad744210 100644 --- a/gdata/gdata-client-login-authorizer.c +++ b/gdata/gdata-client-login-authorizer.c @@ -127,7 +127,11 @@ struct _GDataClientLoginAuthorizerPrivate { /* Mutex for username, password and auth_tokens. It has to be recursive as the top-level authentication functions need to hold a lock on * auth_tokens while looping over it, but lower-level functions also need to modify auth_tokens to add the auth_tokens themselves once they're * returned by the online service. */ +#if GLIB_CHECK_VERSION (2, 31, 0) + GRecMutex mutex; +#else GStaticRecMutex mutex; +#endif gchar *username; GDataSecureString password; /* must be allocated by _gdata_service_secure_strdup() */ @@ -284,7 +288,11 @@ gdata_client_login_authorizer_init (GDataClientLoginAuthorizer *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_CLIENT_LOGIN_AUTHORIZER, GDataClientLoginAuthorizerPrivate); /* Set up the authentication mutex */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_init (&(self->priv->mutex)); +#else g_static_rec_mutex_init (&(self->priv->mutex)); +#endif self->priv->auth_tokens = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, (GDestroyNotify) _gdata_service_secure_strfree); /* Set up the session */ @@ -318,7 +326,11 @@ finalize (GObject *object) _gdata_service_secure_strfree (priv->password); g_free (priv->client_id); g_hash_table_destroy (priv->auth_tokens); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_clear (&(priv->mutex)); +#else g_static_rec_mutex_free (&(priv->mutex)); +#endif if (priv->proxy_uri != NULL) { soup_uri_free (priv->proxy_uri); @@ -338,15 +350,27 @@ get_property (GObject *object, guint property_id, GValue *value, GParamSpec *psp g_value_set_string (value, priv->client_id); break; case PROP_USERNAME: +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); + g_value_set_string (value, priv->username); + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); g_value_set_string (value, priv->username); g_static_rec_mutex_unlock (&(priv->mutex)); +#endif break; case PROP_PASSWORD: /* NOTE: This takes a pageable copy of non-pageable memory and thus could result in the password hitting disk. */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); + g_value_set_string (value, priv->password); + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); g_value_set_string (value, priv->password); g_static_rec_mutex_unlock (&(priv->mutex)); +#endif break; case PROP_PROXY_URI: g_value_set_boxed (value, gdata_client_login_authorizer_get_proxy_uri (GDATA_CLIENT_LOGIN_AUTHORIZER (object))); @@ -395,7 +419,11 @@ process_request (GDataAuthorizer *self, GDataAuthorizationDomain *domain, SoupMe } /* Set the authorisation header */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); +#endif auth_token = (GDataConstSecureString) g_hash_table_lookup (priv->auth_tokens, domain); @@ -415,7 +443,11 @@ process_request (GDataAuthorizer *self, GDataAuthorizationDomain *domain, SoupMe } } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_unlock (&(priv->mutex)); +#endif } static gboolean @@ -424,9 +456,15 @@ is_authorized_for_domain (GDataAuthorizer *self, GDataAuthorizationDomain *domai GDataClientLoginAuthorizerPrivate *priv = GDATA_CLIENT_LOGIN_AUTHORIZER (self)->priv; gpointer result; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); + result = g_hash_table_lookup (priv->auth_tokens, domain); + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); result = g_hash_table_lookup (priv->auth_tokens, domain); g_static_rec_mutex_unlock (&(priv->mutex)); +#endif return (result != NULL) ? TRUE : FALSE; } @@ -521,7 +559,11 @@ set_authentication_details (GDataClientLoginAuthorizer *self, const gchar *usern { GDataClientLoginAuthorizerPrivate *priv = self->priv; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); +#endif /* Ensure the username is always a full e-mail address */ g_free (priv->username); @@ -534,7 +576,11 @@ set_authentication_details (GDataClientLoginAuthorizer *self, const gchar *usern _gdata_service_secure_strfree (priv->password); priv->password = _gdata_service_secure_strdup (password); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_unlock (&(priv->mutex)); +#endif /* Notify of the property changes in the main thread; i.e. if we're running an async operation, schedule the notification in an idle * callback; but if we're running a sync operation, emit them immediately. @@ -574,9 +620,15 @@ parse_authentication_response (GDataClientLoginAuthorizer *self, GDataAuthorizat goto protocol_error; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); + g_hash_table_insert (priv->auth_tokens, g_object_ref (domain), auth_token); + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); g_hash_table_insert (priv->auth_tokens, g_object_ref (domain), auth_token); g_static_rec_mutex_unlock (&(priv->mutex)); +#endif return TRUE; @@ -892,7 +944,11 @@ authenticate_thread (GSimpleAsyncResult *result, GDataClientLoginAuthorizer *aut GDataAuthorizationDomain *domain; AuthenticateAsyncData *data = g_simple_async_result_get_op_res_gpointer (result); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); +#endif /* Authenticate and authorize against each of the services registered with the authorizer */ g_hash_table_iter_init (&iter, priv->auth_tokens); @@ -911,7 +967,11 @@ authenticate_thread (GSimpleAsyncResult *result, GDataClientLoginAuthorizer *aut g_clear_error (&authenticate_error); } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_unlock (&(priv->mutex)); +#endif /* Set or clear the authentication details and return now that we're done */ if (success == TRUE) { @@ -1045,7 +1105,11 @@ gdata_client_login_authorizer_authenticate (GDataClientLoginAuthorizer *self, co priv = self->priv; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_lock (&(priv->mutex)); +#else g_static_rec_mutex_lock (&(priv->mutex)); +#endif /* Authenticate and authorize against each of the services registered with the authorizer */ g_hash_table_iter_init (&iter, self->priv->auth_tokens); @@ -1054,7 +1118,11 @@ gdata_client_login_authorizer_authenticate (GDataClientLoginAuthorizer *self, co retval = authenticate (self, domain, username, password, NULL, NULL, cancellable, error) && retval; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_rec_mutex_unlock (&(priv->mutex)); +#else g_static_rec_mutex_unlock (&(priv->mutex)); +#endif /* Set or clear the authentication details */ if (retval == TRUE) { diff --git a/gdata/gdata-download-stream.c b/gdata/gdata-download-stream.c index ac14a858..a509e908 100644 --- a/gdata/gdata-download-stream.c +++ b/gdata/gdata-download-stream.c @@ -162,13 +162,22 @@ struct _GDataDownloadStreamPrivate { GCancellable *network_cancellable; /* see the comment in gdata_download_stream_constructor() about the relationship between these two */ gboolean finished; +#if GLIB_CHECK_VERSION (2, 31, 0) + GCond finished_cond; + GMutex finished_mutex; /* mutex for ->finished, protected by ->finished_cond */ +#else GCond *finished_cond; GStaticMutex finished_mutex; /* mutex for ->finished, protected by ->finished_cond */ +#endif /* Cached data from the SoupMessage */ gchar *content_type; gssize content_length; +#if GLIB_CHECK_VERSION (2, 31, 0) + GMutex content_mutex; /* mutex to protect them */ +#else GStaticMutex content_mutex; /* mutex to protect them */ +#endif }; enum { @@ -317,12 +326,21 @@ gdata_download_stream_init (GDataDownloadStream *self) self->priv->buffer = NULL; /* created when the network thread is started and destroyed when the stream is closed */ self->priv->finished = FALSE; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_init (&(self->priv->finished_cond)); + g_mutex_init (&(self->priv->finished_mutex)); +#else self->priv->finished_cond = g_cond_new (); g_static_mutex_init (&(self->priv->finished_mutex)); +#endif self->priv->content_type = NULL; self->priv->content_length = -1; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_init (&(self->priv->content_mutex)); +#else g_static_mutex_init (&(self->priv->content_mutex)); +#endif } static void @@ -409,10 +427,17 @@ gdata_download_stream_finalize (GObject *object) reset_network_thread (GDATA_DOWNLOAD_STREAM (object)); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_clear (&(priv->finished_cond)); + g_mutex_clear (&(priv->finished_mutex)); + + g_mutex_clear (&(priv->content_mutex)); +#else g_cond_free (priv->finished_cond); g_static_mutex_free (&(priv->finished_mutex)); g_static_mutex_free (&(priv->content_mutex)); +#endif g_free (priv->download_uri); g_free (priv->content_type); @@ -437,14 +462,26 @@ gdata_download_stream_get_property (GObject *object, guint property_id, GValue * g_value_set_string (value, priv->download_uri); break; case PROP_CONTENT_TYPE: +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->content_mutex)); + g_value_set_string (value, priv->content_type); + g_mutex_unlock (&(priv->content_mutex)); +#else g_static_mutex_lock (&(priv->content_mutex)); g_value_set_string (value, priv->content_type); g_static_mutex_unlock (&(priv->content_mutex)); +#endif break; case PROP_CONTENT_LENGTH: +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->content_mutex)); + g_value_set_long (value, priv->content_length); + g_mutex_unlock (&(priv->content_mutex)); +#else g_static_mutex_lock (&(priv->content_mutex)); g_value_set_long (value, priv->content_length); g_static_mutex_unlock (&(priv->content_mutex)); +#endif break; case PROP_CANCELLABLE: g_value_set_object (value, priv->cancellable); @@ -580,10 +617,17 @@ close_cancelled_cb (GCancellable *cancellable, CancelledData *data) { GDataDownloadStreamPrivate *priv = data->download_stream->priv; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->finished_mutex)); + *(data->cancelled) = TRUE; + g_cond_signal (&(priv->finished_cond)); + g_mutex_unlock (&(priv->finished_mutex)); +#else g_static_mutex_lock (&(priv->finished_mutex)); *(data->cancelled) = TRUE; g_cond_signal (priv->finished_cond); g_static_mutex_unlock (&(priv->finished_mutex)); +#endif } /* Even though calling g_input_stream_close() multiple times on this stream is guaranteed to call gdata_download_stream_close() at most once, other @@ -623,7 +667,11 @@ gdata_download_stream_close (GInputStream *stream, GCancellable *cancellable, GE if (cancellable != NULL) cancelled_signal = g_cancellable_connect (cancellable, (GCallback) close_cancelled_cb, &data, NULL); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->finished_mutex)); +#else g_static_mutex_lock (&(priv->finished_mutex)); +#endif /* If the operation has started but hasn't already finished, cancel the network thread and wait for it to finish before returning */ if (priv->finished == FALSE) { @@ -631,8 +679,13 @@ gdata_download_stream_close (GInputStream *stream, GCancellable *cancellable, GE /* Allow the close() call to be cancelled by cancelling either @cancellable or ->cancellable. Note that this won't prevent the stream * from continuing to be closed in the background — it'll just stop waiting on the operation to finish being cancelled. */ - if (cancelled == FALSE) + if (cancelled == FALSE) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_wait (&(priv->finished_cond), &(priv->finished_mutex)); +#else g_cond_wait (priv->finished_cond, g_static_mutex_get_mutex (&(priv->finished_mutex))); +#endif + } } /* Error handling */ @@ -644,7 +697,11 @@ gdata_download_stream_close (GInputStream *stream, GCancellable *cancellable, GE success = FALSE; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->finished_mutex)); +#else g_static_mutex_unlock (&(priv->finished_mutex)); +#endif /* Disconnect from the signal handlers. Note that we have to do this without @finished_mutex held, as g_cancellable_disconnect() blocks * until any outstanding cancellation callbacks return, and they will block on @finished_mutex. */ @@ -655,13 +712,21 @@ gdata_download_stream_close (GInputStream *stream, GCancellable *cancellable, GE done: /* If we were successful, tidy up various bits of state */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->finished_mutex)); +#else g_static_mutex_lock (&(priv->finished_mutex)); +#endif if (success == TRUE && priv->finished == TRUE) { reset_network_thread (GDATA_DOWNLOAD_STREAM (stream)); } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->finished_mutex)); +#else g_static_mutex_unlock (&(priv->finished_mutex)); +#endif g_assert ((success == TRUE && child_error == NULL) || (success == FALSE && child_error != NULL)); @@ -769,9 +834,15 @@ gdata_download_stream_seek (GSeekable *seekable, goffset offset, GSeekType type, priv->offset = offset; /* Mark the thread as unfinished */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->finished_mutex)); + priv->finished = FALSE; + g_mutex_unlock (&(priv->finished_mutex)); +#else g_static_mutex_lock (&(priv->finished_mutex)); priv->finished = FALSE; g_static_mutex_unlock (&(priv->finished_mutex)); +#endif goto done; } @@ -808,10 +879,17 @@ got_headers_cb (SoupMessage *message, GDataDownloadStream *self) if (SOUP_STATUS_IS_SUCCESSFUL (message->status_code) == FALSE) return; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(self->priv->content_mutex)); + self->priv->content_type = g_strdup (soup_message_headers_get_content_type (message->response_headers, NULL)); + self->priv->content_length = soup_message_headers_get_content_length (message->response_headers); + g_mutex_unlock (&(self->priv->content_mutex)); +#else g_static_mutex_lock (&(self->priv->content_mutex)); self->priv->content_type = g_strdup (soup_message_headers_get_content_type (message->response_headers, NULL)); self->priv->content_length = soup_message_headers_get_content_length (message->response_headers); g_static_mutex_unlock (&(self->priv->content_mutex)); +#endif /* Emit the notifications for the Content-Length and -Type properties */ g_object_freeze_notify (G_OBJECT (self)); @@ -859,10 +937,17 @@ download_thread (GDataDownloadStream *self) gdata_buffer_push_data (priv->buffer, NULL, 0); /* Mark the download as finished */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->finished_mutex)); + priv->finished = TRUE; + g_cond_signal (&(priv->finished_cond)); + g_mutex_unlock (&(priv->finished_mutex)); +#else g_static_mutex_lock (&(priv->finished_mutex)); priv->finished = TRUE; g_cond_signal (priv->finished_cond); g_static_mutex_unlock (&(priv->finished_mutex)); +#endif g_object_unref (self); @@ -878,7 +963,11 @@ create_network_thread (GDataDownloadStream *self, GError **error) priv->buffer = gdata_buffer_new (); g_assert (priv->network_thread == NULL); +#if GLIB_CHECK_VERSION (2, 31, 0) + priv->network_thread = g_thread_try_new ("download-thread", (GThreadFunc) download_thread, self, error); +#else priv->network_thread = g_thread_create ((GThreadFunc) download_thread, self, TRUE, error); +#endif } static void @@ -1012,9 +1101,15 @@ gdata_download_stream_get_content_type (GDataDownloadStream *self) g_return_val_if_fail (GDATA_IS_DOWNLOAD_STREAM (self), NULL); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(self->priv->content_mutex)); + content_type = self->priv->content_type; + g_mutex_unlock (&(self->priv->content_mutex)); +#else g_static_mutex_lock (&(self->priv->content_mutex)); content_type = self->priv->content_type; g_static_mutex_unlock (&(self->priv->content_mutex)); +#endif /* It's safe to return this, even though we're not taking a copy of it, as it's immutable once set. */ return content_type; @@ -1038,9 +1133,15 @@ gdata_download_stream_get_content_length (GDataDownloadStream *self) g_return_val_if_fail (GDATA_IS_DOWNLOAD_STREAM (self), -1); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(self->priv->content_mutex)); + content_length = self->priv->content_length; + g_mutex_unlock (&(self->priv->content_mutex)); +#else g_static_mutex_lock (&(self->priv->content_mutex)); content_length = self->priv->content_length; g_static_mutex_unlock (&(self->priv->content_mutex)); +#endif g_assert (content_length >= -1); diff --git a/gdata/gdata-oauth1-authorizer.c b/gdata/gdata-oauth1-authorizer.c index 4b56c41c..bd34272d 100644 --- a/gdata/gdata-oauth1-authorizer.c +++ b/gdata/gdata-oauth1-authorizer.c @@ -169,7 +169,11 @@ struct _GDataOAuth1AuthorizerPrivate { gchar *application_name; gchar *locale; +#if GLIB_CHECK_VERSION (2, 31, 0) + GMutex mutex; /* mutex for token, token_secret and authorization_domains */ +#else GStaticMutex mutex; /* mutex for token, token_secret and authorization_domains */ +#endif /* Note: This is the access token, not the request token returned by gdata_oauth1_authorizer_request_authentication_uri(). * It's NULL iff the authorizer isn't authenticated. token_secret must be NULL iff token is NULL. */ @@ -281,7 +285,11 @@ gdata_oauth1_authorizer_init (GDataOAuth1Authorizer *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_OAUTH1_AUTHORIZER, GDataOAuth1AuthorizerPrivate); /* Set up the authorizer's mutex */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_init (&(self->priv->mutex)); +#else g_static_mutex_init (&(self->priv->mutex)); +#endif self->priv->authorization_domains = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); /* Set up the session */ @@ -314,7 +322,11 @@ finalize (GObject *object) g_free (priv->locale); g_hash_table_destroy (priv->authorization_domains); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_clear (&(priv->mutex)); +#else g_static_mutex_free (&(priv->mutex)); +#endif if (priv->proxy_uri != NULL) { soup_uri_free (priv->proxy_uri); @@ -391,7 +403,11 @@ process_request (GDataAuthorizer *self, GDataAuthorizationDomain *domain, SoupMe GDataOAuth1AuthorizerPrivate *priv = GDATA_OAUTH1_AUTHORIZER (self)->priv; /* Set the authorisation header */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->mutex)); +#else g_static_mutex_lock (&(priv->mutex)); +#endif /* Sanity check */ g_assert ((priv->token == NULL) == (priv->token_secret == NULL)); @@ -400,7 +416,11 @@ process_request (GDataAuthorizer *self, GDataAuthorizationDomain *domain, SoupMe sign_message (GDATA_OAUTH1_AUTHORIZER (self), message, priv->token, priv->token_secret, NULL); } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->mutex)); +#else g_static_mutex_unlock (&(priv->mutex)); +#endif } static gboolean @@ -410,10 +430,17 @@ is_authorized_for_domain (GDataAuthorizer *self, GDataAuthorizationDomain *domai gpointer result; const gchar *token; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->mutex)); + token = priv->token; + result = g_hash_table_lookup (priv->authorization_domains, domain); + g_mutex_unlock (&(priv->mutex)); +#else g_static_mutex_lock (&(priv->mutex)); token = priv->token; result = g_hash_table_lookup (priv->authorization_domains, domain); g_static_mutex_unlock (&(priv->mutex)); +#endif /* Sanity check */ g_assert (result == NULL || result == domain); @@ -730,7 +757,11 @@ gdata_oauth1_authorizer_request_authentication_uri (GDataOAuth1Authorizer *self, *token_secret = NULL; /* Build up the space-separated list of scopes we're requesting authorisation for */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->mutex)); +#else g_static_mutex_lock (&(priv->mutex)); +#endif scope_string = g_string_new (NULL); g_hash_table_iter_init (&iter, priv->authorization_domains); @@ -746,7 +777,11 @@ gdata_oauth1_authorizer_request_authentication_uri (GDataOAuth1Authorizer *self, is_first = FALSE; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->mutex)); +#else g_static_mutex_unlock (&(priv->mutex)); +#endif /* Build the request body and the set of parameters to be signed */ parameters = g_hash_table_new (g_str_hash, g_str_equal); @@ -1080,7 +1115,11 @@ gdata_oauth1_authorizer_request_authorization (GDataOAuth1Authorizer *self, cons } /* Store the token and token secret in the authoriser */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->mutex)); +#else g_static_mutex_lock (&(priv->mutex)); +#endif g_free (priv->token); priv->token = g_strdup (_token); @@ -1088,7 +1127,11 @@ gdata_oauth1_authorizer_request_authorization (GDataOAuth1Authorizer *self, cons _gdata_service_secure_strfree (priv->token_secret); priv->token_secret = _gdata_service_secure_strdup (_token_secret); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->mutex)); +#else g_static_mutex_unlock (&(priv->mutex)); +#endif /* Zero out the secret token before freeing the hash table, to reduce the chance of it hitting disk later. */ memset ((void*) _token_secret, 0, strlen (_token_secret)); diff --git a/gdata/gdata-service.c b/gdata/gdata-service.c index c5ce2623..93ac8fb8 100644 --- a/gdata/gdata-service.c +++ b/gdata/gdata-service.c @@ -555,7 +555,11 @@ _gdata_service_build_message (GDataService *self, GDataAuthorizationDomain *doma } typedef struct { +#if GLIB_CHECK_VERSION (2, 31, 0) + GMutex mutex; /* mutex to prevent cancellation before the message has been added to the session's message queue */ +#else GStaticMutex mutex; /* mutex to prevent cancellation before the message has been added to the session's message queue */ +#endif SoupSession *session; SoupMessage *message; } MessageData; @@ -563,16 +567,27 @@ typedef struct { static void message_cancel_cb (GCancellable *cancellable, MessageData *data) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(data->mutex)); + soup_session_cancel_message (data->session, data->message, SOUP_STATUS_CANCELLED); + g_mutex_unlock (&(data->mutex)); +#else g_static_mutex_lock (&(data->mutex)); soup_session_cancel_message (data->session, data->message, SOUP_STATUS_CANCELLED); g_static_mutex_unlock (&(data->mutex)); +#endif } static void message_request_queued_cb (SoupSession *session, SoupMessage *message, MessageData *data) { - if (message == data->message) + if (message == data->message) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(data->mutex)); +#else g_static_mutex_unlock (&(data->mutex)); +#endif + } } /* Synchronously send @message via @service, handling asynchronous cancellation as best we can. If @cancellable has been cancelled before we start @@ -594,7 +609,11 @@ _gdata_service_actually_send_message (SoupSession *session, SoupMessage *message /* Listen for cancellation */ if (cancellable != NULL) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_init (&(data.mutex)); +#else g_static_mutex_init (&(data.mutex)); +#endif data.session = session; data.message = message; @@ -607,7 +626,11 @@ _gdata_service_actually_send_message (SoupSession *session, SoupMessage *message * This is a little ugly, but is the only way I can think of to avoid a race condition between calling soup_session_cancel_message() * and soup_session_send_message(), as the former doesn't have any effect until the request has been queued, and once the latter has * returned, all network activity has been finished so cancellation is pointless. */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(data.mutex)); +#else g_static_mutex_lock (&(data.mutex)); +#endif } /* Only send the message if it hasn't already been cancelled. There is no race condition here for the above reasons: if the cancellable has @@ -627,7 +650,11 @@ _gdata_service_actually_send_message (SoupSession *session, SoupMessage *message if (cancel_signal != 0) g_cancellable_disconnect (cancellable, cancel_signal); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_clear (&(data.mutex)); +#else g_static_mutex_free (&(data.mutex)); +#endif } /* Set the cancellation error if applicable. We can't assume that our GCancellable has been cancelled just because the message has; diff --git a/gdata/gdata-upload-stream.c b/gdata/gdata-upload-stream.c index e636bdf5..079cab65 100644 --- a/gdata/gdata-upload-stream.c +++ b/gdata/gdata-upload-stream.c @@ -202,17 +202,33 @@ struct _GDataUploadStreamPrivate { GCancellable *cancellable; GThread *network_thread; +#if GLIB_CHECK_VERSION (2, 31, 0) + GMutex write_mutex; /* mutex for write operations (specifically, write_finished) */ +#else GStaticMutex write_mutex; /* mutex for write operations (specifically, write_finished) */ +#endif gsize message_bytes_outstanding; /* the number of bytes which have been written to the buffer but not libsoup (signalled by write_cond) */ gsize network_bytes_outstanding; /* the number of bytes which have been written to libsoup but not the network (signalled by write_cond) */ gsize network_bytes_written; /* the number of bytes which have been written to the network (signalled by write_cond) */ +#if GLIB_CHECK_VERSION (2, 31, 0) + GCond write_cond; /* signalled when a chunk has been written (protected by write_mutex) */ +#else GCond *write_cond; /* signalled when a chunk has been written (protected by write_mutex) */ +#endif gboolean finished; /* set once the upload thread has finished (protected by response_mutex) */ guint response_status; /* set once we finish receiving the response (SOUP_STATUS_NONE otherwise) (protected by response_mutex) */ +#if GLIB_CHECK_VERSION (2, 31, 0) + GCond finished_cond; /* signalled when sending the message (and receiving the response) is finished (protected by response_mutex) */ +#else GCond *finished_cond; /* signalled when sending the message (and receiving the response) is finished (protected by response_mutex) */ +#endif GError *response_error; /* error asynchronously set by the network thread, and picked up by the main thread when appropriate */ +#if GLIB_CHECK_VERSION (2, 31, 0) + GMutex response_mutex; /* mutex for ->response_error, ->response_status and ->finished_cond */ +#else GStaticMutex response_mutex; /* mutex for ->response_error, ->response_status and ->finished_cond */ +#endif }; enum { @@ -367,10 +383,17 @@ gdata_upload_stream_init (GDataUploadStream *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_UPLOAD_STREAM, GDataUploadStreamPrivate); self->priv->buffer = gdata_buffer_new (); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_init (&(self->priv->write_mutex)); + g_cond_init (&(self->priv->write_cond)); + g_cond_init (&(self->priv->finished_cond)); + g_mutex_init (&(self->priv->response_mutex)); +#else g_static_mutex_init (&(self->priv->write_mutex)); self->priv->write_cond = g_cond_new (); self->priv->finished_cond = g_cond_new (); g_static_mutex_init (&(self->priv->response_mutex)); +#endif } static GObject * @@ -459,10 +482,17 @@ gdata_upload_stream_finalize (GObject *object) { GDataUploadStreamPrivate *priv = GDATA_UPLOAD_STREAM (object)->priv; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_clear (&(priv->response_mutex)); + g_cond_clear (&(priv->finished_cond)); + g_cond_clear (&(priv->write_cond)); + g_mutex_clear (&(priv->write_mutex)); +#else g_static_mutex_free (&(priv->response_mutex)); g_cond_free (priv->finished_cond); g_cond_free (priv->write_cond); g_static_mutex_free (&(priv->write_mutex)); +#endif gdata_buffer_free (priv->buffer); g_clear_error (&(priv->response_error)); g_free (priv->upload_uri); @@ -561,10 +591,17 @@ write_cancelled_cb (GCancellable *cancellable, CancelledData *data) GDataUploadStreamPrivate *priv = data->upload_stream->priv; /* Signal the gdata_upload_stream_write() function that it should stop blocking and cancel */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + *(data->cancelled) = TRUE; + g_cond_signal (&(priv->write_cond)); + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); *(data->cancelled) = TRUE; g_cond_signal (priv->write_cond); g_static_mutex_unlock (&(priv->write_mutex)); +#endif } static gssize @@ -587,12 +624,20 @@ gdata_upload_stream_write (GOutputStream *stream, const void *buffer, gsize coun cancelled_signal = g_cancellable_connect (cancellable, (GCallback) write_cancelled_cb, &data, NULL); /* Check for an error and return if necessary */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); +#endif if (cancelled == TRUE) { g_assert (g_cancellable_set_error_if_cancelled (cancellable, error) == TRUE || g_cancellable_set_error_if_cancelled (priv->cancellable, error) == TRUE); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_unlock (&(priv->write_mutex)); +#endif length_written = -1; goto done; @@ -603,7 +648,11 @@ gdata_upload_stream_write (GOutputStream *stream, const void *buffer, gsize coun old_network_bytes_written = priv->network_bytes_written; priv->message_bytes_outstanding += count; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_unlock (&(priv->write_mutex)); +#endif /* Handle the more common case of the network thread already having been created first */ if (priv->network_thread != NULL) { @@ -629,9 +678,15 @@ gdata_upload_stream_write (GOutputStream *stream, const void *buffer, gsize coun soup_message_body_append (priv->message->request_body, SOUP_MEMORY_TAKE, entry_xml, strlen (entry_xml)); soup_message_body_append (priv->message->request_body, SOUP_MEMORY_TAKE, second_part_header, strlen (second_part_header)); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + priv->network_bytes_outstanding += priv->message->request_body->length; + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); priv->network_bytes_outstanding += priv->message->request_body->length; g_static_mutex_unlock (&(priv->write_mutex)); +#endif } /* Also write out the first chunk of data, so there's guaranteed to be something in the buffer */ @@ -645,11 +700,20 @@ gdata_upload_stream_write (GOutputStream *stream, const void *buffer, gsize coun } write: +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); +#endif /* Wait for it to be written */ - while (priv->network_bytes_written - old_network_bytes_written < count && cancelled == FALSE) + while (priv->network_bytes_written - old_network_bytes_written < count && cancelled == FALSE) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_wait (&(priv->write_cond), &(priv->write_mutex)); +#else g_cond_wait (priv->write_cond, g_static_mutex_get_mutex (&(priv->write_mutex))); +#endif + } length_written = MIN (count, priv->network_bytes_written - old_network_bytes_written); /* Check for an error and return if necessary */ @@ -659,7 +723,11 @@ write: length_written = -1; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_unlock (&(priv->write_mutex)); +#endif done: /* Disconnect from the cancelled signals. Note that we have to do this with @write_mutex not held, as g_cancellable_disconnect() blocks @@ -680,10 +748,17 @@ flush_cancelled_cb (GCancellable *cancellable, CancelledData *data) GDataUploadStreamPrivate *priv = data->upload_stream->priv; /* Signal the gdata_upload_stream_flush() function that it should stop blocking and cancel */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + *(data->cancelled) = TRUE; + g_cond_signal (&(priv->write_cond)); + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); *(data->cancelled) = TRUE; g_cond_signal (priv->write_cond); g_static_mutex_unlock (&(priv->write_mutex)); +#endif } /* Block until ->network_bytes_outstanding reaches zero. Cancelling the cancellable passed to gdata_upload_stream_flush() breaks out of the wait(), @@ -710,11 +785,20 @@ gdata_upload_stream_flush (GOutputStream *stream, GCancellable *cancellable, GEr cancelled_signal = g_cancellable_connect (cancellable, (GCallback) flush_cancelled_cb, &data, NULL); /* Start the flush operation proper */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); +#endif /* Wait for all outstanding bytes to be written to the network */ - while (priv->network_bytes_outstanding > 0 && cancelled == FALSE) + while (priv->network_bytes_outstanding > 0 && cancelled == FALSE) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_wait (&(priv->write_cond), &(priv->write_mutex)); +#else g_cond_wait (priv->write_cond, g_static_mutex_get_mutex (&(priv->write_mutex))); +#endif + } /* Check for an error and return if necessary */ if (cancelled == TRUE) { @@ -723,7 +807,11 @@ gdata_upload_stream_flush (GOutputStream *stream, GCancellable *cancellable, GEr success = FALSE; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_unlock (&(priv->write_mutex)); +#endif /* Disconnect from the cancelled signals. Note that we have to do this without @write_mutex held, as g_cancellable_disconnect() blocks * until any outstanding cancellation callbacks return, and they will block on @write_mutex. */ @@ -741,10 +829,17 @@ close_cancelled_cb (GCancellable *cancellable, CancelledData *data) GDataUploadStreamPrivate *priv = data->upload_stream->priv; /* Signal the gdata_upload_stream_close() function that it should stop blocking and cancel */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->response_mutex)); + *(data->cancelled) = TRUE; + g_cond_signal (&(priv->finished_cond)); + g_mutex_unlock (&(priv->response_mutex)); +#else g_static_mutex_lock (&(priv->response_mutex)); *(data->cancelled) = TRUE; g_cond_signal (priv->finished_cond); g_static_mutex_unlock (&(priv->response_mutex)); +#endif } /* It's guaranteed that we have set ->response_status and ->response_error and are done with *all* network activity before this returns, unless it's @@ -779,13 +874,27 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr return TRUE; /* If we've already closed the stream, return G_IO_ERROR_CLOSED */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->response_mutex)); +#else g_static_mutex_lock (&(priv->response_mutex)); +#endif + if (priv->response_status != SOUP_STATUS_NONE) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->response_mutex)); +#else g_static_mutex_unlock (&(priv->response_mutex)); +#endif g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, _("Stream is already closed")); return FALSE; } + +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->response_mutex)); +#else g_static_mutex_unlock (&(priv->response_mutex)); +#endif /* Allow cancellation */ data.upload_stream = GDATA_UPLOAD_STREAM (stream); @@ -796,7 +905,11 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr if (cancellable != NULL) cancelled_signal = g_cancellable_connect (cancellable, (GCallback) close_cancelled_cb, &data, NULL); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->response_mutex)); +#else g_static_mutex_lock (&(priv->response_mutex)); +#endif /* If an operation is still in progress, the upload thread hasn't finished yet… */ if (priv->finished == FALSE) { @@ -807,9 +920,15 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr gdata_buffer_push_data (priv->buffer, (const guint8*) footer, footer_length); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + priv->message_bytes_outstanding += footer_length; + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); priv->message_bytes_outstanding += footer_length; g_static_mutex_unlock (&(priv->write_mutex)); +#endif } /* Mark the buffer as having reached EOF, and the write operation will close in its own time */ @@ -818,8 +937,13 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr /* Wait for the signal that we've finished. Cancelling the call to gdata_upload_stream_close() will cause this wait to be aborted, * but won't actually prevent the stream being closed (i.e. all it means is that the stream isn't guaranteed to have been closed by * the time gdata_upload_stream_close() returns — whereas normally it would be). */ - if (cancelled == FALSE) + if (cancelled == FALSE) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_wait (&(priv->finished_cond), &(priv->response_mutex)); +#else g_cond_wait (priv->finished_cond, g_static_mutex_get_mutex (&(priv->response_mutex))); +#endif + } } g_assert (priv->response_status == SOUP_STATUS_NONE); @@ -849,7 +973,11 @@ gdata_upload_stream_close (GOutputStream *stream, GCancellable *cancellable, GEr g_assert (priv->response_status != SOUP_STATUS_NONE && (SOUP_STATUS_IS_SUCCESSFUL (priv->response_status) || child_error != NULL)); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->response_mutex)); +#else g_static_mutex_unlock (&(priv->response_mutex)); +#endif /* Disconnect from the signal handler. Note that we have to do this with @response_mutex not held, as g_cancellable_disconnect() blocks * until any outstanding cancellation callbacks return, and they will block on @response_mutex. */ @@ -884,15 +1012,27 @@ write_next_chunk (GDataUploadStream *self, SoupMessage *message) gboolean reached_eof = FALSE; guint8 next_buffer[CHUNK_SIZE]; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); +#endif /* If there are still bytes in libsoup's buffer, don't block on getting new bytes into the stream */ if (priv->network_bytes_outstanding > 0) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_unlock (&(priv->write_mutex)); +#endif return; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_unlock (&(priv->write_mutex)); +#endif /* Append the next chunk to the message body so it can join in the fun. * Note that this call isn't blocking, and can return less than the CHUNK_SIZE. This is because @@ -901,10 +1041,17 @@ write_next_chunk (GDataUploadStream *self, SoupMessage *message) * stream, so we'd happily block on receiving more bytes which weren't forthcoming. */ length = gdata_buffer_pop_data_limited (priv->buffer, next_buffer, CHUNK_SIZE, &reached_eof); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + priv->message_bytes_outstanding -= length; + priv->network_bytes_outstanding += length; + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); priv->message_bytes_outstanding -= length; priv->network_bytes_outstanding += length; g_static_mutex_unlock (&(priv->write_mutex)); +#endif /* Append whatever data was returned */ if (length > 0) @@ -912,9 +1059,15 @@ write_next_chunk (GDataUploadStream *self, SoupMessage *message) /* Finish off the request body if we've reached EOF (i.e. the stream has been closed) */ if (reached_eof == TRUE) { +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + g_assert (priv->message_bytes_outstanding == 0); + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); g_assert (priv->message_bytes_outstanding == 0); g_static_mutex_unlock (&(priv->write_mutex)); +#endif soup_message_body_complete (priv->message->request_body); } @@ -928,9 +1081,15 @@ wrote_headers_cb (SoupMessage *message, GDataUploadStream *self) GDataUploadStreamPrivate *priv = self->priv; /* Signal the main thread that the headers have been written */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + g_cond_signal (&(priv->write_cond)); + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); g_cond_signal (priv->write_cond); g_static_mutex_unlock (&(priv->write_mutex)); +#endif /* Send the first chunk to libsoup */ write_next_chunk (self, message); @@ -942,12 +1101,21 @@ wrote_body_data_cb (SoupMessage *message, SoupBuffer *buffer, GDataUploadStream GDataUploadStreamPrivate *priv = self->priv; /* Signal the main thread that the chunk has been written */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->write_mutex)); + g_assert (priv->network_bytes_outstanding > 0); + priv->network_bytes_outstanding -= buffer->length; + priv->network_bytes_written += buffer->length; + g_cond_signal (&(priv->write_cond)); + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->write_mutex)); g_assert (priv->network_bytes_outstanding > 0); priv->network_bytes_outstanding -= buffer->length; priv->network_bytes_written += buffer->length; g_cond_signal (priv->write_cond); g_static_mutex_unlock (&(priv->write_mutex)); +#endif /* Send the next chunk to libsoup */ write_next_chunk (self, message); @@ -969,16 +1137,30 @@ upload_thread (GDataUploadStream *self) _gdata_service_actually_send_message (priv->session, priv->message, priv->cancellable, NULL); /* Signal write_cond, just in case we errored out and finished sending in the middle of a write */ +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(priv->response_mutex)); + g_mutex_lock (&(priv->write_mutex)); + if (priv->message_bytes_outstanding > 0 || priv->network_bytes_outstanding > 0) { + g_cond_signal (&(priv->write_cond)); + } + g_mutex_unlock (&(priv->write_mutex)); +#else g_static_mutex_lock (&(priv->response_mutex)); g_static_mutex_lock (&(priv->write_mutex)); if (priv->message_bytes_outstanding > 0 || priv->network_bytes_outstanding > 0) g_cond_signal (priv->write_cond); g_static_mutex_unlock (&(priv->write_mutex)); +#endif /* Signal that the operation has finished */ priv->finished = TRUE; +#if GLIB_CHECK_VERSION (2, 31, 0) + g_cond_signal (&(priv->finished_cond)); + g_mutex_unlock (&(priv->response_mutex)); +#else g_cond_signal (priv->finished_cond); g_static_mutex_unlock (&(priv->response_mutex)); +#endif g_object_unref (self); @@ -991,7 +1173,11 @@ create_network_thread (GDataUploadStream *self, GError **error) GDataUploadStreamPrivate *priv = self->priv; g_assert (priv->network_thread == NULL); +#if GLIB_CHECK_VERSION (2, 31, 0) + priv->network_thread = g_thread_try_new ("upload-thread", (GThreadFunc) upload_thread, self, error); +#else priv->network_thread = g_thread_create ((GThreadFunc) upload_thread, self, TRUE, error); +#endif } /** @@ -1088,7 +1274,11 @@ gdata_upload_stream_get_response (GDataUploadStream *self, gssize *length) g_return_val_if_fail (GDATA_IS_UPLOAD_STREAM (self), NULL); +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_lock (&(self->priv->response_mutex)); +#else g_static_mutex_lock (&(self->priv->response_mutex)); +#endif if (self->priv->response_status == SOUP_STATUS_NONE) { /* We can't touch the message until the network thread has finished using it, since it isn't threadsafe */ @@ -1104,7 +1294,11 @@ gdata_upload_stream_get_response (GDataUploadStream *self, gssize *length) _response = self->priv->message->response_body->data; } +#if GLIB_CHECK_VERSION (2, 31, 0) + g_mutex_unlock (&(self->priv->response_mutex)); +#else g_static_mutex_unlock (&(self->priv->response_mutex)); +#endif if (length != NULL) *length = _length; diff --git a/gdata/tests/common.c b/gdata/tests/common.c index feacd994..22e2a8ae 100644 --- a/gdata/tests/common.c +++ b/gdata/tests/common.c @@ -38,7 +38,9 @@ gdata_test_init (int argc, char **argv) gint i; g_type_init (); +#if !GLIB_CHECK_VERSION (2, 31, 0) g_thread_init (NULL); +#endif /* Parse the --no-internet and --no-interactive options */ for (i = 1; i < argc; i++) { diff --git a/gdata/tests/memory.c b/gdata/tests/memory.c index 67bbb4ad..81b1f83d 100644 --- a/gdata/tests/memory.c +++ b/gdata/tests/memory.c @@ -65,7 +65,9 @@ main (int argc, char *argv[]) g_mem_set_vtable (glib_mem_profiler_table); g_type_init (); +#if !GLIB_CHECK_VERSION (2, 31, 0) g_thread_init (NULL); +#endif test_query_events (); diff --git a/gdata/tests/perf.c b/gdata/tests/perf.c index a783e188..eab1edc2 100644 --- a/gdata/tests/perf.c +++ b/gdata/tests/perf.c @@ -84,7 +84,9 @@ main (int argc, char *argv[]) #define ITERATIONS 10000 g_type_init (); +#if !GLIB_CHECK_VERSION (2, 31, 0) g_thread_init (NULL); +#endif /* Test feed parsing time */ g_get_current_time (&start_time); diff --git a/gdata/tests/streams.c b/gdata/tests/streams.c index ae8300d1..ef16e6de 100644 --- a/gdata/tests/streams.c +++ b/gdata/tests/streams.c @@ -32,6 +32,23 @@ run_server_thread (SoupServer *server) return NULL; } +static GThread * +run_server (SoupServer *server) +{ + GThread *thread; + GError *error = NULL; + +#if GLIB_CHECK_VERSION (2, 31, 0) + thread = g_thread_try_new ("server-thread", (GThreadFunc) run_server_thread, server, &error); +#else + thread = g_thread_create ((GThreadFunc) run_server_thread, server, TRUE, &error); +#endif + g_assert_no_error (error); + g_assert (thread != NULL); + + return thread; +} + static gboolean quit_server_cb (SoupServer *server) { @@ -104,9 +121,7 @@ test_download_stream_download_content_length (void) g_assert (server != NULL); /* Create a thread for the server */ - thread = g_thread_create ((GThreadFunc) run_server_thread, server, TRUE, &error); - g_assert_no_error (error); - g_assert (thread != NULL); + thread = run_server (server); /* Create a new download stream connected to the server */ download_uri = g_strdup_printf ("http://127.0.0.1:%u/", soup_server_get_port (server)); @@ -199,9 +214,7 @@ test_download_stream_download_seek_before_start (void) g_assert (server != NULL); /* Create a thread for the server */ - thread = g_thread_create ((GThreadFunc) run_server_thread, server, TRUE, &error); - g_assert_no_error (error); - g_assert (thread != NULL); + thread = run_server (server); /* Create a new download stream connected to the server */ download_uri = g_strdup_printf ("http://127.0.0.1:%u/", soup_server_get_port (server)); @@ -304,9 +317,7 @@ test_download_stream_download_seek_after_start_forwards (void) g_assert (server != NULL); /* Create a thread for the server */ - thread = g_thread_create ((GThreadFunc) run_server_thread, server, TRUE, &error); - g_assert_no_error (error); - g_assert (thread != NULL); + thread = run_server (server); /* Create a new download stream connected to the server */ download_uri = g_strdup_printf ("http://127.0.0.1:%u/", soup_server_get_port (server)); @@ -409,9 +420,7 @@ test_download_stream_download_seek_after_start_backwards (void) g_assert (server != NULL); /* Create a thread for the server */ - thread = g_thread_create ((GThreadFunc) run_server_thread, server, TRUE, &error); - g_assert_no_error (error); - g_assert (thread != NULL); + thread = run_server (server); /* Create a new download stream connected to the server */ download_uri = g_strdup_printf ("http://127.0.0.1:%u/", soup_server_get_port (server)); @@ -535,9 +544,7 @@ test_upload_stream_upload_no_entry_content_length (void) g_assert (server != NULL); /* Create a thread for the server */ - thread = g_thread_create ((GThreadFunc) run_server_thread, server, TRUE, &error); - g_assert_no_error (error); - g_assert (thread != NULL); + thread = run_server (server); /* Create a new upload stream uploading to the server */ upload_uri = g_strdup_printf ("http://127.0.0.1:%u/", soup_server_get_port (server)); |