diff --git a/src/util/threads.h b/src/util/threads.h index e5000ea7a64dbfbd58006dac9951ae1af27ad7cd..8f192cfc02e19a7ee09365fe9047c768419f04a0 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -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