virthread.h 5.8 KB
Newer Older
1
/*
2
 * virthread.h: basic thread synchronization primitives
3
 *
4
 * Copyright (C) 2009-2011 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16
 *
 * 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
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20 21 22
 *
 */

#ifndef __THREADS_H_
23
# define __THREADS_H_
24

25
# include "internal.h"
26
# include "virerror.h"
27 28 29 30 31 32 33 34 35 36

typedef struct virMutex virMutex;
typedef virMutex *virMutexPtr;

typedef struct virCond virCond;
typedef virCond *virCondPtr;

typedef struct virThreadLocal virThreadLocal;
typedef virThreadLocal *virThreadLocalPtr;

37 38 39
typedef struct virThread virThread;
typedef virThread *virThreadPtr;

40 41 42 43
typedef struct virOnceControl virOnceControl;
typedef virOnceControl *virOnceControlPtr;

typedef void (*virOnceFunc)(void);
44 45 46 47

int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
void virThreadOnExit(void);

48 49 50 51 52 53 54 55 56
typedef void (*virThreadFunc)(void *opaque);

int virThreadCreate(virThreadPtr thread,
                    bool joinable,
                    virThreadFunc func,
                    void *opaque) ATTRIBUTE_RETURN_CHECK;
void virThreadSelf(virThreadPtr thread);
bool virThreadIsSelf(virThreadPtr thread);
void virThreadJoin(virThreadPtr thread);
57 58 59 60 61

/* These next two functions are for debugging only, since they are not
 * guaranteed to give unique values for distinct threads on all
 * architectures, nor are the two functions guaranteed to give the same
 * value for the same thread. */
62
int virThreadSelfID(void);
63
int virThreadID(virThreadPtr thread);
64

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/* Static initialization of mutexes is not possible, so we instead
 * provide for guaranteed one-time initialization via a callback
 * function.  Usage:
 * static virOnceControl once = VIR_ONCE_CONTROL_INITIALIZER;
 * static void initializer(void) { ... }
 * void myfunc()
 * {
 *     if (virOnce(&once, initializer) < 0)
 *         goto error;
 *     ...now guaranteed that initializer has completed exactly once
 * }
 */
int virOnce(virOnceControlPtr once, virOnceFunc init)
    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;

80
int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
S
Stefan Berger 已提交
81
int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
82 83 84 85 86 87 88 89 90 91
void virMutexDestroy(virMutexPtr m);

void virMutexLock(virMutexPtr m);
void virMutexUnlock(virMutexPtr m);



int virCondInit(virCondPtr c) ATTRIBUTE_RETURN_CHECK;
int virCondDestroy(virCondPtr c) ATTRIBUTE_RETURN_CHECK;

92 93 94 95 96
/* virCondWait, virCondWaitUntil:
 * These functions can return without the associated predicate
 * changing value. Therefore in nearly all cases they
 * should be enclosed in a while loop that checks the predicate.
 */
97
int virCondWait(virCondPtr c, virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
98
int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms) ATTRIBUTE_RETURN_CHECK;
99

100 101 102 103 104 105 106 107
void virCondSignal(virCondPtr c);
void virCondBroadcast(virCondPtr c);


typedef void (*virThreadLocalCleanup)(void *);
int virThreadLocalInit(virThreadLocalPtr l,
                       virThreadLocalCleanup c) ATTRIBUTE_RETURN_CHECK;
void *virThreadLocalGet(virThreadLocalPtr l);
108
int virThreadLocalSet(virThreadLocalPtr l, void*) ATTRIBUTE_RETURN_CHECK;
109

110
# ifdef WIN32
111
#  include "virthreadwin32.h"
112
# elif defined HAVE_PTHREAD_MUTEXATTR_INIT
113
#  include "virthreadpthread.h"
114
# else
115
#  error "Either pthreads or Win32 threads are required"
116
# endif
117

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

/**
 * 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;                                                       \
    }

167
#endif