Add new function nmem_strsplitx.
[yaz-moved-to-github.git] / src / thread_create.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file thread_create.c
8  * \brief Implements thread creation wrappers
9  *
10  */
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <stddef.h>
20 #include <yaz/xmalloc.h>
21 #include <yaz/log.h>
22 #include <yaz/thread_create.h>
23
24 #if YAZ_POSIX_THREADS
25 #include <pthread.h>
26 #endif
27 #ifdef WIN32
28 #include <windows.h>
29 #include <process.h>
30 #endif
31
32 struct yaz_thread {
33 #if YAZ_POSIX_THREADS
34     pthread_t id;
35 #else
36 #ifdef WIN32
37     HANDLE handle;
38     void *(*routine)(void *p);
39 #endif
40     void *data;
41 #endif
42 };
43
44 #ifdef WIN32
45 unsigned int __stdcall win32_routine(void *p)
46 {
47     yaz_thread_t t = (yaz_thread_t) p;
48     void *userdata = t->data;
49     t->data = t->routine(userdata);
50     _endthreadex(0);
51     return 0;
52 }
53 #endif
54
55 yaz_thread_t yaz_thread_create(void *(*start_routine)(void *p), void *arg)
56 {
57     yaz_thread_t t = xmalloc(sizeof(*t));
58 #if YAZ_POSIX_THREADS
59     int r = pthread_create(&t->id, 0, start_routine, arg);
60     if (r)
61     {
62         xfree(t);
63         t = 0;
64     }
65 #else
66 #ifdef WIN32
67     /* we create a wrapper on windows and pass yaz_thread struct to that */
68     unsigned threadID;
69     uintptr_t ex_ret;
70     t->data = arg; /* use data for both input and output */
71     t->routine = start_routine;
72     ex_ret = _beginthreadex(NULL, 0, win32_routine, t, 0, &threadID);
73     if (ex_ret == -1L)
74     {
75         xfree(t);
76         t = 0;
77     }
78     t->handle = (HANDLE) ex_ret;
79 #else
80     t->data = start_routine(arg);
81 #endif
82 #endif
83     return t;
84 }
85
86 void yaz_thread_join(yaz_thread_t *tp, void **value_ptr)
87 {
88     if (*tp)
89     {
90 #ifdef YAZ_POSIX_THREADS
91         pthread_join((*tp)->id, value_ptr);
92 #else
93 #ifdef WIN32
94         WaitForSingleObject((*tp)->handle, INFINITE);
95         CloseHandle((*tp)->handle);
96 #endif
97         if (value_ptr)
98             *value_ptr = (*tp)->data;
99 #endif
100         xfree(*tp);
101         *tp = 0;
102     }
103 }
104
105 void yaz_thread_detach(yaz_thread_t *tp)
106 {
107     if (*tp)
108     {
109 #ifdef YAZ_POSIX_THREADS
110         pthread_detach((*tp)->id);
111 #else
112 #ifdef WIN32
113         CloseHandle((*tp)->handle);
114 #endif
115 #endif
116         xfree(*tp);
117         *tp = 0;
118     }
119 }
120
121 /*
122  * Local variables:
123  * c-basic-offset: 4
124  * c-file-style: "Stroustrup"
125  * indent-tabs-mode: nil
126  * End:
127  * vim: shiftwidth=4 tabstop=8 expandtab
128  */
129