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>
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
static int virDomainObjOnceInit(void)
{
- if (!(virDomainObjClass = virClassNew("virDomainObj",
+ if (!(virDomainObjClass = virClassNew(virClassForObject(),
+ "virDomainObj",
sizeof(virDomainObj),
virDomainObjDispose)))
return -1;
virDataTypesOnceInit(void)
{
#define DECLARE_CLASS(basename) \
- if (!(basename ## Class = virClassNew(#basename, \
+ if (!(basename ## Class = virClassNew(virClassForObject(), \
+ #basename, \
sizeof(basename), \
basename ## Dispose))) \
return -1;
# virobject.h
+virClassForObject;
+virClassIsDerivedFrom;
virClassName;
virClassNew;
virObjectFreeCallback;
static int virLXCMonitorOnceInit(void)
{
- if (!(virLXCMonitorClass = virClassNew("virLXCMonitor",
+ if (!(virLXCMonitorClass = virClassNew(virClassForObject(),
+ "virLXCMonitor",
sizeof(virLXCMonitor),
virLXCMonitorDispose)))
return -1;
static int qemuAgentOnceInit(void)
{
- if (!(qemuAgentClass = virClassNew("qemuAgent",
+ if (!(qemuAgentClass = virClassNew(virClassForObject(),
+ "qemuAgent",
sizeof(qemuAgent),
qemuAgentDispose)))
return -1;
static int qemuCapsOnceInit(void)
{
- if (!(qemuCapsClass = virClassNew("qemuCaps",
+ if (!(qemuCapsClass = virClassNew(virClassForObject(),
+ "qemuCaps",
sizeof(qemuCaps),
qemuCapsDispose)))
return -1;
static int qemuMonitorOnceInit(void)
{
- if (!(qemuMonitorClass = virClassNew("qemuMonitor",
- sizeof(qemuMonitor),
- qemuMonitorDispose)))
+ if (!(qemuMonitorClass = virClassNew(virClassForObject(),
+ "qemuMonitor",
+ sizeof(qemuMonitor),
+ qemuMonitorDispose)))
return -1;
return 0;
static int virKeepAliveOnceInit(void)
{
- if (!(virKeepAliveClass = virClassNew("virKeepAlive",
+ if (!(virKeepAliveClass = virClassNew(virClassForObject(),
+ "virKeepAlive",
sizeof(virKeepAlive),
virKeepAliveDispose)))
return -1;
static int virNetClientOnceInit(void)
{
- if (!(virNetClientClass = virClassNew("virNetClient",
+ if (!(virNetClientClass = virClassNew(virClassForObject(),
+ "virNetClient",
sizeof(virNetClient),
virNetClientDispose)))
return -1;
static int virNetClientProgramOnceInit(void)
{
- if (!(virNetClientProgramClass = virClassNew("virNetClientProgram",
+ if (!(virNetClientProgramClass = virClassNew(virClassForObject(),
+ "virNetClientProgram",
sizeof(virNetClientProgram),
virNetClientProgramDispose)))
return -1;
static int virNetClientStreamOnceInit(void)
{
- if (!(virNetClientStreamClass = virClassNew("virNetClientStream",
+ if (!(virNetClientStreamClass = virClassNew(virClassForObject(),
+ "virNetClientStream",
sizeof(virNetClientStream),
virNetClientStreamDispose)))
return -1;
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;
static int virNetServerOnceInit(void)
{
- if (!(virNetServerClass = virClassNew("virNetServer",
+ if (!(virNetServerClass = virClassNew(virClassForObject(),
+ "virNetServer",
sizeof(virNetServer),
virNetServerDispose)))
return -1;
static int virNetServerClientOnceInit(void)
{
- if (!(virNetServerClientClass = virClassNew("virNetServerClient",
+ if (!(virNetServerClientClass = virClassNew(virClassForObject(),
+ "virNetServerClient",
sizeof(virNetServerClient),
virNetServerClientDispose)))
return -1;
static int virNetServerProgramOnceInit(void)
{
- if (!(virNetServerProgramClass = virClassNew("virNetServerProgram",
+ if (!(virNetServerProgramClass = virClassNew(virClassForObject(),
+ "virNetServerProgram",
sizeof(virNetServerProgram),
virNetServerProgramDispose)))
return -1;
static int virNetServerServiceOnceInit(void)
{
- if (!(virNetServerServiceClass = virClassNew("virNetServerService",
+ if (!(virNetServerServiceClass = virClassNew(virClassForObject(),
+ "virNetServerService",
sizeof(virNetServerService),
virNetServerServiceDispose)))
return -1;
static int virNetSocketOnceInit(void)
{
- if (!(virNetSocketClass = virClassNew("virNetSocket",
+ if (!(virNetSocketClass = virClassNew(virClassForObject(),
+ "virNetSocket",
sizeof(virNetSocket),
virNetSocketDispose)))
return -1;
static int
virNetSSHSessionOnceInit(void)
{
- if (!(virNetSSHSessionClass = virClassNew("virNetSSHSession",
+ if (!(virNetSSHSessionClass = virClassNew(virClassForObject(),
+ "virNetSSHSession",
sizeof(virNetSSHSession),
virNetSSHSessionDispose)))
return -1;
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;
static int dnsmasqCapsOnceInit(void)
{
- if (!(dnsmasqCapsClass = virClassNew("dnsmasqCaps",
+ if (!(dnsmasqCapsClass = virClassNew(virClassForObject(),
+ "dnsmasqCaps",
sizeof(dnsmasqCaps),
dnsmasqCapsDispose))) {
return -1;
static unsigned int magicCounter = 0xCAFE0000;
struct _virClass {
+ virClassPtr parent;
+
unsigned int magic;
const char *name;
size_t objectSize;
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
*
* 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);
}
+/**
+ * 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
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);
virClassPtr klass)
{
virObjectPtr obj = anyobj;
- return obj != NULL && (obj->magic == klass->magic) && (obj->klass == klass);
+ if (!obj)
+ return false;
+
+ return virClassIsDerivedFrom(obj->klass, klass);
}
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);
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);