]> git.sesse.net Git - vlc/commitdiff
Added initial support for TLS (Thread Local Storage) variables
authorClément Stenac <zorglub@videolan.org>
Mon, 18 Dec 2006 21:40:12 +0000 (21:40 +0000)
committerClément Stenac <zorglub@videolan.org>
Mon, 18 Dec 2006 21:40:12 +0000 (21:40 +0000)
include/vlc_threads.h
include/vlc_threads_funcs.h
src/misc/threads.c
test/NativeLibvlcTest.py
test/native/init.c
test/native/tests.h
test/native/threads.c [new file with mode: 0644]
test/setup.py

index e36a07cdf08f27c32b21070e7e9c86339a854bfe..67ef7619d80b35d50f9375490c76d562eba30417 100644 (file)
@@ -139,6 +139,9 @@ typedef struct
     pth_cond_t cond;
     vlc_object_t * p_this;
 } vlc_cond_t;
+typedef struct
+{
+} vlc_threadvar_t;
 
 #elif defined( ST_INIT_IN_ST_H )
 typedef st_thread_t      vlc_thread_t;
@@ -152,6 +155,9 @@ typedef struct
     st_cond_t cond;
     vlc_object_t * p_this;
 } vlc_cond_t;
+typedef struct
+{
+} vlc_threadvar_t;
 
 #elif defined( WIN32 ) || defined( UNDER_CE )
 typedef HANDLE vlc_thread_t;
@@ -182,6 +188,11 @@ typedef struct
     vlc_object_t * p_this;
 } vlc_cond_t;
 
+typedef struct
+{
+    DWORD   handle;
+} vlc_threadvar_t;
+
 #elif defined( HAVE_KERNEL_SCHEDULER_H )
 /* This is the BeOS implementation of the vlc threads, note that the mutex is
  * not a real mutex and the cond_var is not like a pthread cond_var but it is
@@ -205,6 +216,11 @@ typedef struct
     vlc_object_t * p_this;
 } vlc_cond_t;
 
+typedef struct
+{
+} vlc_threadvar_t;
+
+
 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
 typedef pthread_t       vlc_thread_t;
 typedef struct
@@ -218,6 +234,11 @@ typedef struct
     vlc_object_t * p_this;
 } vlc_cond_t;
 
+typedef struct
+{
+    pthread_key_t handle;
+} vlc_threadvar_t;
+
 #elif defined( HAVE_CTHREADS_H )
 typedef cthread_t       vlc_thread_t;
 
@@ -244,5 +265,10 @@ typedef struct
     vlc_object_t * p_this;
 } vlc_cond_t;
 
+typedef struct
+{
+    cthread_key_t handle;
+} vlc_threadvar_t;
+
 #endif
 
index f5bda035c870bfcbbc5ef9a5f6ff88246fb3f809..078f5d5090c4a8aed4ca62ce062eb1edc65eae0a 100644 (file)
@@ -38,6 +38,7 @@ VLC_EXPORT( int,  __vlc_mutex_init,    ( vlc_object_t *, vlc_mutex_t * ) );
 VLC_EXPORT( int,  __vlc_mutex_destroy, ( const char *, int, vlc_mutex_t * ) );
 VLC_EXPORT( int,  __vlc_cond_init,     ( vlc_object_t *, vlc_cond_t * ) );
 VLC_EXPORT( int,  __vlc_cond_destroy,  ( const char *, int, vlc_cond_t * ) );
+VLC_EXPORT( int, __vlc_threadvar_create, (vlc_object_t *, vlc_threadvar_t * ) );
 VLC_EXPORT( int,  __vlc_thread_create, ( vlc_object_t *, const char *, int, const char *, void * ( * ) ( void * ), int, vlc_bool_t ) );
 VLC_EXPORT( int,  __vlc_thread_set_priority, ( vlc_object_t *, const char *, int, int ) );
 VLC_EXPORT( void, __vlc_thread_ready,  ( vlc_object_t * ) );
@@ -547,6 +548,71 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line,
 #define vlc_cond_destroy( P_COND )                                          \
     __vlc_cond_destroy( __FILE__, __LINE__, P_COND )
 
+/*****************************************************************************
+ * vlc_threadvar_create: create a thread-local variable
+ *****************************************************************************/
+#define vlc_threadvar_create( PTHIS, P_TLS )                                 \
+   __vlc_threadvar_create( PTHIS, P_TLS )
+
+/*****************************************************************************
+ * vlc_threadvar_set: create: set the value of a thread-local variable
+ *****************************************************************************/
+#define vlc_threadvar_set( P_TLS , P_VAL )                                   \
+   __vlc_threadvar_set( __FILE__, __LINE__, P_TLS, P_VAL )
+
+static inline int __vlc_threadvar_set( char* psz_file, int line,
+                                        vlc_threadvar_t * p_tls, void *p_value )
+{
+    int i_ret;
+
+#if defined( PTH_INIT_IN_PTH_H ) || \
+    defined( ST_INIT_IN_ST_H ) || defined( HAVE_KERNEL_SCHEDULER_H )
+    return -1;
+
+#elif defined( UNDER_CE ) || defined( WIN32 )
+    i_ret = ( TlsSetValue( &p_tls->handle, p_value ) != 0 );
+
+#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
+    i_ret = pthread_setspecific( p_tls->handle, p_value );
+
+#elif defined( HAVE_CTHREADS_H )
+    i_ret = cthread_setspecific( p_tls->handle, p_value );
+#endif
+
+    return i_ret;
+}
+
+/*****************************************************************************
+ * vlc_threadvar_get: create: get the value of a thread-local variable
+ *****************************************************************************/
+#define vlc_threadvar_get( P_TLS )                                         \
+   __vlc_threadvar_get( __FILE__, __LINE__, P_TLS )
+
+static inline void* __vlc_threadvar_get( char* psz_file, int line,
+                                         vlc_threadvar_t * p_tls )
+{
+    void* p_ret;
+
+#if defined( PTH_INIT_IN_PTH_H ) || \
+    defined( ST_INIT_IN_ST_H ) || defined( HAVE_KERNEL_SCHEDULER_H )
+    return NULL;
+
+#elif defined( UNDER_CE ) || defined( WIN32 )
+    p_ret = TlsGetValue( &p_tls->handle );
+
+#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
+    p_ret = pthread_getspecific( p_tls->handle );
+
+#elif defined( HAVE_CTHREADS_H )
+    if ( !cthread_getspecific( p_tls->handle, &p_ret ) )
+    {
+        p_ret = NULL;
+    }
+#endif
+
+    return p_ret;
+}
+
 /*****************************************************************************
  * vlc_thread_create: create a thread
  *****************************************************************************/
index da17ec9dda560cbf89752fd2f19d7e12a7fcb58c..367511be2df359986856a8f5ea7e38b617df3d86 100644 (file)
@@ -500,6 +500,36 @@ int __vlc_cond_destroy( const char * psz_file, int i_line, vlc_cond_t *p_condvar
     return i_result;
 }
 
+/*****************************************************************************
+ * vlc_tls_create: create a thread-local variable
+ *****************************************************************************/
+int __vlc_threadvar_create( vlc_object_t *p_this, vlc_threadvar_t *p_tls )
+{
+#if defined( PTH_INIT_IN_PTH_H )
+#elif defined( HAVE_KERNEL_SCHEDULER_H )
+#elif defined( ST_INIT_IN_ST_H )
+    msg_Err( p_this, "TLS not implemented" );
+    return VLC_EGENERIC;
+
+#elif defined( UNDER_CE ) || defined( WIN32 )
+#elif defined( WIN32 )
+    p_tls->handle = TlsAlloc();
+    if( p_tls->handle == 0xFFFFFFFF )
+    {
+        return VLC_EGENERIC;
+    }
+
+    msg_Err( p_this, "TLS not implemented" );
+    return VLC_EGENERIC;
+
+#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
+    return pthread_key_create( &p_tls->handle, NULL );
+
+#elif defined( HAVE_CTHREADS_H )
+    return cthread_keycreate( &p_tls-handle );
+#endif
+}
+
 /*****************************************************************************
  * vlc_thread_create: create a thread, inner version
  *****************************************************************************
index 89d42232d226a06e9b344d27731324d144b684b9..2e213fa64cfc0184e912e924a04202065b8ca0d2 100644 (file)
@@ -3,6 +3,9 @@ import unittest
 import native_libvlc_test
 
 class NativeLibvlcTestCase( unittest.TestCase ):
+    def testTls( self ):
+        """[Thread] Set TLS"""
+        native_libvlc_test.threadvar_test()
     def test1Exception( self ):
         """[LibVLC] Checks libvlc_exception"""
 #      native_libvlc_test.exception_test()
index f74379f9bbbf38d622070a9ee122c119f6b6a1a4..4e0c044b77add4bc8b790d32d50ceae5deb7ce6d 100644 (file)
@@ -24,6 +24,7 @@ static PyMethodDef native_libvlc_test_methods[] = {
    DEF_METHOD( bsearch_direct_test, "Test Bsearch without structure" )
    DEF_METHOD( bsearch_member_test, "Test Bsearch with structure" )
    DEF_METHOD( dict_test, "Test dictionnaries" )
+   DEF_METHOD( threadvar_test, "Test TLS" )
    { NULL, NULL, 0, NULL }
 };
 
index 7f47cbb7e6c387a3c1fb76baf79ad74699ea0ebc..f995021fe9683747a7b7f5bc02071a9bd063c906 100644 (file)
@@ -6,6 +6,8 @@ PyObject *create_destroy( PyObject *self, PyObject *args );
 PyObject *playlist_test( PyObject *self, PyObject *args );
 PyObject *vlm_test( PyObject *self, PyObject *args );
 
+PyObject *threadvar_test( PyObject *self, PyObject *args );
+
 /* Stats */
 PyObject *timers_test( PyObject *self, PyObject *args );
 
diff --git a/test/native/threads.c b/test/native/threads.c
new file mode 100644 (file)
index 0000000..d49be79
--- /dev/null
@@ -0,0 +1,19 @@
+#include "../pyunit.h"
+#include <vlc/vlc.h>
+
+PyObject *threadvar_test( PyObject *self, PyObject *args )
+{
+    void *p_foo = malloc(1);
+    vlc_threadvar_t key, key2;
+
+    vlc_threadvar_create( NULL, &key );
+    vlc_threadvar_set( &key, p_foo );
+    ASSERT( vlc_threadvar_get( &key ) == p_foo, "key does not match" );
+
+    vlc_threadvar_create( NULL, &key2 );
+    vlc_threadvar_set( &key2, NULL );
+    ASSERT( vlc_threadvar_get( &key2 ) == NULL, "key2 does not match" );
+    
+    Py_INCREF( Py_None );
+    return Py_None;
+}
index 9d9278b8cb99bb4eef6887894d288fc80b7b0556..d03c4eb374e33e796d9eff5bd48f9fec3178b571 100644 (file)
@@ -42,7 +42,7 @@ def get_ldflags():
 native_libvlc_test = Extension( 'native_libvlc_test',
                 sources = ['native/init.c', 'native/url.c', 'native/i18n.c',
                            'native/stats.c', 'native/libvlc.c', 'native/profiles.c',
-                'native/algo.c'],
+                'native/algo.c', 'native/threads.c'],
                 include_dirs = ['../include', '../', '/usr/win32/include' ],
                 extra_objects = [ '../src/.libs/libvlc.so', '../src/.libs/libvlc-control.so' ],
                 extra_compile_args = get_cflags(),