|
160
|
1
|
|
|
2 .. _threading:
|
|
|
3
|
|
|
4 Threading and synchronization utilities
|
|
|
5 =======================================
|
|
|
6
|
|
|
7 libuv provides cross-platform implementations for multiple threading and
|
|
|
8 synchronization primitives. The API largely follows the pthreads API.
|
|
|
9
|
|
|
10
|
|
|
11 Data types
|
|
|
12 ----------
|
|
|
13
|
|
|
14 .. c:type:: uv_thread_t
|
|
|
15
|
|
|
16 Thread data type.
|
|
|
17
|
|
|
18 .. c:type:: void (*uv_thread_cb)(void* arg)
|
|
|
19
|
|
|
20 Callback that is invoked to initialize thread execution. `arg` is the same
|
|
|
21 value that was passed to :c:func:`uv_thread_create`.
|
|
|
22
|
|
|
23 .. c:type:: uv_key_t
|
|
|
24
|
|
|
25 Thread-local key data type.
|
|
|
26
|
|
|
27 .. c:type:: uv_once_t
|
|
|
28
|
|
|
29 Once-only initializer data type.
|
|
|
30
|
|
|
31 .. c:type:: uv_mutex_t
|
|
|
32
|
|
|
33 Mutex data type.
|
|
|
34
|
|
|
35 .. c:type:: uv_rwlock_t
|
|
|
36
|
|
|
37 Read-write lock data type.
|
|
|
38
|
|
|
39 .. c:type:: uv_sem_t
|
|
|
40
|
|
|
41 Semaphore data type.
|
|
|
42
|
|
|
43 .. c:type:: uv_cond_t
|
|
|
44
|
|
|
45 Condition data type.
|
|
|
46
|
|
|
47 .. c:type:: uv_barrier_t
|
|
|
48
|
|
|
49 Barrier data type.
|
|
|
50
|
|
|
51
|
|
|
52 API
|
|
|
53 ---
|
|
|
54
|
|
|
55 Threads
|
|
|
56 ^^^^^^^
|
|
|
57
|
|
|
58 .. c:type:: uv_thread_options_t
|
|
|
59
|
|
|
60 Options for spawning a new thread (passed to :c:func:`uv_thread_create_ex`).
|
|
|
61
|
|
|
62 ::
|
|
|
63
|
|
|
64 typedef struct uv_thread_options_s {
|
|
|
65 enum {
|
|
|
66 UV_THREAD_NO_FLAGS = 0x00,
|
|
|
67 UV_THREAD_HAS_STACK_SIZE = 0x01
|
|
|
68 } flags;
|
|
|
69 size_t stack_size;
|
|
|
70 } uv_thread_options_t;
|
|
|
71
|
|
|
72 More fields may be added to this struct at any time, so its exact
|
|
|
73 layout and size should not be relied upon.
|
|
|
74
|
|
|
75 .. versionadded:: 1.26.0
|
|
|
76
|
|
|
77 .. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg)
|
|
|
78
|
|
|
79 .. versionchanged:: 1.4.1 returns a UV_E* error code on failure
|
|
|
80
|
|
|
81 .. c:function:: int uv_thread_detach(uv_thread_t* tid)
|
|
|
82
|
|
|
83 Detaches a thread. Detached threads automatically release their
|
|
|
84 resources upon termination, eliminating the need for the application to
|
|
|
85 call `uv_thread_join`.
|
|
|
86
|
|
|
87 .. versionadded:: 1.50.0
|
|
|
88
|
|
|
89 .. c:function:: int uv_thread_create_ex(uv_thread_t* tid, const uv_thread_options_t* params, uv_thread_cb entry, void* arg)
|
|
|
90
|
|
|
91 Like :c:func:`uv_thread_create`, but additionally specifies options for creating a new thread.
|
|
|
92
|
|
|
93 If `UV_THREAD_HAS_STACK_SIZE` is set, `stack_size` specifies a stack size for the new thread.
|
|
|
94 `0` indicates that the default value should be used, i.e. behaves as if the flag was not set.
|
|
|
95 Other values will be rounded up to the nearest page boundary.
|
|
|
96
|
|
|
97 .. versionadded:: 1.26.0
|
|
|
98
|
|
|
99 .. c:function:: int uv_thread_setaffinity(uv_thread_t* tid, char* cpumask, char* oldmask, size_t mask_size)
|
|
|
100
|
|
|
101 Sets the specified thread's affinity to cpumask, which is specified in
|
|
|
102 bytes. Optionally returning the previous affinity setting in oldmask.
|
|
|
103 On Unix, uses :man:`pthread_getaffinity_np(3)` to get the affinity setting
|
|
|
104 and maps the cpu_set_t to bytes in oldmask. Then maps the bytes in cpumask
|
|
|
105 to a cpu_set_t and uses :man:`pthread_setaffinity_np(3)`. On Windows, maps
|
|
|
106 the bytes in cpumask to a bitmask and uses SetThreadAffinityMask() which
|
|
|
107 returns the previous affinity setting.
|
|
|
108
|
|
|
109 The mask_size specifies the number of entries (bytes) in cpumask / oldmask,
|
|
|
110 and must be greater-than-or-equal-to :c:func:`uv_cpumask_size`.
|
|
|
111
|
|
|
112 .. note::
|
|
|
113 Thread affinity setting is not atomic on Windows. Unsupported on macOS.
|
|
|
114
|
|
|
115 .. versionadded:: 1.45.0
|
|
|
116
|
|
|
117 .. c:function:: int uv_thread_getaffinity(uv_thread_t* tid, char* cpumask, size_t mask_size)
|
|
|
118
|
|
|
119 Gets the specified thread's affinity setting. On Unix, this maps the
|
|
|
120 cpu_set_t returned by :man:`pthread_getaffinity_np(3)` to bytes in cpumask.
|
|
|
121
|
|
|
122 The mask_size specifies the number of entries (bytes) in cpumask,
|
|
|
123 and must be greater-than-or-equal-to :c:func:`uv_cpumask_size`.
|
|
|
124
|
|
|
125 .. note::
|
|
|
126 Thread affinity getting is not atomic on Windows. Unsupported on macOS.
|
|
|
127
|
|
|
128 .. versionadded:: 1.45.0
|
|
|
129
|
|
|
130 .. c:function:: int uv_thread_getcpu(void)
|
|
|
131
|
|
|
132 Gets the CPU number on which the calling thread is running.
|
|
|
133
|
|
|
134 .. note::
|
|
|
135 Currently only implemented on Windows, Linux and FreeBSD.
|
|
|
136
|
|
|
137 .. versionadded:: 1.45.0
|
|
|
138
|
|
|
139 .. c:function:: uv_thread_t uv_thread_self(void)
|
|
|
140 .. c:function:: int uv_thread_join(uv_thread_t *tid)
|
|
|
141 .. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2)
|
|
|
142
|
|
|
143 .. c:function:: int uv_thread_setname(const char* name)
|
|
|
144
|
|
|
145 Sets the name of the current thread. Different platforms define different limits on the max number of characters
|
|
|
146 a thread name can be: Linux, IBM i (16), macOS (64), Windows (32767), and NetBSD (32), etc. `uv_thread_setname()`
|
|
|
147 will truncate it in case `name` is larger than the limit of the platform.
|
|
|
148
|
|
|
149 Not supported on Windows Server 2016, returns `UV_ENOSYS`.
|
|
|
150
|
|
|
151 .. versionadded:: 1.50.0
|
|
|
152
|
|
|
153 .. c:function:: int uv_thread_getname(uv_thread_t* tid, char* name, size_t* size)
|
|
|
154
|
|
|
155 Gets the name of the thread specified by `tid`. The thread name is copied, with the trailing NUL, into the buffer
|
|
|
156 pointed to by `name`. The `size` parameter specifies the size of the buffer pointed to by `name`.
|
|
|
157 The buffer should be large enough to hold the name of the thread plus the trailing NUL, or it will be truncated to fit
|
|
|
158 with the trailing NUL.
|
|
|
159
|
|
|
160 Not supported on Windows Server 2016, returns `UV_ENOSYS`.
|
|
|
161
|
|
|
162 .. versionadded:: 1.50.0
|
|
|
163
|
|
|
164 .. c:function:: int uv_thread_setpriority(uv_thread_t tid, int priority)
|
|
|
165
|
|
|
166 If the function succeeds, the return value is 0.
|
|
|
167 If the function fails, the return value is less than zero.
|
|
|
168 Sets the scheduling priority of the thread specified by tid. It requires elevated
|
|
|
169 privilege to set specific priorities on some platforms.
|
|
|
170 The priority can be set to the following constants. UV_THREAD_PRIORITY_HIGHEST,
|
|
|
171 UV_THREAD_PRIORITY_ABOVE_NORMAL, UV_THREAD_PRIORITY_NORMAL,
|
|
|
172 UV_THREAD_PRIORITY_BELOW_NORMAL, UV_THREAD_PRIORITY_LOWEST.
|
|
|
173
|
|
|
174 .. c:function:: int uv_thread_getpriority(uv_thread_t tid, int* priority)
|
|
|
175
|
|
|
176 If the function succeeds, the return value is 0.
|
|
|
177 If the function fails, the return value is less than zero.
|
|
|
178 Retrieves the scheduling priority of the thread specified by tid. The value in the
|
|
|
179 output parameter priority is platform dependent.
|
|
|
180 For Linux, when schedule policy is SCHED_OTHER (default), priority is 0.
|
|
|
181
|
|
|
182 Thread-local storage
|
|
|
183 ^^^^^^^^^^^^^^^^^^^^
|
|
|
184
|
|
|
185 .. note::
|
|
|
186 The total thread-local storage size may be limited. That is, it may not be possible to
|
|
|
187 create many TLS keys.
|
|
|
188
|
|
|
189 .. c:function:: int uv_key_create(uv_key_t* key)
|
|
|
190 .. c:function:: void uv_key_delete(uv_key_t* key)
|
|
|
191 .. c:function:: void* uv_key_get(uv_key_t* key)
|
|
|
192 .. c:function:: void uv_key_set(uv_key_t* key, void* value)
|
|
|
193
|
|
|
194 Once-only initialization
|
|
|
195 ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
196
|
|
|
197 Runs a function once and only once. Concurrent calls to :c:func:`uv_once` with the
|
|
|
198 same guard will block all callers except one (it's unspecified which one).
|
|
|
199 The guard should be initialized statically with the UV_ONCE_INIT macro.
|
|
|
200
|
|
|
201 .. c:function:: void uv_once(uv_once_t* guard, void (*callback)(void))
|
|
|
202
|
|
|
203 Mutex locks
|
|
|
204 ^^^^^^^^^^^
|
|
|
205
|
|
|
206 Functions return 0 on success or an error code < 0 (unless the
|
|
|
207 return type is void, of course).
|
|
|
208
|
|
|
209 .. c:function:: int uv_mutex_init(uv_mutex_t* handle)
|
|
|
210 .. c:function:: int uv_mutex_init_recursive(uv_mutex_t* handle)
|
|
|
211 .. c:function:: void uv_mutex_destroy(uv_mutex_t* handle)
|
|
|
212 .. c:function:: void uv_mutex_lock(uv_mutex_t* handle)
|
|
|
213 .. c:function:: int uv_mutex_trylock(uv_mutex_t* handle)
|
|
|
214 .. c:function:: void uv_mutex_unlock(uv_mutex_t* handle)
|
|
|
215
|
|
|
216 Read-write locks
|
|
|
217 ^^^^^^^^^^^^^^^^
|
|
|
218
|
|
|
219 Functions return 0 on success or an error code < 0 (unless the
|
|
|
220 return type is void, of course).
|
|
|
221
|
|
|
222 .. c:function:: int uv_rwlock_init(uv_rwlock_t* rwlock)
|
|
|
223 .. c:function:: void uv_rwlock_destroy(uv_rwlock_t* rwlock)
|
|
|
224 .. c:function:: void uv_rwlock_rdlock(uv_rwlock_t* rwlock)
|
|
|
225 .. c:function:: int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock)
|
|
|
226 .. c:function:: void uv_rwlock_rdunlock(uv_rwlock_t* rwlock)
|
|
|
227 .. c:function:: void uv_rwlock_wrlock(uv_rwlock_t* rwlock)
|
|
|
228 .. c:function:: int uv_rwlock_trywrlock(uv_rwlock_t* rwlock)
|
|
|
229 .. c:function:: void uv_rwlock_wrunlock(uv_rwlock_t* rwlock)
|
|
|
230
|
|
|
231 Semaphores
|
|
|
232 ^^^^^^^^^^
|
|
|
233
|
|
|
234 Functions return 0 on success or an error code < 0 (unless the
|
|
|
235 return type is void, of course).
|
|
|
236
|
|
|
237 .. c:function:: int uv_sem_init(uv_sem_t* sem, unsigned int value)
|
|
|
238 .. c:function:: void uv_sem_destroy(uv_sem_t* sem)
|
|
|
239 .. c:function:: void uv_sem_post(uv_sem_t* sem)
|
|
|
240 .. c:function:: void uv_sem_wait(uv_sem_t* sem)
|
|
|
241 .. c:function:: int uv_sem_trywait(uv_sem_t* sem)
|
|
|
242
|
|
|
243 Conditions
|
|
|
244 ^^^^^^^^^^
|
|
|
245
|
|
|
246 Functions return 0 on success or an error code < 0 (unless the
|
|
|
247 return type is void, of course).
|
|
|
248
|
|
|
249 .. note::
|
|
|
250 1. Callers should be prepared to deal with spurious wakeups on :c:func:`uv_cond_wait`
|
|
|
251 and :c:func:`uv_cond_timedwait`.
|
|
|
252 2. The timeout parameter for :c:func:`uv_cond_timedwait` is relative to the time
|
|
|
253 at which function is called.
|
|
|
254 3. On z/OS, the timeout parameter for :c:func:`uv_cond_timedwait` is converted to an
|
|
|
255 absolute system time at which the wait expires. If the current system clock time
|
|
|
256 passes the absolute time calculated before the condition is signaled, an ETIMEDOUT
|
|
|
257 error results. After the wait begins, the wait time is not affected by changes
|
|
|
258 to the system clock.
|
|
|
259
|
|
|
260 .. c:function:: int uv_cond_init(uv_cond_t* cond)
|
|
|
261 .. c:function:: void uv_cond_destroy(uv_cond_t* cond)
|
|
|
262 .. c:function:: void uv_cond_signal(uv_cond_t* cond)
|
|
|
263 .. c:function:: void uv_cond_broadcast(uv_cond_t* cond)
|
|
|
264 .. c:function:: void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex)
|
|
|
265 .. c:function:: int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout)
|
|
|
266
|
|
|
267 Barriers
|
|
|
268 ^^^^^^^^
|
|
|
269
|
|
|
270 Functions return 0 on success or an error code < 0 (unless the
|
|
|
271 return type is void, of course).
|
|
|
272
|
|
|
273 .. note::
|
|
|
274 :c:func:`uv_barrier_wait` returns a value > 0 to an arbitrarily chosen "serializer" thread
|
|
|
275 to facilitate cleanup, i.e.
|
|
|
276
|
|
|
277 ::
|
|
|
278
|
|
|
279 if (uv_barrier_wait(&barrier) > 0)
|
|
|
280 uv_barrier_destroy(&barrier);
|
|
|
281
|
|
|
282 .. c:function:: int uv_barrier_init(uv_barrier_t* barrier, unsigned int count)
|
|
|
283 .. c:function:: void uv_barrier_destroy(uv_barrier_t* barrier)
|
|
|
284 .. c:function:: int uv_barrier_wait(uv_barrier_t* barrier)
|