From b545f65d169c26bbf9a5af6a5d4894ee3316dbff Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 9 Jan 2013 17:54:07 +0000 Subject: [PATCH] Add a virObjectLockable class holding a mutex A great many virObject instances require a mutex, so introduce a convenient class for this which provides a mutex. This avoids repeating the tedious init/destroy code Signed-off-by: Daniel P. Berrange --- src/libvirt_private.syms | 4 ++ src/util/virobject.c | 104 ++++++++++++++++++++++++++++++++++++++- src/util/virobject.h | 20 ++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 70c1591074..1ace1a1822 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1770,13 +1770,17 @@ virNodeSuspendGetTargetMask; # virobject.h virClassForObject; +virClassForObjectLockable; virClassIsDerivedFrom; virClassName; virClassNew; virObjectFreeCallback; virObjectIsClass; +virObjectLock; +virObjectLockableNew; virObjectNew; virObjectRef; +virObjectUnlock; virObjectUnref; diff --git a/src/util/virobject.c b/src/util/virobject.c index 5f44ab2d6d..838b5cd468 100644 --- a/src/util/virobject.c +++ b/src/util/virobject.c @@ -43,6 +43,9 @@ struct _virClass { }; static virClassPtr virObjectClass; +static virClassPtr virObjectLockableClass; + +static void virObjectLockableDispose(void *anyobj); static int virObjectOnceInit(void) { @@ -52,6 +55,12 @@ static int virObjectOnceInit(void) NULL))) return -1; + if (!(virObjectLockableClass = virClassNew(virObjectClass, + "virObjectLockable", + sizeof(virObjectLockable), + virObjectLockableDispose))) + return -1; + return 0; } @@ -72,6 +81,20 @@ virClassPtr virClassForObject(void) } +/** + * virClassForObjectLockable: + * + * Returns the class instance for the virObjectLockable type + */ +virClassPtr virClassForObjectLockable(void) +{ + if (!virObjectInitialize() < 0) + return NULL; + + return virObjectLockableClass; +} + + /** * virClassNew: * @parent: the parent class @@ -180,6 +203,38 @@ void *virObjectNew(virClassPtr klass) } +void *virObjectLockableNew(virClassPtr klass) +{ + virObjectLockablePtr obj; + + if (!virClassIsDerivedFrom(klass, virClassForObjectLockable())) { + virReportInvalidArg(klass, + _("Class %s must derive from virObjectLockable"), + virClassName(klass)); + return NULL; + } + + if (!(obj = virObjectNew(klass))) + return NULL; + + if (virMutexInit(&obj->lock) < 0) { + virReportSystemError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to initialize mutex")); + virObjectUnref(obj); + return NULL; + } + + return obj; +} + + +static void virObjectLockableDispose(void *anyobj) +{ + virObjectLockablePtr obj = anyobj; + + virMutexDestroy(&obj->lock); +} + /** * virObjectUnref: * @anyobj: any instance of virObjectPtr @@ -209,8 +264,6 @@ bool virObjectUnref(void *anyobj) klass = klass->parent; } - virMutexDestroy(&obj->lock); - /* Clear & poison object */ memset(obj, 0, obj->klass->objectSize); obj->magic = 0xDEADBEEF; @@ -243,6 +296,53 @@ void *virObjectRef(void *anyobj) } +/** + * virObjectLock: + * @anyobj: any instance of virObjectLockablePtr + * + * Acquire a lock on @anyobj. The lock must be + * released by virObjectUnlock. + * + * The caller is expected to have acquired a reference + * on the object before locking it (eg virObjectRef). + * The object must be unlocked before releasing this + * reference. + */ +void virObjectLock(void *anyobj) +{ + virObjectLockablePtr obj = anyobj; + + if (!virObjectIsClass(obj, virObjectLockableClass)) { + VIR_WARN("Object %p (%s) is not a virObjectLockable instance", + obj, obj ? obj->parent.klass->name : "(unknown)"); + return; + } + + virMutexLock(&obj->lock); +} + + +/** + * virObjectUnlock: + * @anyobj: any instance of virObjectLockablePtr + * + * Release a lock on @anyobj. The lock must have been + * acquired by virObjectLock. + */ +void virObjectUnlock(void *anyobj) +{ + virObjectLockablePtr obj = anyobj; + + if (!virObjectIsClass(obj, virObjectLockableClass)) { + VIR_WARN("Object %p (%s) is not a virObjectLockable instance", + obj, obj ? obj->parent.klass->name : "(unknown)"); + return; + } + + virMutexUnlock(&obj->lock); +} + + /** * virObjectIsClass: * @anyobj: any instance of virObjectPtr diff --git a/src/util/virobject.h b/src/util/virobject.h index afeb4f5626..bb72a25bc3 100644 --- a/src/util/virobject.h +++ b/src/util/virobject.h @@ -23,6 +23,7 @@ # define __VIR_OBJECT_H__ # include "internal.h" +# include "virthread.h" typedef struct _virClass virClass; typedef virClass *virClassPtr; @@ -30,6 +31,9 @@ typedef virClass *virClassPtr; typedef struct _virObject virObject; typedef virObject *virObjectPtr; +typedef struct _virObjectLockable virObjectLockable; +typedef virObjectLockable *virObjectLockablePtr; + typedef void (*virObjectDisposeCallback)(void *obj); struct _virObject { @@ -38,7 +42,14 @@ struct _virObject { virClassPtr klass; }; +struct _virObjectLockable { + virObject parent; + virMutex lock; +}; + + virClassPtr virClassForObject(void); +virClassPtr virClassForObjectLockable(void); virClassPtr virClassNew(virClassPtr parent, const char *name, @@ -64,4 +75,13 @@ bool virObjectIsClass(void *obj, void virObjectFreeCallback(void *opaque); +void *virObjectLockableNew(virClassPtr klass) + ATTRIBUTE_NONNULL(1); + +void virObjectLock(void *lockableobj) + ATTRIBUTE_NONNULL(1); +void virObjectUnlock(void *lockableobj) + ATTRIBUTE_NONNULL(1); + + #endif /* __VIR_OBJECT_H */ -- GitLab