Allow for multi-level inheritance of virObject classes

Currently all classes must directly inherit from virObject.
This allows for arbitrarily deep hierarchy. There's not much
to this aside from chaining up the 'dispose' handlers from
each class & providing APIs to check types.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2013-01-09 17:37:27 +00:00
parent e397f658b0
commit 69218922e8
23 changed files with 135 additions and 28 deletions

View File

@ -165,6 +165,7 @@ src/util/virnetdevtap.c
src/util/virnetdevvportprofile.c
src/util/virnetlink.c
src/util/virnodesuspend.c
src/util/virobject.c
src/util/virpci.c
src/util/virpidfile.c
src/util/virprocess.c

View File

@ -700,7 +700,8 @@ static void virDomainObjDispose(void *obj);
static int virDomainObjOnceInit(void)
{
if (!(virDomainObjClass = virClassNew("virDomainObj",
if (!(virDomainObjClass = virClassNew(virClassForObject(),
"virDomainObj",
sizeof(virDomainObj),
virDomainObjDispose)))
return -1;

View File

@ -64,7 +64,8 @@ static int
virDataTypesOnceInit(void)
{
#define DECLARE_CLASS(basename) \
if (!(basename ## Class = virClassNew(#basename, \
if (!(basename ## Class = virClassNew(virClassForObject(), \
#basename, \
sizeof(basename), \
basename ## Dispose))) \
return -1;

View File

@ -1769,6 +1769,8 @@ virNodeSuspendGetTargetMask;
# virobject.h
virClassForObject;
virClassIsDerivedFrom;
virClassName;
virClassNew;
virObjectFreeCallback;

View File

@ -50,7 +50,8 @@ static void virLXCMonitorDispose(void *obj);
static int virLXCMonitorOnceInit(void)
{
if (!(virLXCMonitorClass = virClassNew("virLXCMonitor",
if (!(virLXCMonitorClass = virClassNew(virClassForObject(),
"virLXCMonitor",
sizeof(virLXCMonitor),
virLXCMonitorDispose)))
return -1;

View File

@ -121,7 +121,8 @@ static void qemuAgentDispose(void *obj);
static int qemuAgentOnceInit(void)
{
if (!(qemuAgentClass = virClassNew("qemuAgent",
if (!(qemuAgentClass = virClassNew(virClassForObject(),
"qemuAgent",
sizeof(qemuAgent),
qemuAgentDispose)))
return -1;

View File

@ -244,7 +244,8 @@ static void qemuCapsDispose(void *obj);
static int qemuCapsOnceInit(void)
{
if (!(qemuCapsClass = virClassNew("qemuCaps",
if (!(qemuCapsClass = virClassNew(virClassForObject(),
"qemuCaps",
sizeof(qemuCaps),
qemuCapsDispose)))
return -1;

View File

@ -86,9 +86,10 @@ static void qemuMonitorDispose(void *obj);
static int qemuMonitorOnceInit(void)
{
if (!(qemuMonitorClass = virClassNew("qemuMonitor",
sizeof(qemuMonitor),
qemuMonitorDispose)))
if (!(qemuMonitorClass = virClassNew(virClassForObject(),
"qemuMonitor",
sizeof(qemuMonitor),
qemuMonitorDispose)))
return -1;
return 0;

View File

@ -58,7 +58,8 @@ static void virKeepAliveDispose(void *obj);
static int virKeepAliveOnceInit(void)
{
if (!(virKeepAliveClass = virClassNew("virKeepAlive",
if (!(virKeepAliveClass = virClassNew(virClassForObject(),
"virKeepAlive",
sizeof(virKeepAlive),
virKeepAliveDispose)))
return -1;

View File

@ -117,7 +117,8 @@ static void virNetClientDispose(void *obj);
static int virNetClientOnceInit(void)
{
if (!(virNetClientClass = virClassNew("virNetClient",
if (!(virNetClientClass = virClassNew(virClassForObject(),
"virNetClient",
sizeof(virNetClient),
virNetClientDispose)))
return -1;

View File

@ -52,7 +52,8 @@ static void virNetClientProgramDispose(void *obj);
static int virNetClientProgramOnceInit(void)
{
if (!(virNetClientProgramClass = virClassNew("virNetClientProgram",
if (!(virNetClientProgramClass = virClassNew(virClassForObject(),
"virNetClientProgram",
sizeof(virNetClientProgram),
virNetClientProgramDispose)))
return -1;

View File

@ -68,7 +68,8 @@ static void virNetClientStreamDispose(void *obj);
static int virNetClientStreamOnceInit(void)
{
if (!(virNetClientStreamClass = virClassNew("virNetClientStream",
if (!(virNetClientStreamClass = virClassNew(virClassForObject(),
"virNetClientStream",
sizeof(virNetClientStream),
virNetClientStreamDispose)))
return -1;

View File

@ -55,12 +55,14 @@ static void virNetSASLSessionDispose(void *obj);
static int virNetSASLContextOnceInit(void)
{
if (!(virNetSASLContextClass = virClassNew("virNetSASLContext",
if (!(virNetSASLContextClass = virClassNew(virClassForObject(),
"virNetSASLContext",
sizeof(virNetSASLContext),
virNetSASLContextDispose)))
return -1;
if (!(virNetSASLSessionClass = virClassNew("virNetSASLSession",
if (!(virNetSASLSessionClass = virClassNew(virClassForObject(),
"virNetSASLSession",
sizeof(virNetSASLSession),
virNetSASLSessionDispose)))
return -1;

View File

@ -119,7 +119,8 @@ static void virNetServerDispose(void *obj);
static int virNetServerOnceInit(void)
{
if (!(virNetServerClass = virClassNew("virNetServer",
if (!(virNetServerClass = virClassNew(virClassForObject(),
"virNetServer",
sizeof(virNetServer),
virNetServerDispose)))
return -1;

View File

@ -112,7 +112,8 @@ static void virNetServerClientDispose(void *obj);
static int virNetServerClientOnceInit(void)
{
if (!(virNetServerClientClass = virClassNew("virNetServerClient",
if (!(virNetServerClientClass = virClassNew(virClassForObject(),
"virNetServerClient",
sizeof(virNetServerClient),
virNetServerClientDispose)))
return -1;

View File

@ -49,7 +49,8 @@ static void virNetServerProgramDispose(void *obj);
static int virNetServerProgramOnceInit(void)
{
if (!(virNetServerProgramClass = virClassNew("virNetServerProgram",
if (!(virNetServerProgramClass = virClassNew(virClassForObject(),
"virNetServerProgram",
sizeof(virNetServerProgram),
virNetServerProgramDispose)))
return -1;

View File

@ -55,7 +55,8 @@ static void virNetServerServiceDispose(void *obj);
static int virNetServerServiceOnceInit(void)
{
if (!(virNetServerServiceClass = virClassNew("virNetServerService",
if (!(virNetServerServiceClass = virClassNew(virClassForObject(),
"virNetServerService",
sizeof(virNetServerService),
virNetServerServiceDispose)))
return -1;

View File

@ -104,7 +104,8 @@ static void virNetSocketDispose(void *obj);
static int virNetSocketOnceInit(void)
{
if (!(virNetSocketClass = virClassNew("virNetSocket",
if (!(virNetSocketClass = virClassNew(virClassForObject(),
"virNetSocket",
sizeof(virNetSocket),
virNetSocketDispose)))
return -1;

View File

@ -161,7 +161,8 @@ static virClassPtr virNetSSHSessionClass;
static int
virNetSSHSessionOnceInit(void)
{
if (!(virNetSSHSessionClass = virClassNew("virNetSSHSession",
if (!(virNetSSHSessionClass = virClassNew(virClassForObject(),
"virNetSSHSession",
sizeof(virNetSSHSession),
virNetSSHSessionDispose)))
return -1;

View File

@ -85,12 +85,14 @@ static void virNetTLSSessionDispose(void *obj);
static int virNetTLSContextOnceInit(void)
{
if (!(virNetTLSContextClass = virClassNew("virNetTLSContext",
if (!(virNetTLSContextClass = virClassNew(virClassForObject(),
"virNetTLSContext",
sizeof(virNetTLSContext),
virNetTLSContextDispose)))
return -1;
if (!(virNetTLSSessionClass = virClassNew("virNetTLSSession",
if (!(virNetTLSSessionClass = virClassNew(virClassForObject(),
"virNetTLSSession",
sizeof(virNetTLSSession),
virNetTLSSessionDispose)))
return -1;

View File

@ -628,7 +628,8 @@ dnsmasqCapsDispose(void *obj)
static int dnsmasqCapsOnceInit(void)
{
if (!(dnsmasqCapsClass = virClassNew("dnsmasqCaps",
if (!(dnsmasqCapsClass = virClassNew(virClassForObject(),
"dnsmasqCaps",
sizeof(dnsmasqCaps),
dnsmasqCapsDispose))) {
return -1;

View File

@ -33,6 +33,8 @@
static unsigned int magicCounter = 0xCAFE0000;
struct _virClass {
virClassPtr parent;
unsigned int magic;
const char *name;
size_t objectSize;
@ -40,9 +42,39 @@ struct _virClass {
virObjectDisposeCallback dispose;
};
static virClassPtr virObjectClass;
static int virObjectOnceInit(void)
{
if (!(virObjectClass = virClassNew(NULL,
"virObject",
sizeof(virObject),
NULL)))
return -1;
return 0;
}
VIR_ONCE_GLOBAL_INIT(virObject);
/**
* virClassForObject:
*
* Returns the class instance for the base virObject type
*/
virClassPtr virClassForObject(void)
{
if (!virObjectInitialize() < 0)
return NULL;
return virObjectClass;
}
/**
* virClassNew:
* @parent: the parent class
* @name: the class name
* @objectSize: total size of the object struct
* @dispose: callback to run to free object fields
@ -56,15 +88,29 @@ struct _virClass {
*
* Returns a new class instance
*/
virClassPtr virClassNew(const char *name,
virClassPtr virClassNew(virClassPtr parent,
const char *name,
size_t objectSize,
virObjectDisposeCallback dispose)
{
virClassPtr klass;
if (parent == NULL &&
STRNEQ(name, "virObject")) {
virReportInvalidNonNullArg(parent);
return NULL;
} else if (parent &&
objectSize <= parent->objectSize) {
virReportInvalidArg(objectSize,
_("object size %zu of %s is smaller than parent class %zu"),
objectSize, name, parent->objectSize);
return NULL;
}
if (VIR_ALLOC(klass) < 0)
goto no_memory;
klass->parent = parent;
if (!(klass->name = strdup(name)))
goto no_memory;
klass->magic = virAtomicIntInc(&magicCounter);
@ -80,6 +126,27 @@ no_memory:
}
/**
* virClassIsDerivedFrom:
* @klass: the klass to check
* @parent: the possible parent class
*
* Determine if @klass is derived from @parent
*
* Return true if @klass is derived from @parent, false otherwise
*/
bool virClassIsDerivedFrom(virClassPtr klass,
virClassPtr parent)
{
while (klass) {
if (klass->magic == parent->magic)
return true;
klass = klass->parent;
}
return false;
}
/**
* virObjectNew:
* @klass: the klass of object to create
@ -135,8 +202,14 @@ bool virObjectUnref(void *anyobj)
PROBE(OBJECT_UNREF, "obj=%p", obj);
if (lastRef) {
PROBE(OBJECT_DISPOSE, "obj=%p", obj);
if (obj->klass->dispose)
obj->klass->dispose(obj);
virClassPtr klass = obj->klass;
while (klass) {
if (klass->dispose)
klass->dispose(obj);
klass = klass->parent;
}
virMutexDestroy(&obj->lock);
/* Clear & poison object */
memset(obj, 0, obj->klass->objectSize);
@ -184,7 +257,10 @@ bool virObjectIsClass(void *anyobj,
virClassPtr klass)
{
virObjectPtr obj = anyobj;
return obj != NULL && (obj->magic == klass->magic) && (obj->klass == klass);
if (!obj)
return false;
return virClassIsDerivedFrom(obj->klass, klass);
}

View File

@ -38,7 +38,10 @@ struct _virObject {
virClassPtr klass;
};
virClassPtr virClassNew(const char *name,
virClassPtr virClassForObject(void);
virClassPtr virClassNew(virClassPtr parent,
const char *name,
size_t objectSize,
virObjectDisposeCallback dispose)
ATTRIBUTE_NONNULL(1);
@ -46,6 +49,10 @@ virClassPtr virClassNew(const char *name,
const char *virClassName(virClassPtr klass)
ATTRIBUTE_NONNULL(1);
bool virClassIsDerivedFrom(virClassPtr klass,
virClassPtr parent)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void *virObjectNew(virClassPtr klass)
ATTRIBUTE_NONNULL(1);
bool virObjectUnref(void *obj);