text: /*
   * svn_mutex.c: routines for mutual exclusion.
   *
   * ====================================================================
   *    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 <apr_portable.h>
  
  #include "svn_private_config.h"
  #include "private/svn_atomic.h"
  #include "private/svn_mutex.h"
  
  /* With CHECKED set to TRUE, LOCKED and OWNER must be set *after* acquiring
   * the MUTEX and be reset *before* releasing it again.  This is sufficient
   * because we only want to check whether the current thread already holds
   * the lock.  And the current thread cannot be acquiring / releasing a lock
   * *while* checking for recursion at the same time.
   */
  struct svn_mutex__t
  {
  #if APR_HAS_THREADS
  
    apr_thread_mutex_t *mutex;
  
  #else
  
    /* Truly empty structs are not allowed. */
    int dummy;
  
  #endif
  };
  
  svn_error_t *
  svn_mutex__init(svn_mutex__t **mutex_p,
                  svn_boolean_t mutex_required,
                  apr_pool_t *result_pool)
  {
    /* always initialize the mutex pointer, even though it is not
       strictly necessary if APR_HAS_THREADS has not been set */
    *mutex_p = NULL;
  
    if (mutex_required)
      {
        svn_mutex__t *mutex = apr_pcalloc(result_pool, sizeof(*mutex));
  
  #if APR_HAS_THREADS
        apr_status_t status =
            apr_thread_mutex_create(&mutex->mutex,
                                    APR_THREAD_MUTEX_DEFAULT,
                                    result_pool);
        if (status)
          return svn_error_wrap_apr(status, _("Can't create mutex"));
  #endif
  
        *mutex_p = mutex;
      }
  
    return SVN_NO_ERROR;
  }
  
  svn_error_t *
  svn_mutex__lock(svn_mutex__t *mutex)
  {
    if (mutex)
      {
  #if APR_HAS_THREADS
        apr_status_t status = apr_thread_mutex_lock(mutex->mutex);
        if (status)
          return svn_error_wrap_apr(status, _("Can't lock mutex"));
  #endif
      }
  
    return SVN_NO_ERROR;
  }
  
  svn_error_t *
  svn_mutex__unlock(svn_mutex__t *mutex,
                    svn_error_t *err)
  {
    if (mutex)
      {
  #if APR_HAS_THREADS
        apr_status_t status = apr_thread_mutex_unlock(mutex->mutex);
        if (status && !err)
          return svn_error_wrap_apr(status, _("Can't unlock mutex"));
  #endif
      }
  
    return err;
  }
  
  #if APR_HAS_THREADS
  
  apr_thread_mutex_t *
  svn_mutex__get(svn_mutex__t *mutex)
  {
    return mutex->mutex;
  }
  
  #endif
  