diff options
author | kupries <kupries> | 2000-05-02 22:02:32 (GMT) |
---|---|---|
committer | kupries <kupries> | 2000-05-02 22:02:32 (GMT) |
commit | bfac38b888b4dee3f80767f8da8691a1154891b7 (patch) | |
tree | 73773fe6b41f1aec6a847be17c221d4a5ee4cd27 /unix | |
parent | 492f9b8edd489f07ffd0741d0e9f23c0433334f9 (diff) | |
download | tcl-bfac38b888b4dee3f80767f8da8691a1154891b7.zip tcl-bfac38b888b4dee3f80767f8da8691a1154891b7.tar.gz tcl-bfac38b888b4dee3f80767f8da8691a1154891b7.tar.bz2 |
2000-05-02 Andreas Kupries <a.kupries@westend.com>
* Overall changes:
(1) Implementation of joinable threads for all platforms.
(2) Additional API's for channels. Required to allow the
thread extension to move channels between threads.
* generic/tcl.decls (lines 1360f): Added Tcl_JoinThread,
Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel,
Tcl_SpliceChannel, Tcl_IsChannelExisting and
Tcl_ClearChannelHandlers (slots 394 to 400).
* generic/tclIO.c: Implemented Tcl_IsChannelRegistered,
Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
Tcl_IsChannelExisting and Tcl_ClearChannelHandlers.
Tcl_CutChannel uses code from CloseChannel. Replaced this code
by a call to Tcl_CutChannel. Replaced several code fragments
adding channels to the channel list with calls to
Tcl_SpliceChannel. Removed now unused variables from
CloseChannel and Tcl_UnstackChannel. Tcl_ClearChannelHandlers
uses code from Tcl_Close. Replaced this code by a call to
Tcl_ClearChannelHandlers. Removed now unused variables from
Tcl_Close. Added the subcommands 'cut', 'forgetch', 'splice' and
'isshared' to the test code
(TclTestChannelCmd).
* unix/tclUnixThread.c: Implemented Tcl_JoinThread using the
pthread-functionality.
* win/tclWinThrd.c: Fixed several small typos in comments.
Implemented Tcl_JoinThread using a platform independent
emulation layer (see generic/tclThreadJoin.c below). Added
'joinLock' to serialize Tcl_CreateThread and TclpExitThread to
prevent a race for joinable threads.
* mac/tclMacThrd.c: Implemented Tcl_JoinThread using a platform
independent emulation layer (see generic/tclThreadJoin.c
below). Due to the cooperative nature of threading on this
platform the race mentioned above is not present.
* generic/tclThreadJoin.c: New file. Contains a platform
independent emulation layer helping in the implementation of
joinable threads for the win and mac platforms.
* generic/tclInt.h: Added declarations for TclJoinThread,
TclRememberJoinableThread and TclSignalExitThread. These
procedures define the API of the emulation layer for joinable
threads (see generic/tclThreadJoin.c above).
* win/Makefile.in:
* win/makefile.vc: Added generic/tclTheadJoin.o to the rules.
* mac/: I don't know to which file generic/tclTheadJoin.o has to
be added to so that it compiles. Sorry.
* unix/tclUnixChan.c: #ifdef'd the thread-local list of file
channels as it prevents us from transfering channels. To restore
this we may need an extended interface to drivers in the
future. Target: 9.0. Found while testing the new transfer of
channels. The information in this list for a channel was left
behind and then crashed the system during finalization.
* generic/tclThreadTest.c: Added -joinable flag to 'testthread
create'. Added subcommand 'testthread join'.
* doc/CrtChannel.3: Added documentation for Tcl_IsChannelRegistered,
Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
Tcl_IsChannelExisting and Tcl_ClearChannelHandlers.
* doc/Thread.3: Added documentation for Tcl_JoinThread.
* tests/thread.test: Added tests for joining of threads.
Diffstat (limited to 'unix')
-rw-r--r-- | unix/Makefile.in | 9 | ||||
-rw-r--r-- | unix/tclUnixChan.c | 28 | ||||
-rw-r--r-- | unix/tclUnixThrd.c | 36 |
3 files changed, 65 insertions, 8 deletions
diff --git a/unix/Makefile.in b/unix/Makefile.in index df69f9c..c28fcb7 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -5,7 +5,7 @@ # "autoconf" program (constructs like "@foo@" will get replaced in the # actual Makefile. # -# RCS: @(#) $Id: Makefile.in,v 1.63 2000/04/25 20:58:48 hobbs Exp $ +# RCS: @(#) $Id: Makefile.in,v 1.64 2000/05/02 22:02:36 kupries Exp $ VERSION = @TCL_VERSION@ @@ -274,6 +274,7 @@ GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \ tclResolve.o tclResult.o tclScan.o tclStringObj.o tclThread.o \ tclStubInit.o tclStubLib.o tclTimer.o tclUtf.o tclUtil.o tclVar.o + STUB_LIB_OBJS = tclStubLib.o ${COMPAT_OBJS} OBJS = ${GENERIC_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} ${COMPAT_OBJS} @DL_OBJS@ @@ -352,6 +353,7 @@ GENERIC_SRCS = \ $(GENERIC_DIR)/tclTestObj.c \ $(GENERIC_DIR)/tclTestProcBodyObj.c \ $(GENERIC_DIR)/tclThread.c \ + $(GENERIC_DIR)/tclThreadJoin.c \ $(GENERIC_DIR)/tclTimer.c \ $(GENERIC_DIR)/tclUtil.c \ $(GENERIC_DIR)/tclVar.c @@ -473,7 +475,7 @@ topDirName: gendate: yacc -l $(GENERIC_DIR)/tclGetDate.y sed -e 's/yy/TclDate/g' -e '/^#include <values.h>/d' \ - -e 's?SCCSID?RCS: @(#) $$Id: Makefile.in,v 1.63 2000/04/25 20:58:48 hobbs Exp $$?' \ + -e 's?SCCSID?RCS: @(#) $$Id: Makefile.in,v 1.64 2000/05/02 22:02:36 kupries Exp $$?' \ -e '/#ifdef __STDC__/,/#endif/d' -e '/TclDateerrlab:/d' \ -e '/TclDatenewstate:/d' -e '/#pragma/d' \ -e '/#include <inttypes.h>/d' -e 's/const /CONST /g' \ @@ -908,6 +910,9 @@ tclTimer.o: $(GENERIC_DIR)/tclTimer.c tclThread.o: $(GENERIC_DIR)/tclThread.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThread.c +tclThreadJoin.o: $(GENERIC_DIR)/tclThreadJoin.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadJoin.c + tclThreadTest.o: $(GENERIC_DIR)/tclThreadTest.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadTest.c diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c index 1bf4818..d687c9c 100644 --- a/unix/tclUnixChan.c +++ b/unix/tclUnixChan.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixChan.c,v 1.17 2000/04/19 09:17:03 hobbs Exp $ + * RCS: @(#) $Id: tclUnixChan.c,v 1.18 2000/05/02 22:02:37 kupries Exp $ */ #include "tclInt.h" /* Internal definitions for Tcl. */ @@ -76,8 +76,10 @@ typedef struct FileState { int validMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which operations are valid on the file. */ +#ifdef DEPRECATED struct FileState *nextPtr; /* Pointer to next file in list of all * file channels. */ +#endif } FileState; #ifdef SUPPORTS_TTY @@ -108,6 +110,7 @@ typedef struct TtyAttrs { #endif /* !SUPPORTS_TTY */ +#ifdef DEPRECATED typedef struct ThreadSpecificData { /* * List of all file channels currently open. This is per thread and is @@ -118,6 +121,7 @@ typedef struct ThreadSpecificData { } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; +#endif /* * This structure describes per-instance state of a tcp based channel. @@ -442,10 +446,13 @@ FileCloseProc(instanceData, interp) Tcl_Interp *interp; /* For error reporting - unused. */ { FileState *fsPtr = (FileState *) instanceData; +#ifdef DEPRECATED FileState **nextPtrPtr; +#endif int errorCode = 0; +#ifdef DEPRECATED ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - +#endif Tcl_DeleteFileHandler(fsPtr->fd); /* @@ -458,6 +465,7 @@ FileCloseProc(instanceData, interp) errorCode = errno; } } +#ifdef DEPRECATED for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { if ((*nextPtrPtr) == fsPtr) { @@ -465,6 +473,7 @@ FileCloseProc(instanceData, interp) break; } } +#endif ckfree((char *) fsPtr); return errorCode; } @@ -1269,7 +1278,9 @@ TclpOpenFileChannel(interp, fileName, modeString, permissions) char channelName[16 + TCL_INTEGER_SPACE]; Tcl_DString ds, buffer; Tcl_ChannelType *channelTypePtr; +#ifdef DEPRECATED ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); +#endif mode = TclGetOpenMode(interp, modeString, &seekFlag); if (mode == -1) { @@ -1340,8 +1351,10 @@ TclpOpenFileChannel(interp, fileName, modeString, permissions) fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState)); } +#ifdef DEPRECATED fsPtr->nextPtr = tsdPtr->firstFilePtr; tsdPtr->firstFilePtr = fsPtr; +#endif fsPtr->validMask = channelPermissions | TCL_EXCEPTION; fsPtr->fd = fd; @@ -1403,7 +1416,9 @@ Tcl_MakeFileChannel(handle, mode) FileState *fsPtr; char channelName[16 + TCL_INTEGER_SPACE]; int fd = (int) handle; +#ifdef DEPRECATED ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); +#endif if (mode == 0) { return NULL; @@ -1411,22 +1426,27 @@ Tcl_MakeFileChannel(handle, mode) sprintf(channelName, "file%d", fd); + /* * Look to see if a channel with this fd and the same mode already exists. * If the fd is used, but the mode doesn't match, return NULL. */ - + +#ifdef DEPRECATED for (fsPtr = tsdPtr->firstFilePtr; fsPtr != NULL; fsPtr = fsPtr->nextPtr) { if (fsPtr->fd == fd) { return ((mode|TCL_EXCEPTION) == fsPtr->validMask) ? fsPtr->channel : NULL; } } +#endif fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState)); + +#ifdef DEPRECATED fsPtr->nextPtr = tsdPtr->firstFilePtr; tsdPtr->firstFilePtr = fsPtr; - +#endif fsPtr->fd = fd; fsPtr->validMask = mode | TCL_EXCEPTION; fsPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName, diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 2e8e8a4..bbbb3f2 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -53,8 +53,6 @@ static pthread_mutex_t *allocLockPtr = &allocLock; #endif /* TCL_THREADS */ - - /* *---------------------------------------------------------------------- * @@ -133,6 +131,40 @@ Tcl_CreateThread(idPtr, proc, clientData, stackSize, flags) #endif /* TCL_THREADS */ } +/* + *---------------------------------------------------------------------- + * + * Tcl_JoinThread -- + * + * This procedure waits upon the exit of the specified thread. + * + * Results: + * TCL_OK if the wait was successful, TCL_ERROR else. + * + * Side effects: + * The result area is set to the exit code of the thread we + * waited upon. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_JoinThread(id, state) + Tcl_ThreadId id; /* Id of the thread to wait upon */ + int* state; /* Reference to the storage the result + * of the thread we wait upon will be + * written into. */ +{ +#ifdef TCL_THREADS + int result; + + result = pthread_join ((pthread_t) id, (VOID**) state); + return (result == 0) ? TCL_OK : TCL_ERROR; +#else + return TCL_ERROR; +#endif +} + #ifdef TCL_THREADS /* *---------------------------------------------------------------------- |