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