
2010/11/8 Daniel P. Berrange <berrange@redhat.com>:
The util/threads.c/h code already has APIs for mutexes, condition variables and thread locals. This commit adds in code for actually creating threads.
* src/libvirt_private.syms: Export new symbols * src/util/threads.h: Define APIs virThreadCreate, virThreadSelf, virThreadIsSelf and virThreadJoin * src/util/threads-win32.c, src/util/threads-win32.h: Win32 impl of threads * src/util/threads-pthread.c, src/util/threads-pthread.h: POSIX impl of threads
struct virThreadLocalData { @@ -33,7 +35,7 @@ typedef virThreadLocalData *virThreadLocalDataPtr; virMutex virThreadLocalLock; unsigned int virThreadLocalCount = 0; virThreadLocalDataPtr virThreadLocalList = NULL; - +DWORD selfkey;
virThreadLocal virCondEvent;
Not introduced by this patch, but why are this local variables not marked as static?
+ +static unsigned int __stdcall virThreadHelperDaemon(void *data) +{ + struct virThreadArgs *args = data; + virThread self; + HANDLE handle = GetCurrentThread(); + HANDLE process = GetCurrentProcess(); + + self.joinable = true; + DuplicateHandle(process, handle, process, + &self.thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); + TlsSetValue(selfkey, &self); + + args->func(args->opaque); + + TlsSetValue(selfkey, NULL); + CloseHandle(self.thread); + return 0; +}
IMHO virThreadHelperJoinable would be a better name for this function.
+int virThreadCreate(virThreadPtr thread, + bool joinable, + virThreadFunc func, + void *opaque) +{ + struct virThreadArgs args = { func, opaque }; + thread->joinable = joinable; + if (joinable) { + thread->thread = (HANDLE)_beginthreadex(NULL, 0, + virThreadHelperDaemon, + &args, 0, NULL); + if (thread->thread == 0) + return -1; + } else { + thread->thread = (HANDLE)_beginthread(virThreadHelper, 0, &args); + if (thread->thread == (HANDLE)-1L) + return -1; + } + return 0; +} + +void virThreadSelf(virThreadPtr thread) +{ + virThreadPtr self = TlsGetValue(selfkey); + thread->thread = self->thread; + thread->joinable = self->joinable; +} + +bool virThreadIsSelf(virThreadPtr thread) +{ + virThread self; + virThreadSelf(&self); + return self.thread == thread->thread ? true : false; +} + +void virThreadJoin(virThreadPtr thread) +{ + if (thread->joinable) { + WaitForSingleObject(thread->thread, INFINITE); + CloseHandle(thread->thread); + thread->thread = 0; + thread->joinable = false; + } +} +
ACK. Matthias