Partial patch from SF #452266, by Jason Petrone.

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.)
This commit is contained in:
Guido van Rossum 2001-10-16 21:13:49 +00:00
parent 6f543b606d
commit 3c28863e08
16 changed files with 97 additions and 42 deletions

View 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}

View 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);

View File

@ -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

View 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)

View File

@ -111,7 +111,6 @@ void PyThread_init_thread(void)
#ifdef HAVE_PTH
#include "thread_pth.h"
#undef _POSIX_THREADS
#endif
#ifdef _POSIX_THREADS

View 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 )

View 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

View 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

View 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)

View 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;
}
/*

View 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));
}

View 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)

View 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

View 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)

View 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

View 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()));
}