[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v2 2/2] Add virObject and virAtomic.



virObject is the base struct that manages reference-counting
for all structs that need the ability of reference-counting.

virAtomic provides atomic operations which are thread-safe.
---
 src/Makefile.am          |    2 +
 src/libvirt_private.syms |   11 ++++++
 src/util/viratomic.c     |   80 ++++++++++++++++++++++++++++++++++++++++++
 src/util/viratomic.h     |   32 +++++++++++++++++
 src/util/virobject.c     |   64 ++++++++++++++++++++++++++++++++++
 src/util/virobject.h     |   86 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 275 insertions(+), 0 deletions(-)
 create mode 100644 src/util/viratomic.c
 create mode 100644 src/util/viratomic.h
 create mode 100644 src/util/virobject.c
 create mode 100644 src/util/virobject.h

diff --git a/src/Makefile.am b/src/Makefile.am
index dce866e..cb8acc3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -81,6 +81,8 @@ UTIL_SOURCES =							\
 		util/util.c util/util.h				\
 		util/xml.c util/xml.h				\
 		util/virtaudit.c util/virtaudit.h               \
+		util/viratomic.c util/viratomic.h	\
+		util/virobject.c util/virobject.h	\
 		util/virterror.c util/virterror_internal.h
 
 EXTRA_DIST += util/threads-pthread.c util/threads-win32.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 54e4482..a33e877 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -958,6 +958,17 @@ virUUIDGenerate;
 virUUIDParse;
 
 
+# virobject.h
+virObjectInit;
+virObjectRef;
+virObjectUnref;
+
+
+# viratomic.h
+virAtomicInc;
+virAtomicDec;
+
+
 # virtaudit.h
 virAuditClose;
 virAuditEncode;
diff --git a/src/util/viratomic.c b/src/util/viratomic.c
new file mode 100644
index 0000000..c7bb44f
--- /dev/null
+++ b/src/util/viratomic.c
@@ -0,0 +1,80 @@
+/*
+ * viratomic.c: atomic operations
+ *
+ * Copyright (C) 2011 Hu Tao
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Hu Tao <hutao cn fujitsu com>
+ */
+
+#include <config.h>
+
+#include "viratomic.h"
+
+#if defined(__GNUC__)
+
+long virAtomicInc(long *value)
+{
+    return __sync_add_and_fetch(value, 1);
+}
+
+long virAtomicDec(long *value)
+{
+    return __sync_sub_and_fetch(value, 1);
+}
+
+#elif defined(WIN32)
+
+long virAtomicInc(long *value)
+{
+    return InterlockedIncrement(value);
+}
+
+long virAtomicDec(long *value)
+{
+    return InterlockedDecrement(value);
+}
+
+#else
+
+#include "threads.h"
+
+static virMutex virAtomicLock = VIR_MUTEX_INITIALIZER;
+
+long virAtomicInc(long *value)
+{
+    long result;
+    virMutexLock(&virAtomicLock);
+    *value += 1;
+    result = *value;
+    virMutexUnlock(&virAtomicLock);
+
+    return result;
+}
+
+long virAtomicDec(long *value)
+{
+    long result;
+    virMutexLock(&virAtomicLock);
+    *value -= 1;
+    result = *value;
+    virMutexUnlock(&virAtomicLock);
+
+    return result;
+}
+
+#endif
diff --git a/src/util/viratomic.h b/src/util/viratomic.h
new file mode 100644
index 0000000..2b40c77
--- /dev/null
+++ b/src/util/viratomic.h
@@ -0,0 +1,32 @@
+/*
+ * viratomic.h: atomic operations
+ *
+ * Copyright (C) 2011 Hu Tao
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Hu Tao <hutao cn fujitsu com>
+ */
+
+#ifndef __VIR_ATOMIC_H
+#define __VIR_ATOMIC_H
+
+#include "internal.h"
+
+long virAtomicInc(long *value) ATTRIBUTE_NONNULL(1);
+long virAtomicDec(long *value) ATTRIBUTE_NONNULL(1);
+
+#endif /* __VIR_ATOMIC_H */
diff --git a/src/util/virobject.c b/src/util/virobject.c
new file mode 100644
index 0000000..0af53e9
--- /dev/null
+++ b/src/util/virobject.c
@@ -0,0 +1,64 @@
+/*
+ * virobject.c: base object that manages reference-counting
+ *
+ * Copyright (C) 2011 Hu Tao
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Hu Tao <hutao cn fujitsu com>
+ */
+
+#include <stdlib.h>
+
+#include "viratomic.h"
+#include "virobject.h"
+#include "logging.h"
+
+int virObjectInit(virObjectPtr obj, virObjectFree f)
+{
+    if (obj->free) {
+        /* This means the obj is already initialized. A second
+         * initialization will destroy ref field, which is bad.
+         */
+        VIR_ERROR("Object %p is already initialized.", obj);
+        return -1;
+    }
+
+    if (!f) {
+        VIR_ERROR0("virObjectFree method is required.");
+	abort();
+    }
+
+    obj->ref = 1;
+    obj->free = f;
+
+    return 0;
+}
+
+void virObjectRef(virObjectPtr obj)
+{
+    if (virAtomicInc(&obj->ref) < 2)
+        abort(); /* BUG if we get here */
+}
+
+void virObjectUnref(virObjectPtr obj)
+{
+    long ref = virAtomicDec(&obj->ref);
+    if (ref == 0)
+        obj->free(obj);
+    else if (ref < 0)
+        abort(); /* BUG if we get here */
+}
diff --git a/src/util/virobject.h b/src/util/virobject.h
new file mode 100644
index 0000000..a9d3d35
--- /dev/null
+++ b/src/util/virobject.h
@@ -0,0 +1,86 @@
+/*
+ * virobject.h: base object that manages reference-counting
+ *
+ * Copyright (C) 2011 Hu Tao
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Hu Tao <hutao cn fujitsu com>
+ */
+
+#ifndef __VIR_OBJECT_H
+#define __VIR_OBJECT_H
+
+typedef struct _virObject virObject;
+typedef virObject *virObjectPtr;
+
+typedef void (*virObjectFree)(virObjectPtr obj);
+
+/* A thread owns a virObject by incrementing its reference-count by 1.
+ * If a thread owns a virObject, the virObject is guarenteed not be
+ * freed until the thread releases ownership by decrementing its
+ * reference-count by 1. A thread can't access a virObject after it
+ * releases the ownership of virObject because it can be freed at
+ * anytime.
+ *
+ * A thread can own a virObject legally in these ways:
+ *
+ * - a thread owns a virObject that it creates.
+ * - a thread owns a virObject if another thread passes the ownership
+ *   to it. Example: qemuMonitorOpen
+ * - a thread gets a virObject from a container.
+ *   Example: virDomainFindByUUID
+ * - a container owns a virObject by incrementing its reference-count
+ *   by 1 before adding it to the container
+ * - if a virObject is removed from a container its reference-count
+ *   must be decremented by 1
+ */
+/*
+ * Usage of virObject:
+ *
+ * 1. embed virObject into your struct as the first member.
+ *
+ *    struct foo {
+ *        virObject obj;    // must be the first member
+ *        ...
+ *    }
+ *
+ * 2. call virObjectInit(obj, fooFree) in your struct's initialization
+ *    function. fooFree is the free method which be called automatically
+ *    when the ref count becomes 0.
+ *
+ * 3. implement two functions to ref/unref your struct like this:
+ *
+ *    void FooRef(struct foo *f)
+ *    {
+ *        virObjectRef(f->obj);
+ *    }
+ *
+ *    void FooUnref(struct foo *f)
+ *    {
+ *        virObjectUnref(f->obj);
+ *    }
+ */
+struct _virObject {
+    long ref;
+    virObjectFree free;
+};
+
+int virObjectInit(virObjectPtr obj, virObjectFree f);
+void virObjectRef(virObjectPtr obj);
+void virObjectUnref(virObjectPtr obj);
+
+#endif /* __VIR_OBJECT_H */
-- 
1.7.3.1


-- 
Thanks,
Hu Tao


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]