mergerfs/vendored/libfuse/include/mutex_ndebug.hpp
Antonio S. Musumeci 8baf274cde Replace two-statement mutex_lockguard macro with single RAII declaration
The old macro expanded to two statements (mutex_lock + DEFER unlock).
In an unbraced if/else only the lock would be conditional while the
DEFER always executed — a latent double-unlock / unbalanced-unlock bug.

Add ScopedMutexLock to both debug and ndebug headers:
 - debug: stores __FILE__/__func__/__LINE__ from the call site and
   passes them to _mutex_lock/_mutex_unlock for diagnostics
 - ndebug: lightweight wrapper around mutex_lock/mutex_unlock

Redefine mutex_lockguard to create a single uniquely-named
ScopedMutexLock variable (via __COUNTER__), making it safe in any
statement context. Remove the now-unused scope_guard include.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 21:42:24 -04:00

85 lines
1.2 KiB
C++

#pragma once
#include <cstdlib>
#include <pthread.h>
#ifndef PTHREAD_MUTEX_ADAPTIVE_NP
# define PTHREAD_MUTEX_ADAPTIVE_NP PTHREAD_MUTEX_NORMAL
#endif
static
inline
void
mutex_init(pthread_mutex_t &mutex_)
{
int rv;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ADAPTIVE_NP);
rv = pthread_mutex_init(&mutex_,&attr);
if(rv != 0)
std::abort();
pthread_mutexattr_destroy(&attr);
}
static
inline
void
mutex_lock(pthread_mutex_t &mutex_)
{
int rv;
rv = pthread_mutex_lock(&mutex_);
if(rv != 0)
std::abort();
}
static
inline
void
mutex_unlock(pthread_mutex_t &mutex_)
{
int rv;
rv = pthread_mutex_unlock(&mutex_);
if(rv != 0)
std::abort();
}
static
inline
void
mutex_destroy(pthread_mutex_t &mutex_)
{
int rv;
rv = pthread_mutex_destroy(&mutex_);
if(rv != 0)
std::abort();
}
class ScopedMutexLock
{
private:
pthread_mutex_t &_mutex;
public:
ScopedMutexLock(pthread_mutex_t &mutex_)
: _mutex(mutex_)
{
mutex_lock(_mutex);
}
~ScopedMutexLock()
{
mutex_unlock(_mutex);
}
ScopedMutexLock(const ScopedMutexLock&) = delete;
ScopedMutexLock& operator=(const ScopedMutexLock&) = delete;
};