Patchwork [01/29] Introduce QObject

login
register
mail settings
Submitter Luiz Capitulino
Date Aug. 19, 2009, 11:07 p.m.
Message ID <1250723280-3509-2-git-send-email-lcapitulino@redhat.com>
Download mbox | patch
Permalink /patch/31674/
State Superseded
Headers show

Comments

Luiz Capitulino - Aug. 19, 2009, 11:07 p.m.
This commit introduces the qobject.h header file, it contains
basic QObject definitions and helper macros.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qobject.h |  110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)
 create mode 100644 qobject.h
Paolo Bonzini - Aug. 20, 2009, 8:34 a.m.
> +/* High-level interface for qobject_incref() */
> +#define QINCREF(qtype)      \
> +#define QDECREF(qtype)              \

Why "qtype"?

Paolo
Paolo Bonzini - Aug. 20, 2009, 8:51 a.m.
> + *  - New reference: means that the caller is now the owner of a reference,
> + *    for example, if you call a function that returns a 'new reference' you
> + *    must call QDECREF() when you are done
> + *
> + *  - Borrowing a reference: nothing needs to be done, you are not the
> + *    owner of the reference
> + *
> + *  - Stealing a reference: when you pass a reference to a function that
> + *    'steals a reference' this function assumes that it now owns that
> + *    reference

I think the usual terms used here would be like

    - Returning references: A function that returns an object may
    return it as either a weak or a strong reference.  If the reference
    is strong, you are responsible for calling QDECREF() on the reference
    when you are done.

    If the reference is weak, the owner of the reference may free it at
    any time in the future.  Before storing the reference anywhere, you
    should call QINCREF() to make the reference strong.

    - Transferring ownership: when you transfer ownership of a reference
    by calling a function, you are no longer responsible for calling
    QDECREF() when the reference is no longer needed.  In other words,
    when the function returns you must behave as if the reference to the
    passed object
    was weak.

I'll post examples of using this terminology in the review of QDict.

Paolo
Luiz Capitulino - Aug. 20, 2009, 2:17 p.m.
On Thu, 20 Aug 2009 10:34:46 +0200
Paolo Bonzini <bonzini@gnu.org> wrote:

> 
> > +/* High-level interface for qobject_incref() */
> > +#define QINCREF(qtype)      \
> > +#define QDECREF(qtype)              \
> 
> Why "qtype"?

 Why not?
Paolo Bonzini - Aug. 20, 2009, 2:21 p.m.
On 08/20/2009 04:17 PM, Luiz Capitulino wrote:
> On Thu, 20 Aug 2009 10:34:46 +0200
> Paolo Bonzini<bonzini@gnu.org>  wrote:
>
>>
>>> +/* High-level interface for qobject_incref() */
>>> +#define QINCREF(qtype)      \
>>> +#define QDECREF(qtype)              \
>>
>> Why "qtype"?
>
>   Why not?

Because it's an object, not a type. :-)

+typedef struct QType {
+    qtype_code code;
+    void (*destroy)(struct QObject *);
+} QType;

...

+/* Get the QObject part of a type */
+#define QOBJECT(obj) (&obj->base)
+
+/* High-level interface for qobject_incref() */
+#define QINCREF(qtype)      \
+    assert(qtype != NULL);  \
+    qobject_incref(QOBJECT(qtype))

Paolo
Luiz Capitulino - Aug. 20, 2009, 3:12 p.m.
On Thu, 20 Aug 2009 16:21:58 +0200
Paolo Bonzini <bonzini@gnu.org> wrote:

> On 08/20/2009 04:17 PM, Luiz Capitulino wrote:
> > On Thu, 20 Aug 2009 10:34:46 +0200
> > Paolo Bonzini<bonzini@gnu.org>  wrote:
> >
> >>
> >>> +/* High-level interface for qobject_incref() */
> >>> +#define QINCREF(qtype)      \
> >>> +#define QDECREF(qtype)              \
> >>
> >> Why "qtype"?
> >
> >   Why not?
> 
> Because it's an object, not a type. :-)

 Actually, I'm calling anything with QType_HEAD a QType, this
implies that QINCREF() and QDECREF() expects a QType while
qobject_decref() and qobject_incref() expects a QObject.
Paolo Bonzini - Aug. 20, 2009, 3:15 p.m.
On 08/20/2009 05:12 PM, Luiz Capitulino wrote:
>   Actually, I'm calling anything with QType_HEAD a QType, this
> implies that QINCREF() and QDECREF() expects a QType while
> qobject_decref() and qobject_incref() expects a QObject.

But you have a struct QType. :-)

I don't have a really cool suggestion for a better naming, 
unfortunately.  Maybe QObject=>QObjectBase, QType=>QObject?

/me scratches head

Paolo

Patch

diff --git a/qobject.h b/qobject.h
new file mode 100644
index 0000000..c23b5f3
--- /dev/null
+++ b/qobject.h
@@ -0,0 +1,110 @@ 
+/*
+ * QEMU Object Model.
+ *
+ * Based on ideas by Avi Kivity <avi@redhat.com>
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * QObject Reference Counts
+ * ------------------------
+ *
+ *  The concept of reference counting used here is the same of Python, ie,
+ *  'ownership of references'.
+ *
+ *  Basic terminology:
+ *
+ *  - Owning a reference: means being responsible for calling QDECREF()
+ *    when the reference is no longer needed
+ *
+ *  - New reference: means that the caller is now the owner of a reference,
+ *    for example, if you call a function that returns a 'new reference' you
+ *    must call QDECREF() when you are done
+ *
+ *  - Borrowing a reference: nothing needs to be done, you are not the
+ *    owner of the reference
+ *
+ *  - Stealing a reference: when you pass a reference to a function that
+ *    'steals a reference' this function assumes that it now owns that
+ *    reference
+ */
+#ifndef QOBJECT_H
+#define QOBJECT_H
+
+#include <stddef.h>
+#include <assert.h>
+
+typedef enum {
+    QTYPE_NONE,
+} qtype_code;
+
+struct QObject;
+
+typedef struct QType {
+    qtype_code code;
+    void (*destroy)(struct QObject *);
+} QType;
+
+typedef struct QObject {
+    const QType *type;
+    size_t refcnt;
+} QObject;
+
+/* Type definitions must include this */
+#define QType_HEAD  \
+    QObject base;
+
+/* Get the QObject part of a type */
+#define QOBJECT(obj) (&obj->base)
+
+/* High-level interface for qobject_incref() */
+#define QINCREF(qtype)      \
+    assert(qtype != NULL);  \
+    qobject_incref(QOBJECT(qtype))
+
+/* High-level interface for qobject_decref() */
+#define QDECREF(qtype)              \
+    assert(qtype != NULL);          \
+    qobject_decref(QOBJECT(qtype))
+
+/* Initialize a type to default values */
+#define QOBJECT_INIT(qtype, qtype_type)   \
+    qtype->base.refcnt = 1;               \
+    qtype->base.type   = qtype_type
+
+/**
+ * qobject_incref(): Increment QObject's reference count
+ */
+static inline void qobject_incref(QObject *obj)
+{
+    obj->refcnt++;
+}
+
+/**
+ * qobject_decref(): Decrement QObject's reference count, deallocate
+ * when it reaches zero
+ */
+static inline void qobject_decref(QObject *obj)
+{
+    if (--obj->refcnt == 0) {
+        assert(obj->type != NULL);
+        assert(obj->type->destroy != NULL);
+        obj->type->destroy(obj);
+    }
+}
+
+/**
+ * qobject_type(): Return the QObject's type
+ */
+static inline qtype_code qobject_type(const QObject *obj)
+{
+    assert(obj->type != NULL);
+    return obj->type->code;
+}
+
+#endif /* QOBJECT_H */