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