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;
virCondWait;
virCondWaitUntil;
virLockGuardLock;
virLockGuardUnlock;
virMutexDestroy;
virMutexInit;
virMutexInitRecursive;

View File

@ -96,6 +96,21 @@ void virMutexUnlock(virMutex *m)
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)
{

View File

@ -31,6 +31,11 @@ struct virMutex {
pthread_mutex_t lock;
};
typedef struct virLockGuard virLockGuard;
struct virLockGuard {
virMutex *mutex;
};
typedef struct virRWLock virRWLock;
struct virRWLock {
pthread_rwlock_t lock;
@ -121,6 +126,11 @@ void virMutexLock(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;
void virRWLockDestroy(virRWLock *m);