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#include "setup.h"
23
24#if defined(USE_THREADS_POSIX)
25#  ifdef HAVE_PTHREAD_H
26#    include <pthread.h>
27#  endif
28#elif defined(USE_THREADS_WIN32)
29#  ifdef HAVE_PROCESS_H
30#    include <process.h>
31#  endif
32#endif
33
34#include "curl_threads.h"
35
36#define _MPRINTF_REPLACE /* use our functions only */
37#include <curl/mprintf.h>
38
39#include "curl_memory.h"
40/* The last #include file should be: */
41#include "memdebug.h"
42
43#if defined(USE_THREADS_POSIX)
44
45struct curl_actual_call {
46  unsigned int (*func)(void *);
47  void *arg;
48};
49
50static void *curl_thread_create_thunk(void *arg)
51{
52  struct curl_actual_call * ac = arg;
53  unsigned int (*func)(void *) = ac->func;
54  void *real_arg = ac->arg;
55
56  free(ac);
57
58  (*func)(real_arg);
59
60  return 0;
61}
62
63curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
64{
65  curl_thread_t t;
66  struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
67  if(!ac)
68    return curl_thread_t_null;
69
70  ac->func = func;
71  ac->arg = arg;
72
73  if(pthread_create(&t, NULL, curl_thread_create_thunk, ac) != 0) {
74    free(ac);
75    return curl_thread_t_null;
76  }
77
78  return t;
79}
80
81void Curl_thread_destroy(curl_thread_t hnd)
82{
83  if(hnd != curl_thread_t_null)
84    pthread_detach(hnd);
85}
86
87int Curl_thread_join(curl_thread_t *hnd)
88{
89  int ret = (pthread_join(*hnd, NULL) == 0);
90
91  *hnd = curl_thread_t_null;
92
93  return ret;
94}
95
96#elif defined(USE_THREADS_WIN32)
97
98curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
99                                 void *arg)
100{
101#ifdef _WIN32_WCE
102  return CreateThread(NULL, 0, func, arg, 0, NULL);
103#else
104  curl_thread_t t;
105  t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
106  if((t == 0) || (t == (curl_thread_t)-1L))
107    return curl_thread_t_null;
108  return t;
109#endif
110}
111
112void Curl_thread_destroy(curl_thread_t hnd)
113{
114  CloseHandle(hnd);
115}
116
117int Curl_thread_join(curl_thread_t *hnd)
118{
119  int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
120
121  Curl_thread_destroy(*hnd);
122
123  *hnd = curl_thread_t_null;
124
125  return ret;
126}
127
128#endif /* USE_THREADS_* */
129