]> xenbits.xensource.com Git - libvirt.git/commitdiff
Using virOnce for global initialization is desirable since it
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 20 Jul 2012 14:03:39 +0000 (15:03 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 20 Jul 2012 14:03:39 +0000 (15:03 +0100)
ensures that initialization will always take place when it is
needed, and guarantees it only occurs once. The problem is that
the code to setup a global initializer with proper error
propagation is tedious. This introduces VIR_ONCE_GLOBAL_INIT
macro to simplify this.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
src/util/threads.h

index e5000ea7a64dbfbd58006dac9951ae1af27ad7cd..8f192cfc02e19a7ee09365fe9047c768419f04a0 100644 (file)
@@ -114,4 +114,53 @@ int virThreadLocalSet(virThreadLocalPtr l, void*) ATTRIBUTE_RETURN_CHECK;
 #  error "Either pthreads or Win32 threads are required"
 # endif
 
+
+/**
+ * VIR_ONCE_GLOBAL_INIT:
+ * classname: base classname
+ *
+ * This macro simplifies the setup of a one-time only
+ * global file initializer.
+ *
+ * Assuming a class called "virMyObject", and a method
+ * implemented like:
+ *
+ *  int virMyObjectOnceInit(void) {
+ *      ...do init tasks...
+ *  }
+ *
+ * Then invoking the macro:
+ *
+ *  VIR_ONCE_GLOBAL_INIT(virMyObject)
+ *
+ * Will create a method
+ *
+ *  int virMyObjectInitialize(void);
+ *
+ * Which will ensure that 'virMyObjectOnceInit' is
+ * guaranteed to be invoked exactly once.
+ */
+# define VIR_ONCE_GLOBAL_INIT(classname)                                \
+    static virOnceControl classname ## OnceControl = VIR_ONCE_CONTROL_INITIALIZER; \
+    static virErrorPtr classname ## OnceError = NULL;                   \
+                                                                        \
+    static void classname ## Once(void)                                 \
+    {                                                                   \
+        if (classname ## OnceInit() < 0)                                \
+            classname ## OnceError = virSaveLastError();                \
+    }                                                                   \
+                                                                        \
+    static int classname ## Initialize(void)                            \
+    {                                                                   \
+        if (virOnce(&classname ## OnceControl, classname ## Once) < 0)  \
+            return -1;                                                  \
+                                                                        \
+        if (classname ## OnceError) {                                   \
+            virSetError(classname ## OnceError);                        \
+            return -1;                                                  \
+        }                                                               \
+                                                                        \
+        return 0;                                                       \
+    }
+
 #endif