numexpr 2.10.2__cp313-cp313-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
numexpr/utils.py ADDED
@@ -0,0 +1,309 @@
1
+ ###################################################################
2
+ # Numexpr - Fast numerical array expression evaluator for NumPy.
3
+ #
4
+ # License: MIT
5
+ # Author: See AUTHORS.txt
6
+ #
7
+ # See LICENSE.txt and LICENSES/*.txt for details about copyright and
8
+ # rights to use.
9
+ ####################################################################
10
+
11
+ import logging
12
+ log = logging.getLogger(__name__)
13
+
14
+ import os
15
+ import subprocess
16
+ import contextvars
17
+
18
+ from numexpr.interpreter import _set_num_threads, _get_num_threads, MAX_THREADS
19
+ from numexpr import use_vml
20
+ from . import version
21
+
22
+ if use_vml:
23
+ from numexpr.interpreter import (
24
+ _get_vml_version, _set_vml_accuracy_mode, _set_vml_num_threads,
25
+ _get_vml_num_threads)
26
+
27
+
28
+ def get_vml_version():
29
+ """
30
+ Get the VML/MKL library version.
31
+ """
32
+ if use_vml:
33
+ return _get_vml_version()
34
+ else:
35
+ return None
36
+
37
+
38
+ def set_vml_accuracy_mode(mode):
39
+ """
40
+ Set the accuracy mode for VML operations.
41
+
42
+ The `mode` parameter can take the values:
43
+ - 'high': high accuracy mode (HA), <1 least significant bit
44
+ - 'low': low accuracy mode (LA), typically 1-2 least significant bits
45
+ - 'fast': enhanced performance mode (EP)
46
+ - None: mode settings are ignored
47
+
48
+ This call is equivalent to the `vmlSetMode()` in the VML library.
49
+ See:
50
+
51
+ http://www.intel.com/software/products/mkl/docs/webhelp/vml/vml_DataTypesAccuracyModes.html
52
+
53
+ for more info on the accuracy modes.
54
+
55
+ Returns old accuracy settings.
56
+ """
57
+ if use_vml:
58
+ acc_dict = {None: 0, 'low': 1, 'high': 2, 'fast': 3}
59
+ acc_reverse_dict = {1: 'low', 2: 'high', 3: 'fast'}
60
+ if mode not in list(acc_dict.keys()):
61
+ raise ValueError(
62
+ "mode argument must be one of: None, 'high', 'low', 'fast'")
63
+ retval = _set_vml_accuracy_mode(acc_dict.get(mode, 0))
64
+ return acc_reverse_dict.get(retval)
65
+ else:
66
+ return None
67
+
68
+
69
+ def set_vml_num_threads(nthreads):
70
+ """
71
+ Suggests a maximum number of threads to be used in VML operations.
72
+
73
+ This function is equivalent to the call
74
+ `mkl_domain_set_num_threads(nthreads, MKL_DOMAIN_VML)` in the MKL
75
+ library. See:
76
+
77
+ http://www.intel.com/software/products/mkl/docs/webhelp/support/functn_mkl_domain_set_num_threads.html
78
+
79
+ for more info about it.
80
+ """
81
+ if use_vml:
82
+ _set_vml_num_threads(nthreads)
83
+ pass
84
+
85
+ def get_vml_num_threads():
86
+ """
87
+ Gets the maximum number of threads to be used in VML operations.
88
+
89
+ This function is equivalent to the call
90
+ `mkl_domain_get_max_threads (MKL_DOMAIN_VML)` in the MKL
91
+ library. See:
92
+
93
+ http://software.intel.com/en-us/node/522118
94
+
95
+ for more info about it.
96
+ """
97
+ if use_vml:
98
+ return _get_vml_num_threads()
99
+ return None
100
+
101
+ def set_num_threads(nthreads):
102
+ """
103
+ Sets a number of threads to be used in operations.
104
+
105
+ DEPRECATED: returns the previous setting for the number of threads.
106
+
107
+ During initialization time NumExpr sets this number to the number
108
+ of detected cores in the system (see `detect_number_of_cores()`).
109
+ """
110
+ old_nthreads = _set_num_threads(nthreads)
111
+ return old_nthreads
112
+
113
+ def get_num_threads():
114
+ """
115
+ Gets the number of threads currently in use for operations.
116
+ """
117
+ return _get_num_threads()
118
+
119
+ def _init_num_threads():
120
+ """
121
+ Detects the environment variable 'NUMEXPR_MAX_THREADS' to set the threadpool
122
+ size, and if necessary the slightly redundant 'NUMEXPR_NUM_THREADS' or
123
+ 'OMP_NUM_THREADS' env vars to set the initial number of threads used by
124
+ the virtual machine.
125
+ """
126
+ # Any platform-specific short-circuits
127
+ if 'sparc' in version.platform_machine:
128
+ log.warning('The number of threads have been set to 1 because problems related '
129
+ 'to threading have been reported on some sparc machine. '
130
+ 'The number of threads can be changed using the "set_num_threads" '
131
+ 'function.')
132
+ set_num_threads(1)
133
+ return 1
134
+
135
+ env_configured = False
136
+ n_cores = detect_number_of_cores()
137
+ if ('NUMEXPR_MAX_THREADS' in os.environ and os.environ['NUMEXPR_MAX_THREADS'] != '' or
138
+ 'OMP_NUM_THREADS' in os.environ and os.environ['OMP_NUM_THREADS'] != ''):
139
+ # The user has configured NumExpr in the expected way, so suppress logs.
140
+ env_configured = True
141
+ n_cores = MAX_THREADS
142
+ else:
143
+ # The use has not set 'NUMEXPR_MAX_THREADS', so likely they have not
144
+ # configured NumExpr as desired, so we emit info logs.
145
+ if n_cores > MAX_THREADS:
146
+ log.info('Note: detected %d virtual cores but NumExpr set to maximum of %d, check "NUMEXPR_MAX_THREADS" environment variable.'%(n_cores, MAX_THREADS))
147
+ if n_cores > 16:
148
+ # Back in 2019, 8 threads would be considered safe for performance. We are in 2024 now, so adjusting.
149
+ log.info('Note: NumExpr detected %d cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of 16.'%n_cores)
150
+ n_cores = 16
151
+
152
+ # Now we check for 'NUMEXPR_NUM_THREADS' or 'OMP_NUM_THREADS' to set the
153
+ # actual number of threads used.
154
+ if 'NUMEXPR_NUM_THREADS' in os.environ and os.environ['NUMEXPR_NUM_THREADS'] != '':
155
+ requested_threads = int(os.environ['NUMEXPR_NUM_THREADS'])
156
+ elif 'OMP_NUM_THREADS' in os.environ and os.environ['OMP_NUM_THREADS'] != '':
157
+ # Empty string is commonly used to unset the variable
158
+ requested_threads = int(os.environ['OMP_NUM_THREADS'])
159
+ else:
160
+ requested_threads = n_cores
161
+ if not env_configured:
162
+ log.info('NumExpr defaulting to %d threads.'%n_cores)
163
+
164
+ # The C-extension function performs its own checks against `MAX_THREADS`
165
+ set_num_threads(requested_threads)
166
+ return requested_threads
167
+
168
+
169
+ def detect_number_of_cores():
170
+ """
171
+ Detects the number of cores on a system. Cribbed from pp.
172
+ """
173
+ # Linux, Unix and MacOS:
174
+ if hasattr(os, "sysconf"):
175
+ if "SC_NPROCESSORS_ONLN" in os.sysconf_names:
176
+ # Linux & Unix:
177
+ ncpus = os.sysconf("SC_NPROCESSORS_ONLN")
178
+ if isinstance(ncpus, int) and ncpus > 0:
179
+ return ncpus
180
+ else: # OSX:
181
+ return int(subprocess.check_output(["sysctl", "-n", "hw.ncpu"]))
182
+ # Windows:
183
+ try:
184
+ ncpus = int(os.environ.get("NUMBER_OF_PROCESSORS", ""))
185
+ if ncpus > 0:
186
+ return ncpus
187
+ except ValueError:
188
+ pass
189
+ return 1 # Default
190
+
191
+
192
+ def detect_number_of_threads():
193
+ """
194
+ DEPRECATED: use `_init_num_threads` instead.
195
+ If this is modified, please update the note in: https://github.com/pydata/numexpr/wiki/Numexpr-Users-Guide
196
+ """
197
+ log.warning('Deprecated, use `init_num_threads` instead.')
198
+ try:
199
+ nthreads = int(os.environ.get('NUMEXPR_NUM_THREADS', ''))
200
+ except ValueError:
201
+ try:
202
+ nthreads = int(os.environ.get('OMP_NUM_THREADS', ''))
203
+ except ValueError:
204
+ nthreads = detect_number_of_cores()
205
+
206
+ # Check that we don't surpass the MAX_THREADS in interpreter.cpp
207
+ if nthreads > MAX_THREADS:
208
+ nthreads = MAX_THREADS
209
+ return nthreads
210
+
211
+
212
+ class CacheDict(dict):
213
+ """
214
+ A dictionary that prevents itself from growing too much.
215
+ """
216
+
217
+ def __init__(self, maxentries):
218
+ self.maxentries = maxentries
219
+ super(CacheDict, self).__init__(self)
220
+
221
+ def __setitem__(self, key, value):
222
+ # Protection against growing the cache too much
223
+ if len(self) > self.maxentries:
224
+ # Remove a 10% of (arbitrary) elements from the cache
225
+ entries_to_remove = self.maxentries // 10
226
+ for k in list(self.keys())[:entries_to_remove]:
227
+ super(CacheDict, self).__delitem__(k)
228
+ super(CacheDict, self).__setitem__(key, value)
229
+
230
+
231
+ class ContextDict:
232
+ """
233
+ A context aware version dictionary
234
+ """
235
+ def __init__(self):
236
+ self._context_data = contextvars.ContextVar('context_data', default={})
237
+
238
+ def set(self, key=None, value=None, **kwargs):
239
+ data = self._context_data.get().copy()
240
+
241
+ if key is not None:
242
+ data[key] = value
243
+
244
+ for k, v in kwargs.items():
245
+ data[k] = v
246
+
247
+ self._context_data.set(data)
248
+
249
+ def get(self, key, default=None):
250
+ data = self._context_data.get()
251
+ return data.get(key, default)
252
+
253
+ def delete(self, key):
254
+ data = self._context_data.get().copy()
255
+ if key in data:
256
+ del data[key]
257
+ self._context_data.set(data)
258
+
259
+ def clear(self):
260
+ self._context_data.set({})
261
+
262
+ def all(self):
263
+ return self._context_data.get()
264
+
265
+ def update(self, *args, **kwargs):
266
+ data = self._context_data.get().copy()
267
+
268
+ if args:
269
+ if len(args) > 1:
270
+ raise TypeError(f"update() takes at most 1 positional argument ({len(args)} given)")
271
+ other = args[0]
272
+ if isinstance(other, dict):
273
+ data.update(other)
274
+ else:
275
+ for k, v in other:
276
+ data[k] = v
277
+
278
+ data.update(kwargs)
279
+ self._context_data.set(data)
280
+
281
+ def keys(self):
282
+ return self._context_data.get().keys()
283
+
284
+ def values(self):
285
+ return self._context_data.get().values()
286
+
287
+ def items(self):
288
+ return self._context_data.get().items()
289
+
290
+ def __getitem__(self, key):
291
+ return self.get(key)
292
+
293
+ def __setitem__(self, key, value):
294
+ self.set(key, value)
295
+
296
+ def __delitem__(self, key):
297
+ self.delete(key)
298
+
299
+ def __contains__(self, key):
300
+ return key in self._context_data.get()
301
+
302
+ def __len__(self):
303
+ return len(self._context_data.get())
304
+
305
+ def __iter__(self):
306
+ return iter(self._context_data.get())
307
+
308
+ def __repr__(self):
309
+ return repr(self._context_data.get())
numexpr/version.py ADDED
@@ -0,0 +1,5 @@
1
+ # THIS FILE IS GENERATED BY `setup.py`
2
+ __version__ = '2.10.2'
3
+ version = '2.10.2'
4
+ numpy_build_version = '2.1.3'
5
+ platform_machine = 'AMD64'
@@ -0,0 +1,218 @@
1
+ /*
2
+ * Code for simulating pthreads API on Windows. This is Git-specific,
3
+ * but it is enough for Numexpr needs too.
4
+ *
5
+ * Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com>
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ *
25
+ * DISCLAIMER: The implementation is Git-specific, it is subset of original
26
+ * Pthreads API, without lots of other features that Git doesn't use.
27
+ * Git also makes sure that the passed arguments are valid, so there's
28
+ * no need for double-checking.
29
+ */
30
+
31
+ #include "pthread.h"
32
+
33
+ #include <stdio.h>
34
+ #include <stdlib.h>
35
+ #include <errno.h>
36
+ #include <limits.h>
37
+ #include <process.h>
38
+
39
+
40
+ void die(const char *err, ...)
41
+ {
42
+ printf("%s", err);
43
+ exit(-1);
44
+ }
45
+
46
+ static unsigned __stdcall win32_start_routine(void *arg)
47
+ {
48
+ pthread_t *thread = arg;
49
+ thread->arg = thread->start_routine(thread->arg);
50
+ return 0;
51
+ }
52
+
53
+ int pthread_create(pthread_t *thread, const void *unused,
54
+ void *(*start_routine)(void*), void *arg)
55
+ {
56
+ thread->arg = arg;
57
+ thread->start_routine = start_routine;
58
+ thread->handle = (HANDLE)
59
+ _beginthreadex(NULL, 0, win32_start_routine, thread, 0, NULL);
60
+
61
+ if (!thread->handle)
62
+ return errno;
63
+ else
64
+ return 0;
65
+ }
66
+
67
+ int win32_pthread_join(pthread_t *thread, void **value_ptr)
68
+ {
69
+ DWORD result = WaitForSingleObject(thread->handle, INFINITE);
70
+ switch (result) {
71
+ case WAIT_OBJECT_0:
72
+ if (value_ptr)
73
+ *value_ptr = thread->arg;
74
+ return 0;
75
+ case WAIT_ABANDONED:
76
+ return EINVAL;
77
+ default:
78
+ return GetLastError();
79
+ }
80
+ }
81
+
82
+ int pthread_cond_init(pthread_cond_t *cond, const void *unused)
83
+ {
84
+ cond->waiters = 0;
85
+ cond->was_broadcast = 0;
86
+ InitializeCriticalSection(&cond->waiters_lock);
87
+
88
+ cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
89
+ if (!cond->sema)
90
+ die("CreateSemaphore() failed");
91
+
92
+ cond->continue_broadcast = CreateEvent(NULL, /* security */
93
+ FALSE, /* auto-reset */
94
+ FALSE, /* not signaled */
95
+ NULL); /* name */
96
+ if (!cond->continue_broadcast)
97
+ die("CreateEvent() failed");
98
+
99
+ return 0;
100
+ }
101
+
102
+ int pthread_cond_destroy(pthread_cond_t *cond)
103
+ {
104
+ CloseHandle(cond->sema);
105
+ CloseHandle(cond->continue_broadcast);
106
+ DeleteCriticalSection(&cond->waiters_lock);
107
+ return 0;
108
+ }
109
+
110
+ int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
111
+ {
112
+ int last_waiter;
113
+
114
+ EnterCriticalSection(&cond->waiters_lock);
115
+ cond->waiters++;
116
+ LeaveCriticalSection(&cond->waiters_lock);
117
+
118
+ /*
119
+ * Unlock external mutex and wait for signal.
120
+ * NOTE: we've held mutex locked long enough to increment
121
+ * waiters count above, so there's no problem with
122
+ * leaving mutex unlocked before we wait on semaphore.
123
+ */
124
+ LeaveCriticalSection(mutex);
125
+
126
+ /* let's wait - ignore return value */
127
+ WaitForSingleObject(cond->sema, INFINITE);
128
+
129
+ /*
130
+ * Decrease waiters count. If we are the last waiter, then we must
131
+ * notify the broadcasting thread that it can continue.
132
+ * But if we continued due to cond_signal, we do not have to do that
133
+ * because the signaling thread knows that only one waiter continued.
134
+ */
135
+ EnterCriticalSection(&cond->waiters_lock);
136
+ cond->waiters--;
137
+ last_waiter = cond->was_broadcast && cond->waiters == 0;
138
+ LeaveCriticalSection(&cond->waiters_lock);
139
+
140
+ if (last_waiter) {
141
+ /*
142
+ * cond_broadcast was issued while mutex was held. This means
143
+ * that all other waiters have continued, but are contending
144
+ * for the mutex at the end of this function because the
145
+ * broadcasting thread did not leave cond_broadcast, yet.
146
+ * (This is so that it can be sure that each waiter has
147
+ * consumed exactly one slice of the semaphor.)
148
+ * The last waiter must tell the broadcasting thread that it
149
+ * can go on.
150
+ */
151
+ SetEvent(cond->continue_broadcast);
152
+ /*
153
+ * Now we go on to contend with all other waiters for
154
+ * the mutex. Auf in den Kampf!
155
+ */
156
+ }
157
+ /* lock external mutex again */
158
+ EnterCriticalSection(mutex);
159
+
160
+ return 0;
161
+ }
162
+
163
+ /*
164
+ * IMPORTANT: This implementation requires that pthread_cond_signal
165
+ * is called while the mutex is held that is used in the corresponding
166
+ * pthread_cond_wait calls!
167
+ */
168
+ int pthread_cond_signal(pthread_cond_t *cond)
169
+ {
170
+ int have_waiters;
171
+
172
+ EnterCriticalSection(&cond->waiters_lock);
173
+ have_waiters = cond->waiters > 0;
174
+ LeaveCriticalSection(&cond->waiters_lock);
175
+
176
+ /*
177
+ * Signal only when there are waiters
178
+ */
179
+ if (have_waiters)
180
+ return ReleaseSemaphore(cond->sema, 1, NULL) ?
181
+ 0 : GetLastError();
182
+ else
183
+ return 0;
184
+ }
185
+
186
+ /*
187
+ * DOUBLY IMPORTANT: This implementation requires that pthread_cond_broadcast
188
+ * is called while the mutex is held that is used in the corresponding
189
+ * pthread_cond_wait calls!
190
+ */
191
+ int pthread_cond_broadcast(pthread_cond_t *cond)
192
+ {
193
+ EnterCriticalSection(&cond->waiters_lock);
194
+
195
+ if ((cond->was_broadcast = cond->waiters > 0)) {
196
+ /* wake up all waiters */
197
+ ReleaseSemaphore(cond->sema, cond->waiters, NULL);
198
+ LeaveCriticalSection(&cond->waiters_lock);
199
+ /*
200
+ * At this point all waiters continue. Each one takes its
201
+ * slice of the semaphor. Now it's our turn to wait: Since
202
+ * the external mutex is held, no thread can leave cond_wait,
203
+ * yet. For this reason, we can be sure that no thread gets
204
+ * a chance to eat *more* than one slice. OTOH, it means
205
+ * that the last waiter must send us a wake-up.
206
+ */
207
+ WaitForSingleObject(cond->continue_broadcast, INFINITE);
208
+ /*
209
+ * Since the external mutex is held, no thread can enter
210
+ * cond_wait, and, hence, it is safe to reset this flag
211
+ * without cond->waiters_lock held.
212
+ */
213
+ cond->was_broadcast = 0;
214
+ } else {
215
+ LeaveCriticalSection(&cond->waiters_lock);
216
+ }
217
+ return 0;
218
+ }
@@ -0,0 +1,119 @@
1
+ /*
2
+ * Code for simulating pthreads API on Windows. This is Git-specific,
3
+ * but it is enough for Numexpr needs too.
4
+ *
5
+ * Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com>
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ *
25
+ * DISCLAIMER: The implementation is Git-specific, it is subset of original
26
+ * Pthreads API, without lots of other features that Git doesn't use.
27
+ * Git also makes sure that the passed arguments are valid, so there's
28
+ * no need for double-checking.
29
+ */
30
+
31
+ #ifndef PTHREAD_H
32
+ #define PTHREAD_H
33
+
34
+ #ifndef WIN32_LEAN_AND_MEAN
35
+ #define WIN32_LEAN_AND_MEAN
36
+ #endif
37
+
38
+ #include <windows.h>
39
+
40
+ #ifdef __cplusplus
41
+ extern "C" {
42
+ #endif
43
+
44
+ /*
45
+ * Defines that adapt Windows API threads to pthreads API
46
+ */
47
+ #define pthread_mutex_t CRITICAL_SECTION
48
+
49
+ #define pthread_mutex_init(a,b) InitializeCriticalSection((a))
50
+ #define pthread_mutex_destroy(a) DeleteCriticalSection((a))
51
+ #define pthread_mutex_lock EnterCriticalSection
52
+ #define pthread_mutex_unlock LeaveCriticalSection
53
+
54
+ /*
55
+ * Implement simple condition variable for Windows threads, based on ACE
56
+ * implementation.
57
+ *
58
+ * See original implementation: http://bit.ly/1vkDjo
59
+ * ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html
60
+ * See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
61
+ */
62
+ typedef struct {
63
+ LONG waiters;
64
+ int was_broadcast;
65
+ CRITICAL_SECTION waiters_lock;
66
+ HANDLE sema;
67
+ HANDLE continue_broadcast;
68
+ } pthread_cond_t;
69
+
70
+ extern int pthread_cond_init(pthread_cond_t *cond, const void *unused);
71
+ extern int pthread_cond_destroy(pthread_cond_t *cond);
72
+ extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex);
73
+ extern int pthread_cond_signal(pthread_cond_t *cond);
74
+ extern int pthread_cond_broadcast(pthread_cond_t *cond);
75
+
76
+ /*
77
+ * Simple thread creation implementation using pthread API
78
+ */
79
+ typedef struct {
80
+ HANDLE handle;
81
+ void *(*start_routine)(void*);
82
+ void *arg;
83
+ } pthread_t;
84
+
85
+ extern int pthread_create(pthread_t *thread, const void *unused,
86
+ void *(*start_routine)(void*), void *arg);
87
+
88
+ /*
89
+ * To avoid the need of copying a struct, we use small macro wrapper to pass
90
+ * pointer to win32_pthread_join instead.
91
+ */
92
+ #define pthread_join(a, b) win32_pthread_join(&(a), (b))
93
+
94
+ extern int win32_pthread_join(pthread_t *thread, void **value_ptr);
95
+
96
+ /*
97
+ * The POSIX signal system has a more developed interface than what's in
98
+ * Windows. We create a no-op shim layer to proivde enough of the API to
99
+ * pretend to support what's used when creating threads on POSIX systems.
100
+ */
101
+ typedef int sigset_t;
102
+ enum sigop {
103
+ SIG_BLOCK,
104
+ SIG_UNBLOCK,
105
+ SIG_SETMASK
106
+ };
107
+
108
+ static inline int sigemptyset(sigset_t *sigs) { return 0; }
109
+ static inline int sigfillset(sigset_t *sigs) { return 0; }
110
+ static inline int sigaddset(sigset_t *sigs, int sig) { return 0; }
111
+ static inline int sigdelset(sigset_t *sigs, int sig) { return 0; }
112
+ static inline int pthread_sigmask(int how, sigset_t *newmask,
113
+ sigset_t *oldmask) { return 0; }
114
+
115
+ #ifdef __cplusplus
116
+ } // extern "C"
117
+ #endif
118
+
119
+ #endif /* PTHREAD_H */