1251881Speter/**
2251881Speter * @copyright
3251881Speter * ====================================================================
4251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
5251881Speter *    or more contributor license agreements.  See the NOTICE file
6251881Speter *    distributed with this work for additional information
7251881Speter *    regarding copyright ownership.  The ASF licenses this file
8251881Speter *    to you under the Apache License, Version 2.0 (the
9251881Speter *    "License"); you may not use this file except in compliance
10251881Speter *    with the License.  You may obtain a copy of the License at
11251881Speter *
12251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
13251881Speter *
14251881Speter *    Unless required by applicable law or agreed to in writing,
15251881Speter *    software distributed under the License is distributed on an
16251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17251881Speter *    KIND, either express or implied.  See the License for the
18251881Speter *    specific language governing permissions and limitations
19251881Speter *    under the License.
20251881Speter * ====================================================================
21251881Speter * @endcopyright
22251881Speter *
23251881Speter * @file svn_mutex.h
24251881Speter * @brief Strutures and functions for mutual exclusion
25251881Speter */
26251881Speter
27251881Speter#ifndef SVN_MUTEX_H
28251881Speter#define SVN_MUTEX_H
29251881Speter
30251881Speter#include <apr_thread_mutex.h>
31251881Speter
32251881Speter#include "svn_error.h"
33251881Speter
34251881Speter#ifdef __cplusplus
35251881Speterextern "C" {
36251881Speter#endif /* __cplusplus */
37251881Speter
38251881Speter/**
39251881Speter * This is a simple wrapper around @c apr_thread_mutex_t and will be a
40251881Speter * valid identifier even if APR does not support threading.
41251881Speter */
42251881Speter#if APR_HAS_THREADS
43251881Speter
44251881Speter/** A mutex for synchronization between threads. It may be NULL, in
45251881Speter * which case no synchronization will take place. The latter is useful
46251881Speter * when implementing some functionality with optional synchronization.
47251881Speter */
48251881Spetertypedef apr_thread_mutex_t svn_mutex__t;
49251881Speter
50251881Speter#else
51251881Speter
52251881Speter/** Dummy definition. The content will never be actually accessed.
53251881Speter */
54251881Spetertypedef void svn_mutex__t;
55251881Speter
56251881Speter#endif
57251881Speter
58251881Speter/** Initialize the @a *mutex. If @a mutex_required is TRUE, the mutex will
59251881Speter * actually be created with a lifetime defined by @a result_pool. Otherwise,
60251881Speter * the pointer will be set to @c NULL and svn_mutex__lock() as well as
61251881Speter * svn_mutex__unlock() will be no-ops.
62251881Speter *
63251881Speter * If threading is not supported by APR, this function is a no-op.
64251881Speter */
65251881Spetersvn_error_t *
66251881Spetersvn_mutex__init(svn_mutex__t **mutex,
67251881Speter                svn_boolean_t mutex_required,
68251881Speter                apr_pool_t *result_pool);
69251881Speter
70251881Speter/** Acquire the @a mutex, if that has been enabled in svn_mutex__init().
71251881Speter * Make sure to call svn_mutex__unlock() some time later in the same
72251881Speter * thread to release the mutex again. Recursive locking are not supported.
73251881Speter *
74251881Speter * @note You should use #SVN_MUTEX__WITH_LOCK instead of explicit lock
75251881Speter * aquisition and release.
76251881Speter */
77251881Spetersvn_error_t *
78251881Spetersvn_mutex__lock(svn_mutex__t *mutex);
79251881Speter
80251881Speter/** Release the @a mutex, previously acquired using svn_mutex__lock()
81251881Speter * that has been enabled in svn_mutex__init().
82251881Speter *
83251881Speter * Since this is often used as part of the calling function's exit
84251881Speter * sequence, we accept that function's current return code in @a err.
85251881Speter * If it is not #SVN_NO_ERROR, it will be used as the return value -
86251881Speter * irrespective of the possible internal failures during unlock. If @a err
87251881Speter * is #SVN_NO_ERROR, internal failures of this function will be
88251881Speter * reported in the return value.
89251881Speter *
90251881Speter * @note You should use #SVN_MUTEX__WITH_LOCK instead of explicit lock
91251881Speter * aquisition and release.
92251881Speter */
93251881Spetersvn_error_t *
94251881Spetersvn_mutex__unlock(svn_mutex__t *mutex,
95251881Speter                  svn_error_t *err);
96251881Speter
97251881Speter/** Aquires the @a mutex, executes the expression @a expr and finally
98251881Speter * releases the @a mutex. If any of these steps fail, the function using
99251881Speter * this macro will return an #svn_error_t. This macro guarantees that
100251881Speter * the @a mutex will always be unlocked again if it got locked successfully
101251881Speter * by the first step.
102251881Speter *
103251881Speter * @note Prefer using this macro instead of explicit lock aquisition and
104251881Speter * release.
105251881Speter */
106251881Speter#define SVN_MUTEX__WITH_LOCK(mutex, expr)               \
107251881Speterdo {                                                    \
108251881Speter  svn_mutex__t *svn_mutex__m = (mutex);                 \
109251881Speter  SVN_ERR(svn_mutex__lock(svn_mutex__m));               \
110251881Speter  SVN_ERR(svn_mutex__unlock(svn_mutex__m, (expr)));     \
111251881Speter} while (0)
112251881Speter
113251881Speter#ifdef __cplusplus
114251881Speter}
115251881Speter#endif /* __cplusplus */
116251881Speter
117251881Speter#endif /* SVN_MUTEX_H */
118