]> git.sesse.net Git - vlc/blob - include/vlc_threads_funcs.h
* modules/gui/wxwindows/*: make sure we re-use the streaming wizard so the user selec...
[vlc] / include / vlc_threads_funcs.h
1 /*****************************************************************************
2  * vlc_threads_funcs.h : threads implementation for the VideoLAN client
3  * This header provides a portable threads implementation.
4  *****************************************************************************
5  * Copyright (C) 1999, 2002 VideoLAN
6  * $Id: vlc_threads_funcs.h,v 1.16 2003/11/22 00:41:07 titer Exp $
7  *
8  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
9  *          Samuel Hocevar <sam@via.ecp.fr>
10  *          Gildas Bazin <gbazin@netcourrier.com>
11  *          Christophe Massiot <massiot@via.ecp.fr>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Function definitions
30  *****************************************************************************/
31 VLC_EXPORT( int,  __vlc_threads_init,  ( vlc_object_t * ) );
32 VLC_EXPORT( int,  __vlc_threads_end,   ( vlc_object_t * ) );
33 VLC_EXPORT( int,  __vlc_mutex_init,    ( vlc_object_t *, vlc_mutex_t * ) );
34 VLC_EXPORT( int,  __vlc_mutex_destroy, ( char *, int, vlc_mutex_t * ) );
35 VLC_EXPORT( int,  __vlc_cond_init,     ( vlc_object_t *, vlc_cond_t * ) );
36 VLC_EXPORT( int,  __vlc_cond_destroy,  ( char *, int, vlc_cond_t * ) );
37 VLC_EXPORT( int,  __vlc_thread_create, ( vlc_object_t *, char *, int, char *, void * ( * ) ( void * ), int, vlc_bool_t ) );
38 VLC_EXPORT( int,  __vlc_thread_set_priority, ( vlc_object_t *, char *, int, int ) );
39 VLC_EXPORT( void, __vlc_thread_ready,  ( vlc_object_t * ) );
40 VLC_EXPORT( void, __vlc_thread_join,   ( vlc_object_t *, char *, int ) );
41
42
43 /*****************************************************************************
44  * vlc_threads_init: initialize threads system
45  *****************************************************************************/
46 #define vlc_threads_init( P_THIS )                                          \
47     __vlc_threads_init( VLC_OBJECT(P_THIS) )
48
49 /*****************************************************************************
50  * vlc_threads_end: deinitialize threads system
51  *****************************************************************************/
52 #define vlc_threads_end( P_THIS )                                           \
53     __vlc_threads_end( VLC_OBJECT(P_THIS) )
54
55 /*****************************************************************************
56  * vlc_mutex_init: initialize a mutex
57  *****************************************************************************/
58 #define vlc_mutex_init( P_THIS, P_MUTEX )                                   \
59     __vlc_mutex_init( VLC_OBJECT(P_THIS), P_MUTEX )
60
61 /*****************************************************************************
62  * vlc_mutex_lock: lock a mutex
63  *****************************************************************************/
64 #define vlc_mutex_lock( P_MUTEX )                                           \
65     __vlc_mutex_lock( __FILE__, __LINE__, P_MUTEX )
66
67 static inline int __vlc_mutex_lock( char * psz_file, int i_line,
68                                     vlc_mutex_t * p_mutex )
69 {
70     int i_result;
71     /* In case of error : */
72     int i_thread = -1;
73     const char * psz_error = "";
74
75 #if defined( PTH_INIT_IN_PTH_H )
76     i_result = ( pth_mutex_acquire( &p_mutex->mutex, FALSE, NULL ) == FALSE );
77
78 #elif defined( ST_INIT_IN_ST_H )
79     i_result = st_mutex_lock( p_mutex->mutex );
80
81 #elif defined( UNDER_CE )
82     EnterCriticalSection( &p_mutex->csection );
83     i_result = 0;
84
85 #elif defined( WIN32 )
86     if( p_mutex->mutex )
87     {
88         WaitForSingleObject( p_mutex->mutex, INFINITE );
89     }
90     else
91     {
92         EnterCriticalSection( &p_mutex->csection );
93     }
94     i_result = 0;
95
96 #elif defined( HAVE_KERNEL_SCHEDULER_H )
97     if( p_mutex == NULL )
98     {
99         i_result = B_BAD_VALUE;
100     }
101     else if( p_mutex->init < 2000 )
102     {
103         i_result = B_NO_INIT;
104     }
105     else
106     {
107         i_result = acquire_sem( p_mutex->lock );
108     }
109
110 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
111     i_result = pthread_mutex_lock( &p_mutex->mutex );
112     if ( i_result )
113     {
114         i_thread = (int)pthread_self();
115         psz_error = strerror(i_result);
116     }
117
118 #elif defined( HAVE_CTHREADS_H )
119     mutex_lock( p_mutex->mutex );
120     i_result = 0;
121
122 #endif
123
124     if( i_result )
125     {
126         msg_Err( p_mutex->p_this,
127                  "thread %d: mutex_lock failed at %s:%d (%d:%s)",
128                  i_thread, psz_file, i_line, i_result, psz_error );
129     }
130     return i_result;
131 }
132
133 /*****************************************************************************
134  * vlc_mutex_unlock: unlock a mutex
135  *****************************************************************************/
136 #define vlc_mutex_unlock( P_MUTEX )                                         \
137     __vlc_mutex_unlock( __FILE__, __LINE__, P_MUTEX )
138
139 static inline int __vlc_mutex_unlock( char * psz_file, int i_line,
140                                       vlc_mutex_t *p_mutex )
141 {
142     int i_result;
143     /* In case of error : */
144     int i_thread = -1;
145     const char * psz_error = "";
146
147 #if defined( PTH_INIT_IN_PTH_H )
148     i_result = ( pth_mutex_release( &p_mutex->mutex ) == FALSE );
149
150 #elif defined( ST_INIT_IN_ST_H )
151     i_result = st_mutex_unlock( p_mutex->mutex );
152
153 #elif defined( UNDER_CE )
154     LeaveCriticalSection( &p_mutex->csection );
155     i_result = 0;
156
157 #elif defined( WIN32 )
158     if( p_mutex->mutex )
159     {
160         ReleaseMutex( p_mutex->mutex );
161     }
162     else
163     {
164         LeaveCriticalSection( &p_mutex->csection );
165     }
166     i_result = 0;
167
168 #elif defined( HAVE_KERNEL_SCHEDULER_H )
169     if( p_mutex == NULL )
170     {
171         i_result = B_BAD_VALUE;
172     }
173     else if( p_mutex->init < 2000 )
174     {
175         i_result = B_NO_INIT;
176     }
177     else
178     {
179         release_sem( p_mutex->lock );
180         return B_OK;
181     }
182
183 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
184     i_result = pthread_mutex_unlock( &p_mutex->mutex );
185     if ( i_result )
186     {
187         i_thread = (int)pthread_self();
188         psz_error = strerror(i_result);
189     }
190
191 #elif defined( HAVE_CTHREADS_H )
192     mutex_unlock( p_mutex );
193     i_result = 0;
194
195 #endif
196
197     if( i_result )
198     {
199         msg_Err( p_mutex->p_this,
200                  "thread %d: mutex_unlock failed at %s:%d (%d:%s)",
201                  i_thread, psz_file, i_line, i_result, psz_error );
202     }
203
204     return i_result;
205 }
206
207 /*****************************************************************************
208  * vlc_mutex_destroy: destroy a mutex
209  *****************************************************************************/
210 #define vlc_mutex_destroy( P_MUTEX )                                        \
211     __vlc_mutex_destroy( __FILE__, __LINE__, P_MUTEX )
212
213 /*****************************************************************************
214  * vlc_cond_init: initialize a condition
215  *****************************************************************************/
216 #define vlc_cond_init( P_THIS, P_COND )                                     \
217     __vlc_cond_init( VLC_OBJECT(P_THIS), P_COND )
218
219 /*****************************************************************************
220  * vlc_cond_signal: start a thread on condition completion
221  *****************************************************************************/
222 #define vlc_cond_signal( P_COND )                                           \
223     __vlc_cond_signal( __FILE__, __LINE__, P_COND )
224
225 static inline int __vlc_cond_signal( char * psz_file, int i_line,
226                                      vlc_cond_t *p_condvar )
227 {
228     int i_result;
229     /* In case of error : */
230     int i_thread = -1;
231     const char * psz_error = "";
232
233 #if defined( PTH_INIT_IN_PTH_H )
234     i_result = ( pth_cond_notify( &p_condvar->cond, FALSE ) == FALSE );
235
236 #elif defined( ST_INIT_IN_ST_H )
237     i_result = st_cond_signal( p_condvar->cond );
238
239 #elif defined( UNDER_CE )
240     PulseEvent( p_condvar->event );
241     i_result = 0;
242
243 #elif defined( WIN32 )
244     /* Release one waiting thread if one is available. */
245     /* For this trick to work properly, the vlc_cond_signal must be surrounded
246      * by a mutex. This will prevent another thread from stealing the signal */
247     if( !p_condvar->semaphore )
248     {
249         PulseEvent( p_condvar->event );
250     }
251     else if( p_condvar->i_win9x_cv == 1 )
252     {
253         /* Wait for the gate to be open */
254         WaitForSingleObject( p_condvar->event, INFINITE );
255
256         if( p_condvar->i_waiting_threads )
257         {
258             /* Using a semaphore exposes us to a race condition. It is
259              * possible for another thread to start waiting on the semaphore
260              * just after we signaled it and thus steal the signal.
261              * We have to prevent new threads from entering the cond_wait(). */
262             ResetEvent( p_condvar->event );
263
264             /* A semaphore is used here because Win9x doesn't have
265              * SignalObjectAndWait() and thus a race condition exists
266              * during the time we release the mutex and the time we start
267              * waiting on the event (more precisely, the signal can sometimes
268              * be missed by the waiting thread if we use PulseEvent()). */
269             ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
270         }
271     }
272     else
273     {
274         if( p_condvar->i_waiting_threads )
275         {
276             ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
277
278             /* Wait for the last thread to be awakened */
279             WaitForSingleObject( p_condvar->event, INFINITE );
280         }
281     }
282     i_result = 0;
283
284 #elif defined( HAVE_KERNEL_SCHEDULER_H )
285     if( p_condvar == NULL )
286     {
287         i_result = B_BAD_VALUE;
288     }
289     else if( p_condvar->init < 2000 )
290     {
291         i_result = B_NO_INIT;
292     }
293     else
294     {
295         while( p_condvar->thread != -1 )
296         {
297             thread_info info;
298             if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
299             {
300                 return 0;
301             }
302
303             if( info.state != B_THREAD_SUSPENDED )
304             {
305                 /* The  waiting thread is not suspended so it could
306                  * have been interrupted beetwen the unlock and the
307                  * suspend_thread line. That is why we sleep a little
308                  * before retesting p_condver->thread. */
309                 snooze( 10000 );
310             }
311             else
312             {
313                 /* Ok, we have to wake up that thread */
314                 resume_thread( p_condvar->thread );
315                 return 0;
316             }
317         }
318         i_result = 0;
319     }
320
321 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
322     i_result = pthread_cond_signal( &p_condvar->cond );
323     if ( i_result )
324     {
325         i_thread = (int)pthread_self();
326         psz_error = strerror(i_result);
327     }
328
329 #elif defined( HAVE_CTHREADS_H )
330     /* condition_signal() */
331     if ( p_condvar->queue.head || p_condvar->implications )
332     {
333         cond_signal( (condition_t)p_condvar );
334     }
335     i_result = 0;
336
337 #endif
338
339     if( i_result )
340     {
341         msg_Err( p_condvar->p_this,
342                  "thread %d: cond_signal failed at %s:%d (%d:%s)",
343                  i_thread, psz_file, i_line, i_result, psz_error );
344     }
345
346     return i_result;
347 }
348
349 /*****************************************************************************
350  * vlc_cond_broadcast: start all threads waiting on condition completion
351  *****************************************************************************/
352 /*
353  * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
354  * Only works with pthreads, st, win32
355  * You need to adapt it for others
356  * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
357  */
358 #define vlc_cond_broadcast( P_COND )                                        \
359     __vlc_cond_broadcast( __FILE__, __LINE__, P_COND )
360
361 static inline int __vlc_cond_broadcast( char * psz_file, int i_line,
362                                         vlc_cond_t *p_condvar )
363 {
364     int i_result;
365     /* In case of error : */
366     int i_thread = -1;
367     const char * psz_error = "";
368
369 #if defined( PTH_INIT_IN_PTH_H )
370     i_result = ( pth_cond_notify( &p_condvar->cond, TRUE ) == FALSE );
371
372 #elif defined( ST_INIT_IN_ST_H )
373     i_result = st_cond_broadcast( p_condvar->cond );
374
375 #elif defined( UNDER_CE )
376     int i;
377
378     /* Release all waiting threads. */
379     for( i = p_condvar->i_waiting_threads; i > 0; i-- )
380     {
381         PulseEvent( p_condvar->event );
382     }
383     i_result = 0;
384
385 #elif defined( WIN32 )
386     int i;
387
388     /* Release all waiting threads. */
389     if( !p_condvar->semaphore )
390     {
391         for( i = p_condvar->i_waiting_threads; i > 0; i-- )
392         {
393             PulseEvent( p_condvar->event );
394         }
395     }
396     else if( p_condvar->i_win9x_cv == 1 )
397     {
398         /* Wait for the gate to be open */
399         WaitForSingleObject( p_condvar->event, INFINITE );
400
401         if( p_condvar->i_waiting_threads )
402         {
403             /* Using a semaphore exposes us to a race condition. It is
404              * possible for another thread to start waiting on the semaphore
405              * just after we signaled it and thus steal the signal.
406              * We have to prevent new threads from entering the cond_wait(). */
407             ResetEvent( p_condvar->event );
408
409             /* A semaphore is used here because Win9x doesn't have
410              * SignalObjectAndWait() and thus a race condition exists
411              * during the time we release the mutex and the time we start
412              * waiting on the event (more precisely, the signal can sometimes
413              * be missed by the waiting thread if we use PulseEvent()). */
414             ReleaseSemaphore( p_condvar->semaphore,
415                               p_condvar->i_waiting_threads, 0 );
416         }
417     }
418     else
419     {
420         if( p_condvar->i_waiting_threads )
421         {
422             ReleaseSemaphore( p_condvar->semaphore,
423                               p_condvar->i_waiting_threads, 0 );
424
425             /* Wait for the last thread to be awakened */
426             WaitForSingleObject( p_condvar->event, INFINITE );
427         }
428     }
429     i_result = 0;
430
431 #elif defined( HAVE_KERNEL_SCHEDULER_H )
432     if( p_condvar == NULL )
433     {
434         i_result = B_BAD_VALUE;
435     }
436     else if( p_condvar->init < 2000 )
437     {
438         i_result = B_NO_INIT;
439     }
440     else
441     {
442         while( p_condvar->thread != -1 )
443         {
444             thread_info info;
445             if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
446             {
447                 return 0;
448             }
449
450             if( info.state != B_THREAD_SUSPENDED )
451             {
452                 /* The  waiting thread is not suspended so it could
453                  * have been interrupted beetwen the unlock and the
454                  * suspend_thread line. That is why we sleep a little
455                  * before retesting p_condver->thread. */
456                 snooze( 10000 );
457             }
458             else
459             {
460                 /* Ok, we have to wake up that thread */
461                 resume_thread( p_condvar->thread );
462                 return 0;
463             }
464         }
465         i_result = 0;
466     }
467
468 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
469     i_result = pthread_cond_broadcast( &p_condvar->cond );
470     if ( i_result )
471     {
472         i_thread = (int)pthread_self();
473         psz_error = strerror(i_result);
474     }
475
476 #elif defined( HAVE_CTHREADS_H )
477     /* condition_signal() */
478     if ( p_condvar->queue.head || p_condvar->implications )
479     {
480         cond_signal( (condition_t)p_condvar );
481     }
482     i_result = 0;
483
484 #endif
485
486     if( i_result )
487     {
488         msg_Err( p_condvar->p_this,
489                  "thread %d: cond_broadcast failed at %s:%d (%d:%s)",
490                  i_thread, psz_file, i_line, i_result, psz_error );
491     }
492
493     return i_result;
494 }
495
496 /*****************************************************************************
497  * vlc_cond_wait: wait until condition completion
498  *****************************************************************************/
499 #define vlc_cond_wait( P_COND, P_MUTEX )                                     \
500     __vlc_cond_wait( __FILE__, __LINE__, P_COND, P_MUTEX  )
501
502 static inline int __vlc_cond_wait( char * psz_file, int i_line,
503                                    vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
504 {
505     int i_result;
506     /* In case of error : */
507     int i_thread = -1;
508     const char * psz_error = "";
509
510 #if defined( PTH_INIT_IN_PTH_H )
511     i_result = ( pth_cond_await( &p_condvar->cond, &p_mutex->mutex, NULL )
512                  == FALSE );
513
514 #elif defined( ST_INIT_IN_ST_H )
515     st_mutex_unlock( p_mutex->mutex );
516     i_result = st_cond_wait( p_condvar->cond );
517     st_mutex_lock( p_mutex->mutex );
518
519 #elif defined( UNDER_CE )
520     p_condvar->i_waiting_threads++;
521     LeaveCriticalSection( &p_mutex->csection );
522     WaitForSingleObject( p_condvar->event, INFINITE );
523     p_condvar->i_waiting_threads--;
524
525     /* Reacquire the mutex before returning. */
526     vlc_mutex_lock( p_mutex );
527
528     i_result = 0;
529
530 #elif defined( WIN32 )
531     if( !p_condvar->semaphore )
532     {
533         /* Increase our wait count */
534         p_condvar->i_waiting_threads++;
535
536         if( p_mutex->mutex )
537         {
538             /* It is only possible to atomically release the mutex and
539              * initiate the waiting on WinNT/2K/XP. Win9x doesn't have
540              * SignalObjectAndWait(). */
541             p_condvar->SignalObjectAndWait( p_mutex->mutex,
542                                             p_condvar->event,
543                                             INFINITE, FALSE );
544         }
545         else
546         {
547             LeaveCriticalSection( &p_mutex->csection );
548             WaitForSingleObject( p_condvar->event, INFINITE );
549         }
550
551         p_condvar->i_waiting_threads--;
552     }
553     else if( p_condvar->i_win9x_cv == 1 )
554     {
555         int i_waiting_threads;
556
557         /* Wait for the gate to be open */
558         WaitForSingleObject( p_condvar->event, INFINITE );
559
560         /* Increase our wait count */
561         p_condvar->i_waiting_threads++;
562
563         LeaveCriticalSection( &p_mutex->csection );
564         WaitForSingleObject( p_condvar->semaphore, INFINITE );
565
566         /* Decrement and test must be atomic */
567         EnterCriticalSection( &p_condvar->csection );
568
569         /* Decrease our wait count */
570         i_waiting_threads = --p_condvar->i_waiting_threads;
571
572         LeaveCriticalSection( &p_condvar->csection );
573
574         /* Reopen the gate if we were the last waiting thread */
575         if( !i_waiting_threads )
576             SetEvent( p_condvar->event );
577     }
578     else
579     {
580         int i_waiting_threads;
581
582         /* Increase our wait count */
583         p_condvar->i_waiting_threads++;
584
585         LeaveCriticalSection( &p_mutex->csection );
586         WaitForSingleObject( p_condvar->semaphore, INFINITE );
587
588         /* Decrement and test must be atomic */
589         EnterCriticalSection( &p_condvar->csection );
590
591         /* Decrease our wait count */
592         i_waiting_threads = --p_condvar->i_waiting_threads;
593
594         LeaveCriticalSection( &p_condvar->csection );
595
596         /* Signal that the last waiting thread just went through */
597         if( !i_waiting_threads )
598             SetEvent( p_condvar->event );
599     }
600
601     /* Reacquire the mutex before returning. */
602     vlc_mutex_lock( p_mutex );
603
604     i_result = 0;
605
606 #elif defined( HAVE_KERNEL_SCHEDULER_H )
607     if( p_condvar == NULL )
608     {
609         i_result = B_BAD_VALUE;
610     }
611     else if( p_mutex == NULL )
612     {
613         i_result = B_BAD_VALUE;
614     }
615     else if( p_condvar->init < 2000 )
616     {
617         i_result = B_NO_INIT;
618     }
619
620     /* The p_condvar->thread var is initialized before the unlock because
621      * it enables to identify when the thread is interrupted beetwen the
622      * unlock line and the suspend_thread line */
623     p_condvar->thread = find_thread( NULL );
624     vlc_mutex_unlock( p_mutex );
625     suspend_thread( p_condvar->thread );
626     p_condvar->thread = -1;
627
628     vlc_mutex_lock( p_mutex );
629     i_result = 0;
630
631 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
632
633 #   ifdef DEBUG
634     /* In debug mode, timeout */
635     struct timeval now;
636     struct timespec timeout;
637
638     gettimeofday( &now, NULL );
639     timeout.tv_sec = now.tv_sec + THREAD_COND_TIMEOUT;
640     timeout.tv_nsec = now.tv_usec * 1000;
641
642     i_result = pthread_cond_timedwait( &p_condvar->cond, &p_mutex->mutex,
643                                        &timeout );
644
645     if( i_result == ETIMEDOUT )
646     {
647         /* People keep pissing me off with this. --Meuuh */
648         msg_Dbg( p_condvar->p_this,
649                   "thread %d: secret message triggered "
650                   "at %s:%d (%s)", (int)pthread_self(),
651                   psz_file, i_line, strerror(i_result) );
652
653         i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex );
654     }
655
656 #   else
657     i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex );
658 #   endif
659
660     if ( i_result )
661     {
662         i_thread = (int)pthread_self();
663         psz_error = strerror(i_result);
664     }
665
666 #elif defined( HAVE_CTHREADS_H )
667     condition_wait( (condition_t)p_condvar, (mutex_t)p_mutex );
668     i_result = 0;
669
670 #endif
671
672     if( i_result )
673     {
674         msg_Err( p_condvar->p_this,
675                  "thread %d: cond_wait failed at %s:%d (%d:%s)",
676                  i_thread, psz_file, i_line, i_result, psz_error );
677     }
678
679     return i_result;
680 }
681
682 /*****************************************************************************
683  * vlc_cond_destroy: destroy a condition
684  *****************************************************************************/
685 #define vlc_cond_destroy( P_COND )                                          \
686     __vlc_cond_destroy( __FILE__, __LINE__, P_COND )
687
688 /*****************************************************************************
689  * vlc_thread_create: create a thread
690  *****************************************************************************/
691 #define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, PRIORITY, WAIT )         \
692     __vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, (void * ( * ) ( void * ))FUNC, PRIORITY, WAIT )
693
694 /*****************************************************************************
695  * vlc_thread_set_priority: set the priority of the calling thread
696  *****************************************************************************/
697 #define vlc_thread_set_priority( P_THIS, PRIORITY )                         \
698     __vlc_thread_set_priority( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PRIORITY )
699
700 /*****************************************************************************
701  * vlc_thread_ready: tell the parent thread we were successfully spawned
702  *****************************************************************************/
703 #define vlc_thread_ready( P_THIS )                                          \
704     __vlc_thread_ready( VLC_OBJECT(P_THIS) )
705
706 /*****************************************************************************
707  * vlc_thread_join: wait until a thread exits
708  *****************************************************************************/
709 #define vlc_thread_join( P_THIS )                                           \
710     __vlc_thread_join( VLC_OBJECT(P_THIS), __FILE__, __LINE__ )