8888a017080c665f2c2551f5247b9cfbf0a0600e
[vlc.git] / src / misc / threads.c
1 /*****************************************************************************
2  * threads.c : threads implementation for the VideoLAN client
3  *****************************************************************************
4  * Copyright (C) 1999-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *          Clément Sténac
11  *          Rémi Denis-Courmont
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33
34 #include "libvlc.h"
35 #include <assert.h>
36 #include <errno.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40
41 #if defined( LIBVLC_USE_PTHREAD )
42 # include <sched.h>
43 #endif
44
45 struct vlc_thread_boot
46 {
47     void * (*entry) (vlc_object_t *);
48     vlc_object_t *object;
49 };
50
51 static void *thread_entry (void *data)
52 {
53     vlc_object_t *obj = ((struct vlc_thread_boot *)data)->object;
54     void *(*func) (vlc_object_t *) = ((struct vlc_thread_boot *)data)->entry;
55
56     free (data);
57     msg_Dbg (obj, "thread started");
58     func (obj);
59     msg_Dbg (obj, "thread ended");
60
61     return NULL;
62 }
63
64 #undef vlc_thread_create
65 /*****************************************************************************
66  * vlc_thread_create: create a thread
67  *****************************************************************************
68  * Note that i_priority is only taken into account on platforms supporting
69  * userland real-time priority threads.
70  *****************************************************************************/
71 int vlc_thread_create( vlc_object_t *p_this, void *(*func) ( vlc_object_t * ),
72                        int i_priority )
73 {
74     int i_ret;
75     vlc_object_internals_t *p_priv = vlc_internals( p_this );
76
77     struct vlc_thread_boot *boot = malloc (sizeof (*boot));
78     if (boot == NULL)
79         return errno;
80     boot->entry = func;
81     boot->object = p_this;
82
83     /* Make sure we don't re-create a thread if the object has already one */
84     assert( !p_priv->b_thread );
85
86     i_ret = vlc_clone( &p_priv->thread_id, thread_entry, boot, i_priority );
87     if( i_ret == 0 )
88         p_priv->b_thread = true;
89     else
90     {
91         errno = i_ret;
92         msg_Err( p_this, "cannot create thread (%m)" );
93         free (boot);
94     }
95
96     return i_ret;
97 }
98
99 #undef vlc_thread_join
100 /*****************************************************************************
101  * vlc_thread_join: wait until a thread exits, inner version
102  *****************************************************************************/
103 void vlc_thread_join( vlc_object_t *p_this )
104 {
105     vlc_object_internals_t *p_priv = vlc_internals( p_this );
106
107     vlc_join( p_priv->thread_id, NULL );
108     p_priv->b_thread = false;
109 }
110
111 void vlc_thread_cancel (vlc_object_t *obj)
112 {
113     vlc_object_internals_t *priv = vlc_internals (obj);
114
115     if (priv->b_thread)
116         vlc_cancel (priv->thread_id);
117 }
118
119 /*** Global locks ***/
120
121 void vlc_global_mutex (unsigned n, bool acquire)
122 {
123     static vlc_mutex_t locks[] = {
124         VLC_STATIC_MUTEX,
125         VLC_STATIC_MUTEX,
126         VLC_STATIC_MUTEX,
127     };
128     assert (n < (sizeof (locks) / sizeof (locks[0])));
129     vlc_mutex_t *lock = locks + n;
130
131     if (acquire)
132         vlc_mutex_lock (lock);
133     else
134         vlc_mutex_unlock (lock);
135
136     /* Compile-time assertion ;-) */
137     char enough_locks[(sizeof (locks) / sizeof (locks[0])) - VLC_MAX_MUTEX];
138     (void) enough_locks;
139 }