You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/07/11 23:05:26 UTC
svn commit: r1145352 -
/subversion/branches/svn_mutex/subversion/libsvn_subr/utf.c
Author: stefan2
Date: Mon Jul 11 21:05:26 2011
New Revision: 1145352
URL: http://svn.apache.org/viewvc?rev=1145352&view=rev
Log:
On svn_mutex branch:
Switch UTF management code to svn_mutex__t.
Simplify locking-related code when possible.
* subversion/libsvn_subr/utf.c
(xlate_handle_mutex): we can always have the - maybe dummy - mutex objects
(xlate_cleanup): svn_mutex__t* will be cleaned up automatically
(svn_utf_initialize): simplify using new API
(xlate_alloc_handle): common, to-be-sync'ed handle allocation
(get_xlate_handle_node_internal): to-be-sync'ed part of get_xlate_handle_node
(get_xlate_handle_node): part that does not need sync; sync'ed call to above functions
(put_xlate_handle_node_internal): to-be-sync'ed part of put_xlate_handle_node
(put_xlate_handle_node): part that does not need sync; sync'ed call to above function
(svn_utf_stringbuf_to_utf8, svn_utf_string_to_utf8, svn_utf_cstring_to_utf8,
svn_utf_cstring_to_utf8_ex2): adapt to changed signatures
Modified:
subversion/branches/svn_mutex/subversion/libsvn_subr/utf.c
Modified: subversion/branches/svn_mutex/subversion/libsvn_subr/utf.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_subr/utf.c?rev=1145352&r1=1145351&r2=1145352&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_subr/utf.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_subr/utf.c Mon Jul 11 21:05:26 2011
@@ -42,6 +42,7 @@
#include "private/svn_utf_private.h"
#include "private/svn_dep_compat.h"
#include "private/svn_string_private.h"
+#include "private/svn_mutex.h"
@@ -53,9 +54,7 @@ static const char *SVN_UTF_UTON_XLATE_HA
static const char *SVN_APR_UTF8_CHARSET = "UTF-8";
-#if APR_HAS_THREADS
-static apr_thread_mutex_t *xlate_handle_mutex = NULL;
-#endif
+static svn_mutex__t *xlate_handle_mutex = NULL;
/* The xlate handle cache is a global hash table with linked lists of xlate
* handles. In multi-threaded environments, a thread "borrows" an xlate
@@ -99,10 +98,6 @@ xlate_cleanup(void *arg)
{
/* We set the cache variables to NULL so that translation works in other
cleanup functions, even if it isn't cached then. */
-#if APR_HAS_THREADS
- apr_thread_mutex_destroy(xlate_handle_mutex);
- xlate_handle_mutex = NULL;
-#endif
xlate_handle_hash = NULL;
/* ensure no stale objects get accessed */
@@ -126,9 +121,7 @@ void
svn_utf_initialize(apr_pool_t *pool)
{
apr_pool_t *subpool;
-#if APR_HAS_THREADS
- apr_thread_mutex_t *mutex;
-#endif
+ svn_mutex__t *mutex;
if (!xlate_handle_hash)
{
@@ -136,16 +129,18 @@ svn_utf_initialize(apr_pool_t *pool)
We can't use the pool passed to us by the caller, since we will
use it for xlate handle allocations, possibly in multiple threads,
and pool allocation is not thread-safe. */
- subpool = svn_pool_create(pool);
-#if APR_HAS_THREADS
- if (apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, subpool)
- == APR_SUCCESS)
- xlate_handle_mutex = mutex;
- else
- return;
-#endif
+ apr_pool_t *subpool = svn_pool_create(pool);
+ svn_mutex__t *mutex;
+ svn_error_t *err = svn_mutex__init(&mutex, TRUE, subpool);
+ if (err)
+ {
+ svn_error_clear(err);
+ return;
+ }
+ xlate_handle_mutex = mutex;
xlate_handle_hash = apr_hash_make(subpool);
+
apr_pool_cleanup_register(subpool, NULL, xlate_cleanup,
apr_pool_cleanup_null);
}
@@ -200,91 +195,17 @@ atomic_swap(volatile void **mem, void *n
#endif
}
-/* Set *RET to a handle node for converting from FROMPAGE to TOPAGE,
- creating the handle node if it doesn't exist in USERDATA_KEY.
- If a node is not cached and apr_xlate_open() returns APR_EINVAL or
- APR_ENOTIMPL, set (*RET)->handle to NULL. If fail for any other
- reason, return the error.
-
- Allocate *RET and its xlate handle in POOL if svn_utf_initialize()
- hasn't been called or USERDATA_KEY is NULL. Else, allocate them
- in the pool of xlate_handle_hash. */
+/* Set *RET to a newly created handle node for converting from FROMPAGE
+ to TOPAGE, If apr_xlate_open() returns APR_EINVAL or APR_ENOTIMPL, set
+ (*RET)->handle to NULL. If fail for any other reason, return the error.
+ Allocate *RET and its xlate handle in POOL. */
static svn_error_t *
-get_xlate_handle_node(xlate_handle_node_t **ret,
- const char *topage, const char *frompage,
- const char *userdata_key, apr_pool_t *pool)
+xlate_alloc_handle(xlate_handle_node_t **ret,
+ const char *topage, const char *frompage,
+ apr_pool_t *pool)
{
- xlate_handle_node_t **old_node_p;
- xlate_handle_node_t *old_node = NULL;
apr_status_t apr_err;
apr_xlate_t *handle;
- svn_error_t *err = NULL;
-
- /* If we already have a handle, just return it. */
- if (userdata_key)
- {
- if (xlate_handle_hash)
- {
- /* 1st level: global, static items */
- if (userdata_key == SVN_UTF_NTOU_XLATE_HANDLE)
- old_node = atomic_swap(&xlat_ntou_static_handle, NULL);
- else if (userdata_key == SVN_UTF_UTON_XLATE_HANDLE)
- old_node = atomic_swap(&xlat_uton_static_handle, NULL);
-
- if (old_node && old_node->valid)
- {
- *ret = old_node;
- return SVN_NO_ERROR;
- }
-
- /* 2nd level: hash lookup */
-#if APR_HAS_THREADS
- apr_err = apr_thread_mutex_lock(xlate_handle_mutex);
- if (apr_err != APR_SUCCESS)
- return svn_error_create(apr_err, NULL,
- _("Can't lock charset translation mutex"));
-#endif
- old_node_p = apr_hash_get(xlate_handle_hash, userdata_key,
- APR_HASH_KEY_STRING);
- if (old_node_p)
- old_node = *old_node_p;
- if (old_node)
- {
- /* Ensure that the handle is still valid. */
- if (old_node->valid)
- {
- /* Remove from the list. */
- *old_node_p = old_node->next;
- old_node->next = NULL;
-#if APR_HAS_THREADS
- apr_err = apr_thread_mutex_unlock(xlate_handle_mutex);
- if (apr_err != APR_SUCCESS)
- return svn_error_create(apr_err, NULL,
- _("Can't unlock charset "
- "translation mutex"));
-#endif
- *ret = old_node;
- return SVN_NO_ERROR;
- }
- }
- }
- else
- {
- void *p;
- /* We fall back on a per-pool cache instead. */
- apr_pool_userdata_get(&p, userdata_key, pool);
- old_node = p;
- /* Ensure that the handle is still valid. */
- if (old_node && old_node->valid)
- {
- *ret = old_node;
- return SVN_NO_ERROR;
- }
- }
- }
-
- /* Note that we still have the mutex locked (if it is initialized), so we
- can use the global pool for creating the new xlate handle. */
/* The error handling doesn't support the following cases, since we don't
use them currently. Catch this here. */
@@ -293,10 +214,6 @@ get_xlate_handle_node(xlate_handle_node_
&& (frompage != SVN_APR_LOCALE_CHARSET
|| topage != SVN_APR_LOCALE_CHARSET));
- /* Use the correct pool for creating the handle. */
- if (userdata_key && xlate_handle_hash)
- pool = apr_hash_pool_get(xlate_handle_hash);
-
/* Try to create a handle. */
#if defined(WIN32)
apr_err = svn_subr__win32_xlate_open((win32_xlate_t **)&handle, topage,
@@ -325,8 +242,7 @@ get_xlate_handle_node(xlate_handle_node_
_("Can't create a character converter from "
"'%s' to '%s'"), frompage, topage);
- err = svn_error_create(apr_err, NULL, errstr);
- goto cleanup;
+ return svn_error_create(apr_err, NULL, errstr);
}
/* Allocate and initialize the node. */
@@ -348,34 +264,159 @@ get_xlate_handle_node(xlate_handle_node_
apr_pool_cleanup_register(pool, *ret, xlate_handle_node_cleanup,
apr_pool_cleanup_null);
- cleanup:
- /* Don't need the lock anymore. */
-#if APR_HAS_THREADS
+ return SVN_NO_ERROR;
+}
+
+/* Extend xlate_alloc_handle by using USERDATA_KEY as a key in our
+ global hash map, if available.
+
+ Allocate *RET and its xlate handle in POOL if svn_utf_initialize()
+ hasn't been called or USERDATA_KEY is NULL. Else, allocate them
+ in the pool of xlate_handle_hash.
+
+ Note: this function is not thread-safe. Call get_xlate_handle_node
+ instead. */
+static svn_error_t *
+get_xlate_handle_node_internal(xlate_handle_node_t **ret,
+ const char *topage, const char *frompage,
+ const char *userdata_key, apr_pool_t *pool)
+{
+ /* If we already have a handle, just return it. */
if (userdata_key && xlate_handle_hash)
{
- apr_status_t unlock_err = apr_thread_mutex_unlock(xlate_handle_mutex);
- if (unlock_err != APR_SUCCESS)
- return svn_error_create(unlock_err, NULL,
- _("Can't unlock charset translation mutex"));
+ xlate_handle_node_t *old_node = NULL;
+
+ /* 2nd level: hash lookup */
+ xlate_handle_node_t **old_node_p = apr_hash_get(xlate_handle_hash,
+ userdata_key,
+ APR_HASH_KEY_STRING);
+ if (old_node_p)
+ old_node = *old_node_p;
+ if (old_node)
+ {
+ /* Ensure that the handle is still valid. */
+ if (old_node->valid)
+ {
+ /* Remove from the list. */
+ *old_node_p = old_node->next;
+ old_node->next = NULL;
+ *ret = old_node;
+ return SVN_NO_ERROR;
+ }
+ }
+ }
+
+ /* Note that we still have the mutex locked (if it is initialized), so we
+ can use the global pool for creating the new xlate handle. */
+
+ /* Use the correct pool for creating the handle. */
+ pool = apr_hash_pool_get(xlate_handle_hash);
+
+ return xlate_alloc_handle(ret, topage, frompage, pool);
+}
+
+/* Set *RET to a handle node for converting from FROMPAGE to TOPAGE,
+ creating the handle node if it doesn't exist in USERDATA_KEY.
+ If a node is not cached and apr_xlate_open() returns APR_EINVAL or
+ APR_ENOTIMPL, set (*RET)->handle to NULL. If fail for any other
+ reason, return the error.
+
+ Allocate *RET and its xlate handle in POOL if svn_utf_initialize()
+ hasn't been called or USERDATA_KEY is NULL. Else, allocate them
+ in the pool of xlate_handle_hash. */
+static svn_error_t *
+get_xlate_handle_node(xlate_handle_node_t **ret,
+ const char *topage, const char *frompage,
+ const char *userdata_key, apr_pool_t *pool)
+{
+ xlate_handle_node_t **old_node_p;
+ xlate_handle_node_t *old_node = NULL;
+ apr_status_t apr_err;
+ apr_xlate_t *handle;
+ svn_error_t *err = NULL;
+
+ /* If we already have a handle, just return it. */
+ if (userdata_key)
+ {
+ if (xlate_handle_hash)
+ {
+ /* 1st level: global, static items */
+ if (userdata_key == SVN_UTF_NTOU_XLATE_HANDLE)
+ old_node = atomic_swap(&xlat_ntou_static_handle, NULL);
+ else if (userdata_key == SVN_UTF_UTON_XLATE_HANDLE)
+ old_node = atomic_swap(&xlat_uton_static_handle, NULL);
+
+ if (old_node && old_node->valid)
+ {
+ *ret = old_node;
+ return SVN_NO_ERROR;
+ }
+ }
+ else
+ {
+ void *p;
+ /* We fall back on a per-pool cache instead. */
+ apr_pool_userdata_get(&p, userdata_key, pool);
+ old_node = p;
+ /* Ensure that the handle is still valid. */
+ if (old_node && old_node->valid)
+ {
+ *ret = old_node;
+ return SVN_NO_ERROR;
+ }
+
+ return xlate_alloc_handle(ret, topage, frompage, pool);
+ }
}
-#endif
- return err;
+ SVN_MUTEX__WITH_LOCK(xlate_handle_mutex,
+ get_xlate_handle_node_internal(ret,
+ topage,
+ frompage,
+ userdata_key,
+ pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Put back NODE into the xlate handle cache for use by other calls.
+
+ Note: this function is not thread-safe. Call put_xlate_handle_node
+ instead. */
+static svn_error_t *
+put_xlate_handle_node_internal(xlate_handle_node_t *node,
+ const char *userdata_key)
+{
+ xlate_handle_node_t **node_p = apr_hash_get(xlate_handle_hash,
+ userdata_key,
+ APR_HASH_KEY_STRING);
+ if (node_p == NULL)
+ {
+ userdata_key = apr_pstrdup(apr_hash_pool_get(xlate_handle_hash),
+ userdata_key);
+ node_p = apr_palloc(apr_hash_pool_get(xlate_handle_hash),
+ sizeof(*node_p));
+ *node_p = NULL;
+ apr_hash_set(xlate_handle_hash, userdata_key,
+ APR_HASH_KEY_STRING, node_p);
+ }
+ node->next = *node_p;
+ *node_p = node;
+
+ return SVN_NO_ERROR;
}
/* Put back NODE into the xlate handle cache for use by other calls.
If there is no global cache, store the handle in POOL.
- Ignore errors related to locking/unlocking the mutex.
- ### Mutex errors here are very weird. Should we handle them "correctly"
- ### even if that complicates error handling in the routines below? */
-static void
+ Ignore errors related to locking/unlocking the mutex. */
+static svn_error_t *
put_xlate_handle_node(xlate_handle_node_t *node,
const char *userdata_key,
apr_pool_t *pool)
{
assert(node->next == NULL);
if (!userdata_key)
- return;
+ return SVN_NO_ERROR;
/* push previous global node to the hash */
if (xlate_handle_hash)
@@ -388,36 +429,19 @@ put_xlate_handle_node(xlate_handle_node_
else if (userdata_key == SVN_UTF_UTON_XLATE_HANDLE)
node = atomic_swap(&xlat_uton_static_handle, node);
if (node == NULL)
- return;
+ return SVN_NO_ERROR;
-#if APR_HAS_THREADS
- if (apr_thread_mutex_lock(xlate_handle_mutex) != APR_SUCCESS)
- SVN_ERR_MALFUNCTION_NO_RETURN();
-#endif
- node_p = apr_hash_get(xlate_handle_hash, userdata_key,
- APR_HASH_KEY_STRING);
- if (node_p == NULL)
- {
- userdata_key = apr_pstrdup(apr_hash_pool_get(xlate_handle_hash),
- userdata_key);
- node_p = apr_palloc(apr_hash_pool_get(xlate_handle_hash),
- sizeof(*node_p));
- *node_p = NULL;
- apr_hash_set(xlate_handle_hash, userdata_key,
- APR_HASH_KEY_STRING, node_p);
- }
- node->next = *node_p;
- *node_p = node;
-#if APR_HAS_THREADS
- if (apr_thread_mutex_unlock(xlate_handle_mutex) != APR_SUCCESS)
- SVN_ERR_MALFUNCTION_NO_RETURN();
-#endif
+ SVN_MUTEX__WITH_LOCK(xlate_handle_mutex,
+ put_xlate_handle_node_internal(node,
+ userdata_key));
}
else
{
/* Store it in the per-pool cache. */
apr_pool_userdata_set(node, userdata_key, apr_pool_cleanup_null, pool);
}
+
+ return SVN_NO_ERROR;
}
/* Return the apr_xlate handle for converting native characters to UTF-8. */
@@ -702,6 +726,7 @@ svn_utf_stringbuf_to_utf8(svn_stringbuf_
{
xlate_handle_node_t *node;
svn_error_t *err;
+ svn_error_t *err2;
SVN_ERR(get_ntou_xlate_handle_node(&node, pool));
@@ -718,9 +743,11 @@ svn_utf_stringbuf_to_utf8(svn_stringbuf_
*dest = svn_stringbuf_dup(src, pool);
}
- put_xlate_handle_node(node, SVN_UTF_NTOU_XLATE_HANDLE, pool);
-
- return err;
+ return svn_error_compose_create(err,
+ put_xlate_handle_node
+ (node,
+ SVN_UTF_NTOU_XLATE_HANDLE,
+ pool));
}
@@ -750,9 +777,11 @@ svn_utf_string_to_utf8(const svn_string_
*dest = svn_string_dup(src, pool);
}
- put_xlate_handle_node(node, SVN_UTF_NTOU_XLATE_HANDLE, pool);
-
- return err;
+ return svn_error_compose_create(err,
+ put_xlate_handle_node
+ (node,
+ SVN_UTF_NTOU_XLATE_HANDLE,
+ pool));
}
@@ -793,8 +822,11 @@ svn_utf_cstring_to_utf8(const char **des
SVN_ERR(get_ntou_xlate_handle_node(&node, pool));
err = convert_cstring(dest, src, node, pool);
- put_xlate_handle_node(node, SVN_UTF_NTOU_XLATE_HANDLE, pool);
- SVN_ERR(err);
+ SVN_ERR(svn_error_compose_create(err,
+ put_xlate_handle_node
+ (node,
+ SVN_UTF_NTOU_XLATE_HANDLE,
+ pool)));
return check_cstring_utf8(*dest, pool);
}
@@ -813,8 +845,12 @@ svn_utf_cstring_to_utf8_ex2(const char *
SVN_ERR(get_xlate_handle_node(&node, SVN_APR_UTF8_CHARSET, frompage,
convset_key, pool));
err = convert_cstring(dest, src, node, pool);
- put_xlate_handle_node(node, convset_key, pool);
- SVN_ERR(err);
+ SVN_ERR(svn_error_compose_create(err,
+ put_xlate_handle_node
+ (node,
+ SVN_UTF_NTOU_XLATE_HANDLE,
+ pool)));
+
return check_cstring_utf8(*dest, pool);
}