virthread: Introduce virLockGuard

Locks a virMutex on creation and unlocks it in its destructor.

The VIR_LOCK_GUARD macro is used instead of "g_auto(virLockGuard)" to
work around a clang issue (see https://bugs.llvm.org/show_bug.cgi?id=3888
and https://bugs.llvm.org/show_bug.cgi?id=43482).

Typical usage:

    void function(virMutex *m)
    {
        VIR_LOCK_GUARD lock = virLockGuardLock(m);
        /* `m` is locked, and released automatically on scope exit */

        ...
        while (expression) {
            VIR_LOCK_GUARD lock2 = virLockGuardLock(...);
            /* similar */
        }
    }

Signed-off-by: Tim Wiederhake <twiederh@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Tim Wiederhake 2021-08-25 10:25:32 +02:00
parent 3f19e116cd
commit d00d078968
3 changed files with 27 additions and 0 deletions

View File

@ -3388,6 +3388,8 @@ virCondInit;
virCondSignal; virCondSignal;
virCondWait; virCondWait;
virCondWaitUntil; virCondWaitUntil;
virLockGuardLock;
virLockGuardUnlock;
virMutexDestroy; virMutexDestroy;
virMutexInit; virMutexInit;
virMutexInitRecursive; virMutexInitRecursive;

View File

@ -96,6 +96,21 @@ void virMutexUnlock(virMutex *m)
pthread_mutex_unlock(&m->lock); pthread_mutex_unlock(&m->lock);
} }
virLockGuard virLockGuardLock(virMutex *m)
{
virLockGuard l = { m };
virMutexLock(m);
return l;
}
void virLockGuardUnlock(virLockGuard *l)
{
if (!l || !l->mutex)
return;
virMutexUnlock(g_steal_pointer(&l->mutex));
}
int virRWLockInit(virRWLock *m) int virRWLockInit(virRWLock *m)
{ {

View File

@ -31,6 +31,11 @@ struct virMutex {
pthread_mutex_t lock; pthread_mutex_t lock;
}; };
typedef struct virLockGuard virLockGuard;
struct virLockGuard {
virMutex *mutex;
};
typedef struct virRWLock virRWLock; typedef struct virRWLock virRWLock;
struct virRWLock { struct virRWLock {
pthread_rwlock_t lock; pthread_rwlock_t lock;
@ -121,6 +126,11 @@ void virMutexLock(virMutex *m);
void virMutexUnlock(virMutex *m); void virMutexUnlock(virMutex *m);
virLockGuard virLockGuardLock(virMutex *m);
void virLockGuardUnlock(virLockGuard *l);
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(virLockGuard, virLockGuardUnlock);
#define VIR_LOCK_GUARD g_auto(virLockGuard) G_GNUC_UNUSED
int virRWLockInit(virRWLock *m) G_GNUC_WARN_UNUSED_RESULT; int virRWLockInit(virRWLock *m) G_GNUC_WARN_UNUSED_RESULT;
void virRWLockDestroy(virRWLock *m); void virRWLockDestroy(virRWLock *m);