cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

rwlock.h (5073B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#ifndef __GUAC_RWLOCK_H
     21#define __GUAC_RWLOCK_H
     22
     23#include <pthread.h>
     24
     25/**
     26 * This file implements reentrant read-write locks using thread-local storage
     27 * to keep track of how locks are held and released by the current thread,
     28 * since the pthread locks do not support reentrant behavior.
     29 *
     30 * A thread will attempt to acquire the requested lock on the first acquire
     31 * function call, and will release it once the number of unlock requests
     32 * matches the number of lock requests. Therefore, it is safe to aquire a lock
     33 * and then call a function that also acquires the same lock, provided that
     34 * the caller and the callee request to unlock the lock when done with it.
     35 *
     36 * Any lock that's locked using one of the functions defined in this file
     37 * must _only_ be unlocked using the unlock function defined here to avoid
     38 * unexpected behavior.
     39 */
     40
     41/**
     42 * A structure packaging together a pthread rwlock along with a key to a
     43 * thread-local property to keep track of the current status of the lock,
     44 * allowing the functions defined in this header to provide reentrant behavior.
     45 * Note that both the lock and key must be initialized before being provided
     46 * to any of these functions.
     47 */
     48typedef struct guac_rwlock {
     49
     50    /**
     51     * A non-reentrant pthread rwlock to be wrapped by the local lock,
     52     * functions providing reentrant behavior.
     53     */
     54    pthread_rwlock_t lock;
     55
     56    /**
     57     * A key to access a thread-local property tracking any ownership of the
     58     * lock by the current thread.
     59     */
     60    pthread_key_t key;
     61
     62} guac_rwlock;
     63
     64/**
     65 * Initialize the provided guac reentrant rwlock. The lock will be configured to be
     66 * visible to child processes.
     67 *
     68 * @param lock
     69 *     The guac reentrant rwlock to be initialized.
     70 */
     71void guac_rwlock_init(guac_rwlock* lock);
     72
     73/**
     74 * Clean up and destroy the provided guac reentrant rwlock.
     75 *
     76 * @param lock
     77 *     The guac reentrant rwlock to be destroyed.
     78 */
     79void guac_rwlock_destroy(guac_rwlock* lock);
     80
     81/**
     82 * Aquire the write lock for the provided guac reentrant rwlock, if the key does not
     83 * indicate that the write lock is already acquired. If the key indicates that
     84 * the read lock is already acquired, the read lock will be dropped before the
     85 * write lock is acquired. The thread local property associated with the key
     86 * will be updated as necessary to track the thread's ownership of the lock.
     87 *
     88 * If an error occurs while attempting to acquire the lock, a non-zero value is
     89 * returned, and guac_error is set appropriately.
     90 *
     91 * @param reentrant_rwlock
     92 *     The guac reentrant rwlock for which the write lock should be acquired
     93 *     reentrantly.
     94 *
     95 * @return
     96 *     Zero if the lock is succesfully acquired, or a non-zero value if an
     97 *     error occured.
     98 */
     99int guac_rwlock_acquire_write_lock(guac_rwlock* reentrant_rwlock);
    100
    101/**
    102 * Aquire the read lock for the provided guac reentrant rwlock, if the key does not
    103 * indicate that the read or write lock is already acquired. The thread local
    104 * property associated with the key will be updated as necessary to track the
    105 * thread's ownership of the lock.
    106 *
    107 * If an error occurs while attempting to acquire the lock, a non-zero value is
    108 * returned, and guac_error is set appropriately.
    109 *
    110 * @param reentrant_rwlock
    111 *     The guac reentrant rwlock for which the read lock should be acquired
    112 *     reentrantly.
    113 *
    114 * @return
    115 *     Zero if the lock is succesfully acquired, or a non-zero value if an
    116 *     error occured.
    117 */
    118int guac_rwlock_acquire_read_lock(guac_rwlock* reentrant_rwlock);
    119
    120/**
    121 * Release the the rwlock associated with the provided guac reentrant rwlock if this
    122 * is the last level of the lock held by this thread. Otherwise, the thread
    123 * local property associated with the key will be updated as needed to ensure
    124 * that the correct number of release requests will finally release the lock.
    125 *
    126 * If an error occurs while attempting to release the lock, a non-zero value is
    127 * returned, and guac_error is set appropriately.
    128 *
    129 * @param reentrant_rwlock
    130 *     The guac reentrant rwlock that should be released.
    131 *
    132 * @return
    133 *     Zero if the lock is succesfully released, or a non-zero value if an
    134 *     error occured.
    135 */
    136int guac_rwlock_release_lock(guac_rwlock* reentrant_rwlock);
    137
    138#endif
    139