]> granicus.if.org Git - python/commitdiff
Partial patch from SF #452266, by Jason Petrone.
authorGuido van Rossum <guido@python.org>
Tue, 16 Oct 2001 21:13:49 +0000 (21:13 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 16 Oct 2001 21:13:49 +0000 (21:13 +0000)
This changes Pythread_start_thread() to return the thread ID, or -1
for an error.  (It's technically an incompatible API change, but I
doubt anyone calls it.)

16 files changed:
Doc/lib/libthread.tex
Include/pythread.h
Misc/NEWS
Modules/threadmodule.c
Python/thread.c
Python/thread_beos.h
Python/thread_cthread.h
Python/thread_foobar.h
Python/thread_lwp.h
Python/thread_nt.h
Python/thread_os2.h
Python/thread_pth.h
Python/thread_pthread.h
Python/thread_sgi.h
Python/thread_solaris.h
Python/thread_wince.h

index 652058da375e848272901740214af4d3a2dd0601..a2e5b7e4a0c88c1badfa348752226c573ccaa495 100644 (file)
@@ -32,11 +32,10 @@ This is the type of lock objects.
 \end{datadesc}
 
 \begin{funcdesc}{start_new_thread}{function, args\optional{, kwargs}}
-Start a new thread.  The thread executes the function \var{function}
-with the argument list \var{args} (which must be a tuple).  The
-optional \var{kwargs} argument specifies a dictionary of keyword
-arguments.  When the
-function returns, the thread silently exits.  When the function
+Start a new thread and return its identifier.  The thread executes the function
+\var{function} with the argument list \var{args} (which must be a tuple).  The
+optional \var{kwargs} argument specifies a dictionary of keyword arguments.
+When the function returns, the thread silently exits.  When the function
 terminates with an unhandled exception, a stack trace is printed and
 then the thread exits (but other threads continue to run).
 \end{funcdesc}
index c0a718e5ade187b7f3917688846d0347dbc1eb2b..514cdeafe07d75f73cd60e566a1cff74b1485fc2 100644 (file)
@@ -13,7 +13,7 @@ extern "C" {
 #endif
 
 DL_IMPORT(void) PyThread_init_thread(void);
-DL_IMPORT(int) PyThread_start_new_thread(void (*)(void *), void *);
+DL_IMPORT(long) PyThread_start_new_thread(void (*)(void *), void *);
 DL_IMPORT(void) PyThread_exit_thread(void);
 DL_IMPORT(void) PyThread__PyThread_exit_thread(void);
 DL_IMPORT(long) PyThread_get_thread_ident(void);
index 690759b1709ffc23e9012a6e3c8c2281230566d2..1d86a4313ea343d496bfa3aefa8ce0e2adee519f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,8 @@ Core
 
 Library
 
+- thread.start_new_thread() now returns the thread ID (previously None).
+
 - doctest now excludes functions and classes not defined by the module
   being tested, thanks to Tim Hochberg.
 
@@ -91,6 +93,13 @@ C API
   Consequently, PyArg_ParseTuple's 'L' code also accepts int (as well
   as long) arguments.
 
+- PyThread_start_new_thread() now returns a long int giving the thread
+  ID, if one can be calculated; it returns -1 for error, 0 if no
+  thread ID is calculated (this is an incompatible change, but only
+  the thread module used this API).  This code has only really been
+  tested on Linux and Windows; other platforms please beware (and
+  report any bugs or strange behavior).
+
 New platforms
 
 Tests
index 7050914b06712434e225d598a2cb1c71f394f099..bdc7932c6e06041eab640896fbc6ae99adc40a41 100644 (file)
@@ -213,6 +213,7 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
 {
        PyObject *func, *args, *keyw = NULL;
        struct bootstate *boot;
+       long ident;
 
        if (!PyArg_ParseTuple(fargs, "OO|O:start_new_thread", &func, &args, &keyw))
                return NULL;
@@ -242,7 +243,8 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
        Py_INCREF(args);
        Py_XINCREF(keyw);
        PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
-       if (!PyThread_start_new_thread(t_bootstrap, (void*) boot)) {
+       ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
+       if (ident == -1) {
                PyErr_SetString(ThreadError, "can't start new thread\n");
                Py_DECREF(func);
                Py_DECREF(args);
@@ -250,20 +252,19 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
                PyMem_DEL(boot);
                return NULL;
        }
-       Py_INCREF(Py_None);
-       return Py_None;
+       return PyInt_FromLong(ident);
 }
 
 static char start_new_doc[] =
 "start_new_thread(function, args[, kwargs])\n\
 (start_new() is an obsolete synonym)\n\
 \n\
-Start a new thread.  The thread will call the function with positional\n\
-arguments from the tuple args and keyword arguments taken from the optional\n\
-dictionary kwargs.  The thread exits when the function returns; the return\n\
-value is ignored.  The thread will also exit when the function raises an\n\
-unhandled exception; a stack trace will be printed unless the exception is\n\
-SystemExit.";
+Start a new thread and return its identifier.  The thread will call the\n\
+function with positional arguments from the tuple args and keyword arguments\n\
+taken from the optional dictionary kwargs.  The thread exits when the\n\
+function returns; the return value is ignored.  The thread will also exit\n\
+when the function raises an unhandled exception; a stack trace will be\n\
+printed unless the exception is SystemExit.\n";
 
 static PyObject *
 thread_PyThread_exit_thread(PyObject *self, PyObject *args)
index 3558af0afcd2bb46ffe8b1d753f9cad7013217b9..df42f316be0529569283c046f7958492d5df31b7 100644 (file)
@@ -111,7 +111,6 @@ void PyThread_init_thread(void)
 
 #ifdef HAVE_PTH
 #include "thread_pth.h"
-#undef _POSIX_THREADS
 #endif
 
 #ifdef _POSIX_THREADS
index 046d37eea79f9d718e01edb3eaf58845a791e177..3f843474bffaa6d489ea58909f1d104dd0edbbb6 100644 (file)
@@ -112,7 +112,7 @@ static void PyThread__init_thread( void )
 
 static int32 thread_count = 0;
 
-int PyThread_start_new_thread( void (*func)(void *), void *arg )
+long PyThread_start_new_thread( void (*func)(void *), void *arg )
 {
        status_t success = 0;
        thread_id tid;
@@ -131,7 +131,7 @@ int PyThread_start_new_thread( void (*func)(void *), void *arg )
                success = resume_thread( tid );
        }
 
-       return ( success == B_NO_ERROR ? 1 : 0 );
+       return ( success == B_NO_ERROR ? tid : -1 );
 }
 
 long PyThread_get_thread_ident( void )
index 080505134dde6115d4530fe4d9cab4b85d893a40..8487cc295f695674fbe939ac333067980d0c447d 100644 (file)
@@ -14,7 +14,7 @@ PyThread__init_thread(void)
 /*
  * Thread support.
  */
-int
+long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
        int success = 0;        /* init not needed when SOLARIS_THREADS and */
@@ -27,7 +27,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
         * so well do it here
         */
        cthread_detach(cthread_fork((cthread_fn_t) func, arg));
-       return success < 0 ? 0 : 1;
+       return success < 0 ? -1 : 0;
 }
 
 long
index 6edd0f93a50a45d289516d4bb53d3cfe810931db..4baf7e78463db2558559bde25ce5980fd2530e82 100644 (file)
@@ -10,7 +10,7 @@ PyThread__init_thread(void)
 /*
  * Thread support.
  */
-int
+long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
        int success = 0;        /* init not needed when SOLARIS_THREADS and */
@@ -19,7 +19,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
        dprintf(("PyThread_start_new_thread called\n"));
        if (!initialized)
                PyThread_init_thread();
-       return success < 0 ? 0 : 1;
+       return success < 0 ? -1 : 0;
 }
 
 long
index bf44e0425cb5acca17bba22a1999b98db21c89f9..f6e688568b0455547e8def570226c6e9090422c9 100644 (file)
@@ -26,7 +26,7 @@ static void PyThread__init_thread(void)
  */
 
 
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
        thread_t tid;
        int success;
@@ -34,7 +34,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
        if (!initialized)
                PyThread_init_thread();
        success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
-       return success < 0 ? 0 : 1;
+       return success < 0 ? -1 : 0;
 }
 
 long PyThread_get_thread_ident(void)
index 1d276274eb4cfdb3271f220a4712c9319799dcbb..21aac29a496371dd138ac3c3a13bfdcd2e8c2b5b 100644 (file)
@@ -5,6 +5,7 @@
 #include <windows.h>
 #include <limits.h>
 #include <process.h>
+#include <Python.h>
 
 typedef struct NRMUTEX {
        LONG   owned ;
@@ -12,6 +13,8 @@ typedef struct NRMUTEX {
        HANDLE hevent ;
 } NRMUTEX, *PNRMUTEX ;
 
+/* dictionary to correlate thread ids with the handle needed to terminate them*/
+static PyObject *threads = NULL;
 
 typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ;
 
@@ -145,28 +148,67 @@ long PyThread_get_thread_ident(void);
  */
 static void PyThread__init_thread(void)
 {
+       threads = PyDict_New();
 }
 
 /*
  * Thread support.
  */
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+
+typedef struct {
+       void (*func)(void*);
+       void *arg;                      
+       long id;
+       HANDLE done;
+} callobj;
+
+static int
+bootstrap(void *call)
+{
+       callobj *obj = (callobj*)call;
+       /* copy callobj since other thread might free it before we're done */
+       void (*func)(void*) = obj->func;
+       void *arg = obj->arg;
+
+       obj->id = PyThread_get_thread_ident();
+       ReleaseSemaphore(obj->done, 1, NULL);
+       func(arg);
+       return 0;
+}
+
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
        unsigned long rv;
        int success = 0;
+       callobj *obj;
+       int id;
+       PyObject *key, *val;
 
        dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
        if (!initialized)
                PyThread_init_thread();
 
-       rv = _beginthread(func, 0, arg); /* use default stack size */
+       obj = malloc(sizeof(callobj)); 
+       obj->func = func;
+       obj->arg = arg;
+       obj->done = CreateSemaphore(NULL, 0, 1, NULL);
+
+       rv = _beginthread(func, 0, obj); /* use default stack size */
  
        if (rv != (unsigned long)-1) {
                success = 1;
                dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", PyThread_get_thread_ident(), rv));
        }
 
-       return success;
+       /* wait for thread to initialize and retrieve id */
+       WaitForSingleObject(obj->done, 5000);  /* maybe INFINITE instead of 5000? */
+       CloseHandle((HANDLE)obj->done);
+       key = PyLong_FromLong(obj->id);
+       val = PyLong_FromLong((long)rv);
+       PyDict_SetItem(threads, key, val);
+       id = obj->id;
+       free(obj);
+       return id;
 }
 
 /*
index 3f913c5dbef6d0a87c4303b87a7805458e9b78c7..31800d6c26465cdf3065fb1e02dc492662bd8efd 100644 (file)
@@ -21,16 +21,16 @@ PyThread__init_thread(void)
 /*
  * Thread support.
  */
-int
+long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
   int aThread;
-  int success = 1;
+  int success = 0;
 
   aThread = _beginthread(func,NULL,65536,arg);
 
   if( aThread == -1 ) {
-    success = 0;
+    success = -1;
     fprintf(stderr,"aThread failed == %d",aThread);
     dprintf(("_beginthread failed. return %ld\n", errno));
   }
index 6596b1a8c77fc755a3aac0d6a865ecf5af6d0d70..71e0d042cff9662087b0c2914a415ff9a623fc9a 100644 (file)
@@ -44,7 +44,7 @@ static void PyThread__init_thread(void)
  */
 
 
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
        pth_t th;
        dprintf(("PyThread_start_new_thread called\n"));
@@ -56,7 +56,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
                                 (void *)arg
                                 );
 
-       return th == NULL ? 0 : 1;
+       return th;
 }
 
 long PyThread_get_thread_ident(void)
index 7170c8a81202d024ac0f2910ec1c0e25c90bf690..0fbafdafc708c8042addb1d66c2348a65a70c184 100644 (file)
@@ -143,7 +143,7 @@ PyThread__init_thread(void)
  */
 
 
-int 
+long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
        pthread_t th;
@@ -210,7 +210,11 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
                pthread_detach(th);
 #endif
        }
-       return success != 0 ? 0 : 1;
+#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
+       return (long) th;
+#else
+       return (long) *(long *) &th;
+#endif
 }
 
 /* XXX This implementation is considered (to quote Tim Peters) "inherently
index 863284e412a08cb466859e3877ba95afd48e999e..eda79726f72bb045639951512d6f5dd0c40048ac 100644 (file)
@@ -168,7 +168,7 @@ static void clean_threads(void)
        }
 }
 
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
 #ifdef USE_DL
        long addr, size;
@@ -223,7 +223,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
        }
        if (usunsetlock(count_lock) < 0)
                perror("usunsetlock (count_lock)");
-       return success < 0 ? 0 : 1;
+       return success;
 }
 
 long PyThread_get_thread_ident(void)
index 66bdfa25a3445438032ee7a71d1444db68672319..4c958b915e2aa5565bd3fa42bade19f2de53c491 100644 (file)
@@ -36,9 +36,10 @@ new_func(void *funcarg)
 }
 
 
-int 
+long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
+       thread_t tid;
        struct func_arg *funcarg;
        int success = 0;        /* init not needed when SOLARIS_THREADS and */
                                /* C_THREADS implemented properly */
@@ -50,12 +51,12 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
        funcarg->func = func;
        funcarg->arg = arg;
        if (thr_create(0, 0, new_func, funcarg,
-                      THR_DETACHED | THR_NEW_LWP, 0)) {
+                      THR_DETACHED | THR_NEW_LWP, &tid)) {
                perror("thr_create");
                free((void *) funcarg);
                success = -1;
        }
-       return success < 0 ? 0 : 1;
+       return tid;
 }
 
 long
index 3790bdab7d07e7ae82d7350d249bf9199c200b1c..b5129b2149d2a16189052117ea0a747602623abd 100644 (file)
@@ -22,10 +22,10 @@ static void PyThread__init_thread(void)
 /*
  * Thread support.
  */
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
        long rv;
-       int success = 0;
+       int success = -1;
 
        dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
        if (!initialized)
@@ -34,7 +34,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
        rv = _beginthread(func, 0, arg); /* use default stack size */
  
        if (rv != -1) {
-               success = 1;
+               success = 0;
                dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident()));
        }