1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "curl_setup.h"
24
25#if defined(USE_THREADS_POSIX)
26#  ifdef HAVE_PTHREAD_H
27#    include <pthread.h>
28#  endif
29#elif defined(USE_THREADS_WIN32)
30#  ifdef HAVE_PROCESS_H
31#    include <process.h>
32#  endif
33#endif
34
35#include "curl_threads.h"
36
37#define _MPRINTF_REPLACE /* use our functions only */
38#include <curl/mprintf.h>
39
40#include "curl_memory.h"
41/* The last #include file should be: */
42#include "memdebug.h"
43
44#if defined(USE_THREADS_POSIX)
45
46struct curl_actual_call {
47  unsigned int (*func)(void *);
48  void *arg;
49};
50
51static void *curl_thread_create_thunk(void *arg)
52{
53  struct curl_actual_call * ac = arg;
54  unsigned int (*func)(void *) = ac->func;
55  void *real_arg = ac->arg;
56
57  free(ac);
58
59  (*func)(real_arg);
60
61  return 0;
62}
63
64curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
65{
66  curl_thread_t t;
67  struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
68  if(!ac)
69    return curl_thread_t_null;
70
71  ac->func = func;
72  ac->arg = arg;
73
74  if(pthread_create(&t, NULL, curl_thread_create_thunk, ac) != 0) {
75    free(ac);
76    return curl_thread_t_null;
77  }
78
79  return t;
80}
81
82void Curl_thread_destroy(curl_thread_t hnd)
83{
84  if(hnd != curl_thread_t_null)
85    pthread_detach(hnd);
86}
87
88int Curl_thread_join(curl_thread_t *hnd)
89{
90  int ret = (pthread_join(*hnd, NULL) == 0);
91
92  *hnd = curl_thread_t_null;
93
94  return ret;
95}
96
97#elif defined(USE_THREADS_WIN32)
98
99curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
100                                 void *arg)
101{
102#ifdef _WIN32_WCE
103  return CreateThread(NULL, 0, func, arg, 0, NULL);
104#else
105  curl_thread_t t;
106  t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
107  if((t == 0) || (t == (curl_thread_t)-1L))
108    return curl_thread_t_null;
109  return t;
110#endif
111}
112
113void Curl_thread_destroy(curl_thread_t hnd)
114{
115  CloseHandle(hnd);
116}
117
118int Curl_thread_join(curl_thread_t *hnd)
119{
120  int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
121
122  Curl_thread_destroy(*hnd);
123
124  *hnd = curl_thread_t_null;
125
126  return ret;
127}
128
129#endif /* USE_THREADS_* */
130