Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
/*
|
|
|
|
* virobject.c: libvirt reference counted object
|
|
|
|
*
|
2014-04-04 23:36:25 +00:00
|
|
|
* Copyright (C) 2012-2014 Red Hat, Inc.
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2013-01-22 17:13:01 +00:00
|
|
|
#define VIR_PARENT_REQUIRED /* empty, to allow virObject to have no parent */
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
#include "virobject.h"
|
2012-12-13 15:49:48 +00:00
|
|
|
#include "virthread.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
#include "viratomic.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2014-02-27 13:41:11 +00:00
|
|
|
#include "virprobe.h"
|
2013-05-24 07:19:51 +00:00
|
|
|
#include "virstring.h"
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.object");
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
static unsigned int magicCounter = 0xCAFE0000;
|
|
|
|
|
|
|
|
struct _virClass {
|
2013-01-09 17:37:27 +00:00
|
|
|
virClassPtr parent;
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
unsigned int magic;
|
2013-05-24 07:19:51 +00:00
|
|
|
char *name;
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
size_t objectSize;
|
|
|
|
|
|
|
|
virObjectDisposeCallback dispose;
|
|
|
|
};
|
|
|
|
|
util: Add magic number check for object validity
The virObjectIsClass API has only ever checked object validity
based on if the @obj is not NULL and it was derived from some class.
While this has worked well in general, there is one additional
check that could be made prior to calling virClassIsDerivedFrom
which loops through the classes checking the magic number against
the klass expected magic number.
If by chance a non virObject is passed, rather than assuming the
void * @obj is a _virObject and thus offsetting to obj->klass,
obj->magic, and obj->parent, let's check that the void * @obj
has at least the "base part" of the magic number in the right
place and generate a more specific VIR_WARN message if not.
There are many consumers to virObjectIsClass, include the locking
primitives virObject{Lock|Unlock}, virObjectRWLock{Read|Write},
and virObjectRWUnlock. For those callers, the locking call will
not fail, but it also will not attempt a virMutex* call which
will "most likely" fail since the &obj->lock is used.
In order to avoid some possible future wrap on the 0xCAFExxxx
value, add a check during initialization that some new class
won't cause the wrap. Should be good for a few years at least!
It is still left up to the caller to handle the failed API calls
just as it would be if it passed a NULL opaque pointer anyobj.
2017-07-31 22:58:55 +00:00
|
|
|
#define VIR_OBJECT_NOTVALID(obj) (!obj || ((obj->u.s.magic & 0xFFFF0000) != 0xCAFE0000))
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, objclass) \
|
|
|
|
do { \
|
|
|
|
virObjectPtr obj = anyobj; \
|
|
|
|
if (VIR_OBJECT_NOTVALID(obj)) { \
|
|
|
|
if (!obj) \
|
|
|
|
VIR_WARN("Object cannot be NULL"); \
|
|
|
|
else \
|
|
|
|
VIR_WARN("Object %p has a bad magic number %X", \
|
|
|
|
obj, obj->u.s.magic); \
|
|
|
|
} else { \
|
|
|
|
VIR_WARN("Object %p (%s) is not a %s instance", \
|
2018-09-19 08:38:14 +00:00
|
|
|
anyobj, obj->klass->name, #objclass); \
|
2017-11-03 12:09:47 +00:00
|
|
|
} \
|
2017-07-28 15:09:31 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
2013-01-09 17:37:27 +00:00
|
|
|
static virClassPtr virObjectClass;
|
2013-01-09 17:54:07 +00:00
|
|
|
static virClassPtr virObjectLockableClass;
|
2017-07-19 07:31:50 +00:00
|
|
|
static virClassPtr virObjectRWLockableClass;
|
2013-01-09 17:54:07 +00:00
|
|
|
|
|
|
|
static void virObjectLockableDispose(void *anyobj);
|
2017-07-19 07:31:50 +00:00
|
|
|
static void virObjectRWLockableDispose(void *anyobj);
|
2013-01-09 17:37:27 +00:00
|
|
|
|
2017-03-28 19:09:55 +00:00
|
|
|
static int
|
|
|
|
virObjectOnceInit(void)
|
2013-01-09 17:37:27 +00:00
|
|
|
{
|
|
|
|
if (!(virObjectClass = virClassNew(NULL,
|
|
|
|
"virObject",
|
|
|
|
sizeof(virObject),
|
2019-03-15 14:41:18 +00:00
|
|
|
0,
|
2013-01-09 17:37:27 +00:00
|
|
|
NULL)))
|
|
|
|
return -1;
|
|
|
|
|
2018-04-17 15:42:33 +00:00
|
|
|
if (!VIR_CLASS_NEW(virObjectLockable, virObjectClass))
|
2013-01-09 17:54:07 +00:00
|
|
|
return -1;
|
|
|
|
|
2018-04-17 15:42:33 +00:00
|
|
|
if (!VIR_CLASS_NEW(virObjectRWLockable, virObjectClass))
|
2017-07-19 07:31:50 +00:00
|
|
|
return -1;
|
|
|
|
|
2013-01-09 17:37:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_ONCE_GLOBAL_INIT(virObject);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virClassForObject:
|
|
|
|
*
|
|
|
|
* Returns the class instance for the base virObject type
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
virClassPtr
|
|
|
|
virClassForObject(void)
|
2013-01-09 17:37:27 +00:00
|
|
|
{
|
2013-01-17 19:17:14 +00:00
|
|
|
if (virObjectInitialize() < 0)
|
2013-01-09 17:37:27 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return virObjectClass;
|
|
|
|
}
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
|
2013-01-09 17:54:07 +00:00
|
|
|
/**
|
|
|
|
* virClassForObjectLockable:
|
|
|
|
*
|
|
|
|
* Returns the class instance for the virObjectLockable type
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
virClassPtr
|
|
|
|
virClassForObjectLockable(void)
|
2013-01-09 17:54:07 +00:00
|
|
|
{
|
2013-01-17 19:17:14 +00:00
|
|
|
if (virObjectInitialize() < 0)
|
2013-01-09 17:54:07 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return virObjectLockableClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-19 07:31:50 +00:00
|
|
|
/**
|
|
|
|
* virClassForObjectRWLockable:
|
|
|
|
*
|
|
|
|
* Returns the class instance for the virObjectRWLockable type
|
|
|
|
*/
|
|
|
|
virClassPtr
|
|
|
|
virClassForObjectRWLockable(void)
|
|
|
|
{
|
|
|
|
if (virObjectInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return virObjectRWLockableClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
/**
|
|
|
|
* virClassNew:
|
2013-01-09 17:37:27 +00:00
|
|
|
* @parent: the parent class
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
* @name: the class name
|
|
|
|
* @objectSize: total size of the object struct
|
|
|
|
* @dispose: callback to run to free object fields
|
|
|
|
*
|
|
|
|
* Register a new object class with @name. The @objectSize
|
|
|
|
* should give the total size of the object struct, which
|
2019-03-15 04:14:41 +00:00
|
|
|
* is expected to have a 'virObject parent;' field as (or
|
|
|
|
* contained in) its first member. When the last reference
|
|
|
|
* on the object is released, the @dispose callback will be
|
|
|
|
* invoked to free memory of the local object fields, as
|
|
|
|
* well as the dispose callbacks of the parent classes.
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
*
|
|
|
|
* Returns a new class instance
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
virClassPtr
|
|
|
|
virClassNew(virClassPtr parent,
|
|
|
|
const char *name,
|
|
|
|
size_t objectSize,
|
2019-03-15 14:41:18 +00:00
|
|
|
size_t parentSize,
|
2017-03-28 19:09:55 +00:00
|
|
|
virObjectDisposeCallback dispose)
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
{
|
|
|
|
virClassPtr klass;
|
|
|
|
|
2013-01-09 17:37:27 +00:00
|
|
|
if (parent == NULL &&
|
|
|
|
STRNEQ(name, "virObject")) {
|
|
|
|
virReportInvalidNonNullArg(parent);
|
|
|
|
return NULL;
|
2019-03-15 14:41:18 +00:00
|
|
|
} else if (objectSize <= parentSize ||
|
|
|
|
parentSize != (parent ? parent->objectSize : 0)) {
|
|
|
|
sa_assert(parent);
|
2013-01-09 17:37:27 +00:00
|
|
|
virReportInvalidArg(objectSize,
|
2019-03-15 14:41:18 +00:00
|
|
|
_("object size %zu of %s is not larger than parent class %zu"),
|
2013-01-09 17:37:27 +00:00
|
|
|
objectSize, name, parent->objectSize);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-04 10:17:18 +00:00
|
|
|
if (VIR_ALLOC(klass) < 0)
|
2013-05-24 07:19:51 +00:00
|
|
|
goto error;
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
|
2013-01-09 17:37:27 +00:00
|
|
|
klass->parent = parent;
|
util: Add magic number check for object validity
The virObjectIsClass API has only ever checked object validity
based on if the @obj is not NULL and it was derived from some class.
While this has worked well in general, there is one additional
check that could be made prior to calling virClassIsDerivedFrom
which loops through the classes checking the magic number against
the klass expected magic number.
If by chance a non virObject is passed, rather than assuming the
void * @obj is a _virObject and thus offsetting to obj->klass,
obj->magic, and obj->parent, let's check that the void * @obj
has at least the "base part" of the magic number in the right
place and generate a more specific VIR_WARN message if not.
There are many consumers to virObjectIsClass, include the locking
primitives virObject{Lock|Unlock}, virObjectRWLock{Read|Write},
and virObjectRWUnlock. For those callers, the locking call will
not fail, but it also will not attempt a virMutex* call which
will "most likely" fail since the &obj->lock is used.
In order to avoid some possible future wrap on the 0xCAFExxxx
value, add a check during initialization that some new class
won't cause the wrap. Should be good for a few years at least!
It is still left up to the caller to handle the failed API calls
just as it would be if it passed a NULL opaque pointer anyobj.
2017-07-31 22:58:55 +00:00
|
|
|
klass->magic = virAtomicIntInc(&magicCounter);
|
|
|
|
if (klass->magic > 0xCAFEFFFF) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("too many object classes defined"));
|
|
|
|
goto error;
|
|
|
|
}
|
2019-10-20 11:49:46 +00:00
|
|
|
klass->name = g_strdup(name);
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
klass->objectSize = objectSize;
|
|
|
|
klass->dispose = dispose;
|
|
|
|
|
|
|
|
return klass;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
error:
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
VIR_FREE(klass);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-09 17:37:27 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
bool
|
|
|
|
virClassIsDerivedFrom(virClassPtr klass,
|
|
|
|
virClassPtr parent)
|
2013-01-09 17:37:27 +00:00
|
|
|
{
|
|
|
|
while (klass) {
|
|
|
|
if (klass->magic == parent->magic)
|
|
|
|
return true;
|
|
|
|
klass = klass->parent;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
/**
|
|
|
|
* virObjectNew:
|
|
|
|
* @klass: the klass of object to create
|
|
|
|
*
|
|
|
|
* Allocates a new object of type @klass. The returned
|
|
|
|
* object will be an instance of "virObjectPtr", which
|
|
|
|
* can be cast to the struct associated with @klass.
|
|
|
|
*
|
|
|
|
* The initial reference count of the object will be 1.
|
|
|
|
*
|
|
|
|
* Returns the new object
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
void *
|
|
|
|
virObjectNew(virClassPtr klass)
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
{
|
|
|
|
virObjectPtr obj = NULL;
|
|
|
|
|
2013-04-03 13:14:23 +00:00
|
|
|
if (VIR_ALLOC_VAR(obj,
|
|
|
|
char,
|
2013-07-04 10:17:18 +00:00
|
|
|
klass->objectSize - sizeof(virObject)) < 0)
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
return NULL;
|
|
|
|
|
object: require maximal alignment in base class
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors
The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'. The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space. On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.
Reported by Michele Paolino and others.
* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-12 23:01:15 +00:00
|
|
|
obj->u.s.magic = klass->magic;
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
obj->klass = klass;
|
object: require maximal alignment in base class
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors
The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'. The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space. On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.
Reported by Michele Paolino and others.
* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-12 23:01:15 +00:00
|
|
|
virAtomicIntSet(&obj->u.s.refs, 1);
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
|
|
|
|
PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, obj->klass->name);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-28 19:09:55 +00:00
|
|
|
void *
|
|
|
|
virObjectLockableNew(virClassPtr klass)
|
2013-01-09 17:54:07 +00:00
|
|
|
{
|
|
|
|
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) {
|
2014-11-28 08:37:42 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unable to initialize mutex"));
|
2013-01-09 17:54:07 +00:00
|
|
|
virObjectUnref(obj);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-19 07:31:50 +00:00
|
|
|
void *
|
|
|
|
virObjectRWLockableNew(virClassPtr klass)
|
|
|
|
{
|
|
|
|
virObjectRWLockablePtr obj;
|
|
|
|
|
|
|
|
if (!virClassIsDerivedFrom(klass, virClassForObjectRWLockable())) {
|
|
|
|
virReportInvalidArg(klass,
|
|
|
|
_("Class %s must derive from virObjectRWLockable"),
|
|
|
|
virClassName(klass));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(obj = virObjectNew(klass)))
|
|
|
|
return NULL;
|
|
|
|
|
2017-07-25 08:31:54 +00:00
|
|
|
if (virRWLockInit(&obj->lock) < 0) {
|
2017-07-19 07:31:50 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unable to initialize RW lock"));
|
|
|
|
virObjectUnref(obj);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-28 19:09:55 +00:00
|
|
|
static void
|
|
|
|
virObjectLockableDispose(void *anyobj)
|
2013-01-09 17:54:07 +00:00
|
|
|
{
|
|
|
|
virObjectLockablePtr obj = anyobj;
|
|
|
|
|
|
|
|
virMutexDestroy(&obj->lock);
|
|
|
|
}
|
|
|
|
|
2017-03-28 19:09:55 +00:00
|
|
|
|
2017-07-19 07:31:50 +00:00
|
|
|
static void
|
|
|
|
virObjectRWLockableDispose(void *anyobj)
|
|
|
|
{
|
|
|
|
virObjectRWLockablePtr obj = anyobj;
|
|
|
|
|
|
|
|
virRWLockDestroy(&obj->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
/**
|
|
|
|
* virObjectUnref:
|
|
|
|
* @anyobj: any instance of virObjectPtr
|
|
|
|
*
|
|
|
|
* Decrement the reference count on @anyobj and if
|
2019-03-15 04:14:41 +00:00
|
|
|
* it hits zero, runs the "dispose" callbacks associated
|
|
|
|
* with the object class and its parents before freeing
|
|
|
|
* @anyobj.
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
*
|
|
|
|
* Returns true if the remaining reference count is
|
|
|
|
* non-zero, false if the object was disposed of
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
bool
|
|
|
|
virObjectUnref(void *anyobj)
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
{
|
|
|
|
virObjectPtr obj = anyobj;
|
|
|
|
|
2017-03-31 15:35:05 +00:00
|
|
|
if (VIR_OBJECT_NOTVALID(obj))
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
return false;
|
|
|
|
|
object: require maximal alignment in base class
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors
The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'. The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space. On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.
Reported by Michele Paolino and others.
* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-12 23:01:15 +00:00
|
|
|
bool lastRef = virAtomicIntDecAndTest(&obj->u.s.refs);
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
PROBE(OBJECT_UNREF, "obj=%p", obj);
|
|
|
|
if (lastRef) {
|
|
|
|
PROBE(OBJECT_DISPOSE, "obj=%p", obj);
|
2013-01-09 17:37:27 +00:00
|
|
|
virClassPtr klass = obj->klass;
|
|
|
|
while (klass) {
|
|
|
|
if (klass->dispose)
|
|
|
|
klass->dispose(obj);
|
|
|
|
klass = klass->parent;
|
|
|
|
}
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
/* Clear & poison object */
|
|
|
|
memset(obj, 0, obj->klass->objectSize);
|
object: require maximal alignment in base class
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors
The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'. The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space. On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.
Reported by Michele Paolino and others.
* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-12 23:01:15 +00:00
|
|
|
obj->u.s.magic = 0xDEADBEEF;
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
obj->klass = (void*)0xDEADBEEF;
|
|
|
|
VIR_FREE(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
return !lastRef;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virObjectRef:
|
|
|
|
* @anyobj: any instance of virObjectPtr
|
|
|
|
*
|
|
|
|
* Increment the reference count on @anyobj and return
|
|
|
|
* the same pointer
|
|
|
|
*
|
|
|
|
* Returns @anyobj
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
void *
|
|
|
|
virObjectRef(void *anyobj)
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
{
|
|
|
|
virObjectPtr obj = anyobj;
|
|
|
|
|
2017-03-31 15:35:05 +00:00
|
|
|
if (VIR_OBJECT_NOTVALID(obj))
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
return NULL;
|
object: require maximal alignment in base class
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors
The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'. The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space. On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.
Reported by Michele Paolino and others.
* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-12 23:01:15 +00:00
|
|
|
virAtomicIntInc(&obj->u.s.refs);
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
PROBE(OBJECT_REF, "obj=%p", obj);
|
|
|
|
return anyobj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-28 14:14:40 +00:00
|
|
|
static virObjectLockablePtr
|
|
|
|
virObjectGetLockableObj(void *anyobj)
|
|
|
|
{
|
|
|
|
if (virObjectIsClass(anyobj, virObjectLockableClass))
|
|
|
|
return anyobj;
|
|
|
|
|
2017-07-28 15:09:31 +00:00
|
|
|
VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, virObjectLockable);
|
2017-07-28 14:14:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-28 14:27:11 +00:00
|
|
|
static virObjectRWLockablePtr
|
|
|
|
virObjectGetRWLockableObj(void *anyobj)
|
|
|
|
{
|
|
|
|
if (virObjectIsClass(anyobj, virObjectRWLockableClass))
|
|
|
|
return anyobj;
|
|
|
|
|
2017-07-28 15:09:31 +00:00
|
|
|
VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, virObjectRWLockable);
|
2017-07-28 14:27:11 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-19 07:31:50 +00:00
|
|
|
/**
|
|
|
|
* virObjectLock:
|
2018-05-11 17:48:26 +00:00
|
|
|
* @anyobj: any instance of virObjectLockable
|
2017-07-19 07:31:50 +00:00
|
|
|
*
|
|
|
|
* Acquire a lock on @anyobj. The lock must be released by
|
2017-07-28 14:14:40 +00:00
|
|
|
* virObjectUnlock.
|
2017-07-19 07:31:50 +00:00
|
|
|
*
|
|
|
|
* 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)
|
2017-03-29 20:21:31 +00:00
|
|
|
{
|
2017-07-28 14:14:40 +00:00
|
|
|
virObjectLockablePtr obj = virObjectGetLockableObj(anyobj);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virMutexLock(&obj->lock);
|
2017-03-29 20:21:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-09 17:54:07 +00:00
|
|
|
/**
|
2017-07-28 13:57:04 +00:00
|
|
|
* virObjectRWLockRead:
|
2017-07-19 07:31:50 +00:00
|
|
|
* @anyobj: any instance of virObjectRWLockable
|
2013-01-09 17:54:07 +00:00
|
|
|
*
|
2017-07-19 07:31:50 +00:00
|
|
|
* Acquire a read lock on @anyobj. The lock must be
|
2017-07-28 16:03:50 +00:00
|
|
|
* released by virObjectRWUnlock.
|
2013-01-09 17:54:07 +00:00
|
|
|
*
|
|
|
|
* 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.
|
2017-07-28 13:57:04 +00:00
|
|
|
*
|
|
|
|
* NB: It's possible to return without the lock if
|
|
|
|
* @anyobj was invalid - this has been considered
|
|
|
|
* a programming error rather than something that
|
|
|
|
* should be checked.
|
2013-01-09 17:54:07 +00:00
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
void
|
2017-07-28 13:57:04 +00:00
|
|
|
virObjectRWLockRead(void *anyobj)
|
2013-01-09 17:54:07 +00:00
|
|
|
{
|
2017-07-28 14:27:11 +00:00
|
|
|
virObjectRWLockablePtr obj = virObjectGetRWLockableObj(anyobj);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virRWLockRead(&obj->lock);
|
2013-01-09 17:54:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-28 14:06:55 +00:00
|
|
|
/**
|
|
|
|
* virObjectRWLockWrite:
|
|
|
|
* @anyobj: any instance of virObjectRWLockable
|
|
|
|
*
|
|
|
|
* Acquire a write lock on @anyobj. The lock must be
|
2017-07-28 16:03:50 +00:00
|
|
|
* released by virObjectRWUnlock.
|
2017-07-28 14:06:55 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* NB: It's possible to return without the lock if
|
|
|
|
* @anyobj was invalid - this has been considered
|
|
|
|
* a programming error rather than something that
|
|
|
|
* should be checked.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virObjectRWLockWrite(void *anyobj)
|
|
|
|
{
|
2017-07-28 14:27:11 +00:00
|
|
|
virObjectRWLockablePtr obj = virObjectGetRWLockableObj(anyobj);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virRWLockWrite(&obj->lock);
|
2017-07-28 14:06:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-09 17:54:07 +00:00
|
|
|
/**
|
|
|
|
* virObjectUnlock:
|
2017-07-28 16:03:50 +00:00
|
|
|
* @anyobj: any instance of virObjectLockable
|
2013-01-09 17:54:07 +00:00
|
|
|
*
|
2017-07-19 07:31:50 +00:00
|
|
|
* Release a lock on @anyobj. The lock must have been acquired by
|
2017-07-28 16:03:50 +00:00
|
|
|
* virObjectLock.
|
2013-01-09 17:54:07 +00:00
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
void
|
|
|
|
virObjectUnlock(void *anyobj)
|
2013-01-09 17:54:07 +00:00
|
|
|
{
|
2017-07-28 16:03:50 +00:00
|
|
|
virObjectLockablePtr obj = virObjectGetLockableObj(anyobj);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virMutexUnlock(&obj->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virObjectRWUnlock:
|
|
|
|
* @anyobj: any instance of virObjectRWLockable
|
|
|
|
*
|
|
|
|
* Release a lock on @anyobj. The lock must have been acquired by
|
|
|
|
* virObjectRWLockRead or virObjectRWLockWrite.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virObjectRWUnlock(void *anyobj)
|
|
|
|
{
|
|
|
|
virObjectRWLockablePtr obj = virObjectGetRWLockableObj(anyobj);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virRWLockUnlock(&obj->lock);
|
2013-01-09 17:54:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
/**
|
|
|
|
* virObjectIsClass:
|
|
|
|
* @anyobj: any instance of virObjectPtr
|
|
|
|
* @klass: the class to check
|
|
|
|
*
|
|
|
|
* Checks whether @anyobj is an instance of
|
|
|
|
* @klass
|
|
|
|
*
|
|
|
|
* Returns true if @anyobj is an instance of @klass
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
bool
|
|
|
|
virObjectIsClass(void *anyobj,
|
|
|
|
virClassPtr klass)
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
{
|
|
|
|
virObjectPtr obj = anyobj;
|
util: Add magic number check for object validity
The virObjectIsClass API has only ever checked object validity
based on if the @obj is not NULL and it was derived from some class.
While this has worked well in general, there is one additional
check that could be made prior to calling virClassIsDerivedFrom
which loops through the classes checking the magic number against
the klass expected magic number.
If by chance a non virObject is passed, rather than assuming the
void * @obj is a _virObject and thus offsetting to obj->klass,
obj->magic, and obj->parent, let's check that the void * @obj
has at least the "base part" of the magic number in the right
place and generate a more specific VIR_WARN message if not.
There are many consumers to virObjectIsClass, include the locking
primitives virObject{Lock|Unlock}, virObjectRWLock{Read|Write},
and virObjectRWUnlock. For those callers, the locking call will
not fail, but it also will not attempt a virMutex* call which
will "most likely" fail since the &obj->lock is used.
In order to avoid some possible future wrap on the 0xCAFExxxx
value, add a check during initialization that some new class
won't cause the wrap. Should be good for a few years at least!
It is still left up to the caller to handle the failed API calls
just as it would be if it passed a NULL opaque pointer anyobj.
2017-07-31 22:58:55 +00:00
|
|
|
if (VIR_OBJECT_NOTVALID(obj))
|
2013-01-09 17:37:27 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return virClassIsDerivedFrom(obj->klass, klass);
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virClassName:
|
|
|
|
* @klass: the object class
|
|
|
|
*
|
|
|
|
* Returns the name of @klass
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
const char *
|
|
|
|
virClassName(virClassPtr klass)
|
Add a generic reference counted virObject type
This introduces a fairly basic reference counted virObject type
and an associated virClass type, that use atomic operations for
ref counting.
In a global initializer (recommended to be invoked using the
virOnceInit API), a virClass type must be allocated for each
object type. This requires a class name, a "dispose" callback
which will be invoked to free memory associated with the object's
fields, and the size in bytes of the object struct.
eg,
virClassPtr connclass = virClassNew("virConnect",
sizeof(virConnect),
virConnectDispose);
The struct for the object, must include 'virObject' as its
first member
eg
struct _virConnect {
virObject object;
virURIPtr uri;
};
The 'dispose' callback is only responsible for freeing
fields in the object, not the object itself. eg a suitable
impl for the above struct would be
void virConnectDispose(void *obj) {
virConnectPtr conn = obj;
virURIFree(conn->uri);
}
There is no need to reset fields to 'NULL' or '0' in the
dispose callback, since the entire object will be memset
to 0, and the klass pointer & magic integer fields will
be poisoned with 0xDEADBEEF before being free()d
When creating an instance of an object, one needs simply
pass the virClassPtr eg
virConnectPtr conn = virObjectNew(connclass);
if (!conn)
return NULL;
conn->uri = virURIParse("foo:///bar")
Object references can be manipulated with
virObjectRef(conn)
virObjectUnref(conn)
The latter returns a true value, if the object has been
freed (ie its ref count hit zero)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-11 13:35:44 +00:00
|
|
|
{
|
|
|
|
return klass->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virObjectFreeCallback:
|
|
|
|
* @opaque: a pointer to a virObject instance
|
|
|
|
*
|
|
|
|
* Provides identical functionality to virObjectUnref,
|
|
|
|
* but with the signature matching the virFreeCallback
|
|
|
|
* typedef.
|
|
|
|
*/
|
|
|
|
void virObjectFreeCallback(void *opaque)
|
|
|
|
{
|
|
|
|
virObjectUnref(opaque);
|
|
|
|
}
|
2014-04-04 23:36:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virObjectFreeHashData:
|
|
|
|
* @opaque: a pointer to a virObject instance
|
|
|
|
* @name: ignored, name of the hash key being deleted
|
|
|
|
*
|
|
|
|
* Provides identical functionality to virObjectUnref,
|
|
|
|
* but with the signature matching the virHashDataFree
|
|
|
|
* typedef.
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
void
|
2019-11-21 19:27:58 +00:00
|
|
|
virObjectFreeHashData(void *opaque)
|
2014-04-04 23:36:25 +00:00
|
|
|
{
|
|
|
|
virObjectUnref(opaque);
|
|
|
|
}
|
2015-04-29 09:54:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virObjectListFree:
|
|
|
|
* @list: A pointer to a NULL-terminated list of object pointers to free
|
|
|
|
*
|
|
|
|
* Unrefs all members of @list and frees the list itself.
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
void
|
|
|
|
virObjectListFree(void *list)
|
2015-04-29 09:54:58 +00:00
|
|
|
{
|
|
|
|
void **next;
|
|
|
|
|
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (next = (void **) list; *next; next++)
|
|
|
|
virObjectUnref(*next);
|
|
|
|
|
|
|
|
VIR_FREE(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virObjectListFreeCount:
|
|
|
|
* @list: A pointer to a list of object pointers to freea
|
|
|
|
* @count: Number of elements in the list.
|
|
|
|
*
|
|
|
|
* Unrefs all members of @list and frees the list itself.
|
|
|
|
*/
|
2017-03-28 19:09:55 +00:00
|
|
|
void
|
|
|
|
virObjectListFreeCount(void *list,
|
|
|
|
size_t count)
|
2015-04-29 09:54:58 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
virObjectUnref(((void **)list)[i]);
|
|
|
|
|
|
|
|
VIR_FREE(list);
|
|
|
|
}
|