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 2021/04/06 14:06:34 UTC
svn commit: r1888439 - in /subversion/trunk: build.conf
subversion/include/private/svn_waitable_counter.h
subversion/libsvn_fs_x/batch_fsync.c
subversion/libsvn_subr/waitable_counter.c
Author: stefan2
Date: Tue Apr 6 14:06:34 2021
New Revision: 1888439
URL: http://svn.apache.org/viewvc?rev=1888439&view=rev
Log:
Turn waitable_counter_t into the svn_waitable_counter__* internal API.
* subversion/include/private/svn_waitable_counter.h
(new file): Declare & document the new internal API.
* subversion/libsvn_subr/waitable_counter.c
(new file): Implement the new internal API.
* subversion/libsvn_fs_x/batch_fsync.c
(waitable_counter_t,
waitable_counter__create,
waitable_counter__increment,
waitable_counter__wait_for,
waitable_counter__reset): Remove as superseeded by new API.
(to_sync_t,
svn_fs_x__batch_fsync_t,
svn_fs_x__batch_fsync_create,
flush_task,
svn_fs_x__batch_fsync_run): Use new API (just renames).
* build.conf
(libsvn_subr/msvc-export): Add new private API header.
Added:
subversion/trunk/subversion/include/private/svn_waitable_counter.h (with props)
subversion/trunk/subversion/libsvn_subr/waitable_counter.c (with props)
Modified:
subversion/trunk/build.conf
subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c
Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1888439&r1=1888438&r2=1888439&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Tue Apr 6 14:06:34 2021
@@ -396,7 +396,7 @@ msvc-export =
private\svn_sorts_private.h private\svn_auth_private.h
private\svn_string_private.h private\svn_magic.h
private\svn_subr_private.h private\svn_mutex.h
- private\svn_subr_private.h private\svn_thread_cond.h
+ private\svn_thread_cond.h private\svn_waitable_counter.h
private\svn_packed_data.h private\svn_object_pool.h private\svn_cert.h
private\svn_config_private.h private\svn_dirent_uri_private.h
Added: subversion/trunk/subversion/include/private/svn_waitable_counter.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_waitable_counter.h?rev=1888439&view=auto
==============================================================================
--- subversion/trunk/subversion/include/private/svn_waitable_counter.h (added)
+++ subversion/trunk/subversion/include/private/svn_waitable_counter.h Tue Apr 6 14:06:34 2021
@@ -0,0 +1,78 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_waitable_counter.h
+ * @brief Structures and functions for concurrent waitable counters
+ */
+
+#ifndef SVN_WAITABLE_COUNTER_H
+#define SVN_WAITABLE_COUNTER_H
+
+#include "svn_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * A thread-safe counter object that can be incremented and reset.
+ *
+ * Threads can wait efficiently for a counter to assume a specific value.
+ * This whole structure can be opaque to the API users.
+ *
+ * While it is possible to use this API without APR thread support, you
+ * should not call @a svn_waitable_counter__wait_for() in that case.
+ * @see svn_waitable_counter__wait_for
+ */
+typedef struct svn_waitable_counter_t svn_waitable_counter_t;
+
+/** Set @a *counter_p to a new waitable_counter_t instance allocated in
+ * @a result_pool. The initial counter value is 0.
+ */
+svn_error_t *
+svn_waitable_counter__create(svn_waitable_counter_t **counter_p,
+ apr_pool_t *result_pool);
+
+/** Increment the value in @a counter by 1 and notify waiting threads. */
+svn_error_t *
+svn_waitable_counter__increment(svn_waitable_counter_t *counter);
+
+/** Efficiently wait for @a counter to assume @a value.
+ *
+ * @note: If APR does not support threads, no other threads will ever
+ * modify the counter. Therefore, it is illegal to call this function
+ * with a @a value other than what is stored in @a *counter, unless APR
+ * supports multithreading.
+ */
+svn_error_t *
+svn_waitable_counter__wait_for(svn_waitable_counter_t *counter,
+ int value);
+
+/** Set the value in @a counter to 0 and notify waiting threads. */
+svn_error_t *
+svn_waitable_counter__reset(svn_waitable_counter_t *counter);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_WAITABLE_COUNTER_H */
Propchange: subversion/trunk/subversion/include/private/svn_waitable_counter.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c?rev=1888439&r1=1888438&r2=1888439&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c Tue Apr 6 14:06:34 2021
@@ -33,6 +33,7 @@
#include "private/svn_mutex.h"
#include "private/svn_subr_private.h"
#include "private/svn_thread_cond.h"
+#include "private/svn_waitable_counter.h"
/* Handy macro to check APR function results and turning them into
* svn_error_t upon failure. */
@@ -43,87 +44,6 @@
return svn_error_wrap_apr(status_, msg); \
}
-/* Utility construct: Clients can efficiently wait for the encapsulated
- * counter to reach a certain value. Currently, only increments have been
- * implemented. This whole structure can be opaque to the API users.
- */
-typedef struct waitable_counter_t
-{
- /* Current value, initialized to 0. */
- int value;
-
- /* Synchronization objects. */
- svn_thread_cond__t *cond;
- svn_mutex__t *mutex;
-} waitable_counter_t;
-
-/* Set *COUNTER_P to a new waitable_counter_t instance allocated in
- * RESULT_POOL. The initial counter value is 0. */
-static svn_error_t *
-waitable_counter__create(waitable_counter_t **counter_p,
- apr_pool_t *result_pool)
-{
- waitable_counter_t *counter = apr_pcalloc(result_pool, sizeof(*counter));
- counter->value = 0;
-
- SVN_ERR(svn_thread_cond__create(&counter->cond, result_pool));
- SVN_ERR(svn_mutex__init(&counter->mutex, TRUE, result_pool));
-
- *counter_p = counter;
-
- return SVN_NO_ERROR;
-}
-
-/* Increment the value in COUNTER by 1. */
-static svn_error_t *
-waitable_counter__increment(waitable_counter_t *counter)
-{
- SVN_ERR(svn_mutex__lock(counter->mutex));
- counter->value++;
-
- SVN_ERR(svn_thread_cond__broadcast(counter->cond));
- SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR));
-
- return SVN_NO_ERROR;
-}
-
-/* Efficiently wait for COUNTER to assume VALUE. */
-static svn_error_t *
-waitable_counter__wait_for(waitable_counter_t *counter,
- int value)
-{
- svn_boolean_t done = FALSE;
-
- /* This loop implicitly handles spurious wake-ups. */
- do
- {
- SVN_ERR(svn_mutex__lock(counter->mutex));
-
- if (counter->value == value)
- done = TRUE;
- else
- SVN_ERR(svn_thread_cond__wait(counter->cond, counter->mutex));
-
- SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR));
- }
- while (!done);
-
- return SVN_NO_ERROR;
-}
-
-/* Set the value in COUNTER to 0. */
-static svn_error_t *
-waitable_counter__reset(waitable_counter_t *counter)
-{
- SVN_ERR(svn_mutex__lock(counter->mutex));
- counter->value = 0;
- SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR));
-
- SVN_ERR(svn_thread_cond__broadcast(counter->cond));
-
- return SVN_NO_ERROR;
-}
-
/* Entry type for the svn_fs_x__batch_fsync_t collection. There is one
* instance per file handle.
*/
@@ -140,7 +60,7 @@ typedef struct to_sync_t
svn_error_t *result;
/* Counter to increment when we completed the task. */
- waitable_counter_t *counter;
+ svn_waitable_counter_t *counter;
} to_sync_t;
/* The actual collection object. */
@@ -150,7 +70,7 @@ struct svn_fs_x__batch_fsync_t
apr_hash_t *files;
/* Counts the number of completed fsync tasks. */
- waitable_counter_t *counter;
+ svn_waitable_counter_t *counter;
/* Perform fsyncs only if this flag has been set. */
svn_boolean_t flush_to_disk;
@@ -277,7 +197,7 @@ svn_fs_x__batch_fsync_create(svn_fs_x__b
result->files = svn_hash__make(result_pool);
result->flush_to_disk = flush_to_disk;
- SVN_ERR(waitable_counter__create(&result->counter, result_pool));
+ SVN_ERR(svn_waitable_counter__create(&result->counter, result_pool));
apr_pool_cleanup_register(result_pool, result, fsync_batch_cleanup,
apr_pool_cleanup_null);
@@ -430,7 +350,7 @@ flush_task(apr_thread_t *tid,
OTOH, the main thread will probably deadlock anyway if we got
an error here, thus there is no point in trying to tell the
main thread what the problem was. */
- svn_error_clear(waitable_counter__increment(to_sync->counter));
+ svn_error_clear(svn_waitable_counter__increment(to_sync->counter));
return NULL;
}
@@ -465,7 +385,7 @@ svn_fs_x__batch_fsync_run(svn_fs_x__batc
/* Make sure the task completion counter is set to 0. */
chain = svn_error_compose_create(chain,
- waitable_counter__reset(batch->counter));
+ svn_waitable_counter__reset(batch->counter));
/* Start the actual fsyncing process. */
if (batch->flush_to_disk)
@@ -509,8 +429,8 @@ svn_fs_x__batch_fsync_run(svn_fs_x__batc
/* Wait for all outstanding flush operations to complete. */
chain = svn_error_compose_create(chain,
- waitable_counter__wait_for(batch->counter,
- tasks));
+ svn_waitable_counter__wait_for(
+ batch->counter, tasks));
/* Collect the results, close all files and release memory. */
for (hi = apr_hash_first(scratch_pool, batch->files);
Added: subversion/trunk/subversion/libsvn_subr/waitable_counter.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/waitable_counter.c?rev=1888439&view=auto
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/waitable_counter.c (added)
+++ subversion/trunk/subversion/libsvn_subr/waitable_counter.c Tue Apr 6 14:06:34 2021
@@ -0,0 +1,106 @@
+/* waitable_counter.c --- implement a concurrent waitable counter.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include "private/svn_waitable_counter.h"
+#include "private/svn_thread_cond.h"
+
+struct svn_waitable_counter_t
+{
+ /* Current value, initialized to 0. */
+ int value;
+
+ /* Synchronization objects, always used in tandem. */
+ svn_thread_cond__t *cond;
+ svn_mutex__t *mutex;
+};
+
+svn_error_t *
+svn_waitable_counter__create(svn_waitable_counter_t **counter_p,
+ apr_pool_t *result_pool)
+{
+ svn_waitable_counter_t *counter = apr_pcalloc(result_pool, sizeof(*counter));
+ counter->value = 0;
+
+ SVN_ERR(svn_thread_cond__create(&counter->cond, result_pool));
+ SVN_ERR(svn_mutex__init(&counter->mutex, TRUE, result_pool));
+
+ *counter_p = counter;
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_waitable_counter__increment(svn_waitable_counter_t *counter)
+{
+ SVN_ERR(svn_mutex__lock(counter->mutex));
+ counter->value++;
+
+ SVN_ERR(svn_thread_cond__broadcast(counter->cond));
+ SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_waitable_counter__wait_for(svn_waitable_counter_t *counter,
+ int value)
+{
+#if APR_HAS_THREADS
+
+ svn_boolean_t done = FALSE;
+
+ /* This loop implicitly handles spurious wake-ups. */
+ do
+ {
+ SVN_ERR(svn_mutex__lock(counter->mutex));
+
+ if (counter->value == value)
+ done = TRUE;
+ else
+ SVN_ERR(svn_thread_cond__wait(counter->cond, counter->mutex));
+
+ SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR));
+ }
+ while (!done);
+
+#else
+
+ /* If the counter does not match, we would be wait indefintely.
+ * this is a bug that we should report. */
+ SVN_ERR_ASSERT(counter->value == value);
+
+#endif
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_waitable_counter__reset(svn_waitable_counter_t *counter)
+{
+ SVN_ERR(svn_mutex__lock(counter->mutex));
+ counter->value = 0;
+ SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR));
+
+ SVN_ERR(svn_thread_cond__broadcast(counter->cond));
+
+ return SVN_NO_ERROR;
+}
Propchange: subversion/trunk/subversion/libsvn_subr/waitable_counter.c
------------------------------------------------------------------------------
svn:eol-style = native