00001 #define TCL_THREADS
00002
00003 #include <tk.h>
00004 #include <tcl.h>
00005 #include <cstdio>
00006 #include <malloc.h>
00007 #include <cmath>
00008 #include <cstring>
00009 #include <iostream>
00010
00011
00012
00013
00014
00015 #include "imgclass.hpp"
00016 #include "xgray_tcl.hpp"
00017 #include "guithread.hpp"
00018
00019 using namespace std;
00020
00021 extern "C" int Xgray_Init(Tcl_Interp *);
00022
00023
00024 TCL_DECLARE_MUTEX(threadMutex)
00025
00026 struct ThreadEvent {
00027 Tcl_Event event;
00028 char *script;
00029 Tcl_Interp *interp;
00030
00031 struct ThreadEventResult *resultPtr;
00032
00033
00034 };
00035
00036 struct ThreadEventResult {
00037 Tcl_Condition done;
00038 int code;
00039 char *result;
00040 char *errorInfo;
00041 char *errorCode;
00042 Tcl_ThreadId srcThreadId;
00043 Tcl_ThreadId dstThreadId;
00044 struct ThreadEvent *eventPtr;
00045 struct ThreadEventResult *nextPtr;
00046 struct ThreadEventResult *prevPtr;
00047
00048 };
00049
00050 static void
00051 ThreadFreeProc(ClientData clientData)
00052 {
00053 if (clientData) {
00054 ckfree((char *) clientData);
00055 }
00056 }
00057
00058 static int ThreadEventProc(
00059 Tcl_Event *evPtr,
00060 int mask)
00061 {
00062 ThreadEvent *threadEventPtr = (ThreadEvent *)evPtr;
00063 ThreadEventResult *resultPtr = threadEventPtr->resultPtr;
00064 Tcl_Interp *interp = threadEventPtr->interp;
00065 int code;
00066 const char *result, *errorCode, *errorInfo;
00067
00068 if (interp == NULL) {
00069 code = TCL_ERROR;
00070 result = "no target interp!";
00071 errorCode = "THREAD";
00072 errorInfo = "";
00073 } else {
00074 Tcl_Preserve((ClientData) interp);
00075 Tcl_ResetResult(interp);
00076 Tcl_CreateThreadExitHandler(ThreadFreeProc,
00077 (ClientData) threadEventPtr->script);
00078 code = Tcl_GlobalEval(interp, threadEventPtr->script);
00079 Tcl_DeleteThreadExitHandler(ThreadFreeProc,
00080 (ClientData) threadEventPtr->script);
00081 if (code != TCL_OK) {
00082 errorCode = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY);
00083 errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
00084 } else {
00085 errorCode = errorInfo = NULL;
00086 }
00087 result = Tcl_GetStringResult(interp);
00088 }
00089 ckfree(threadEventPtr->script);
00090 if (interp != NULL) {
00091 Tcl_Release((ClientData) interp);
00092 }
00093 return 1;
00094 }
00095
00096
00097 int tcl_thread_send(Tcl_ThreadId id, Tcl_Interp* interp, const char *script)
00098 {
00099 ThreadEvent *threadEventPtr;
00100 ThreadEventResult *resultPtr;
00101 int found, code;
00102 Tcl_ThreadId threadId = (Tcl_ThreadId) id;
00103
00104 Tcl_MutexLock(&threadMutex);
00105
00106
00107
00108
00109 threadEventPtr = (ThreadEvent *) ckalloc(sizeof(ThreadEvent));
00110 threadEventPtr->script = ckalloc(strlen(script) + 1);
00111 threadEventPtr->interp = interp;
00112 strcpy(threadEventPtr->script, script);
00113 resultPtr = threadEventPtr->resultPtr = NULL;
00114
00115
00116
00117
00118
00119 threadEventPtr->event.proc = ThreadEventProc;
00120 Tcl_ThreadQueueEvent(threadId, (Tcl_Event *)threadEventPtr,
00121 TCL_QUEUE_TAIL);
00122 Tcl_ThreadAlert(threadId);
00123
00124
00125 Tcl_MutexUnlock(&threadMutex);
00126 return TCL_OK;
00127 }
00128
00129
00130
00131 extern "C" {
00132 static int AppInit(Tcl_Interp *interp);
00133 static Tcl_ThreadCreateType slaveinterpreter (ClientData dummy);
00134 }
00135
00136
00137
00138 static Tcl_ThreadId displaythreadId=0;
00139 static Tcl_Interp *interp=NULL;
00140 static int argc=0;
00141 static const char ** argv=NULL;
00142 static Tcl_Condition startup_condition=NULL;
00143 static volatile bool started=false;
00144
00145 int AppInit(Tcl_Interp *interp_) {
00146 interp = interp_;
00147
00148 Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
00149 if(Tcl_Init(interp) == TCL_ERROR) return TCL_ERROR;
00150 if(Tk_Init(interp) == TCL_ERROR) return TCL_ERROR;
00151 if (Xgray_Init(interp)==TCL_ERROR) return TCL_ERROR;
00152
00153
00154 cout<<"T2"<<endl<<flush;
00155 Tcl_MutexLock(&threadMutex);
00156
00157
00158
00159 started=true;
00160 Tcl_ConditionNotify(&startup_condition);
00161 Tcl_MutexUnlock(&threadMutex);
00162
00163 return TCL_OK;
00164 }
00165
00166 Tcl_ThreadCreateType slaveinterpreter (ClientData dummy) {
00167 Tcl_Channel outChannel;
00168
00169 Tcl_Interp *interp = Tcl_CreateInterp();
00170
00171
00172
00173
00174
00175 if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
00176 abort();
00177 }
00178
00179
00180 #ifdef MAC_OSX_TK
00181 {
00182 TkMacOSXDefaultStartupScript();
00183 }
00184 #endif
00185
00186
00187
00188
00189
00190 Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
00191
00192
00193
00194
00195
00196 if (AppInit(interp) != TCL_OK) {
00197 return 0;
00198 }
00199
00200
00201
00202
00203
00204
00205 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
00206 if (outChannel) {
00207 Tcl_Flush(outChannel);
00208 }
00209
00210 Tcl_ResetResult(interp);
00211
00212
00213
00214
00215
00216
00217 Tk_MainLoop();
00218 Tcl_DeleteInterp(interp);
00219
00220
00221 return 0;
00222 }
00223
00224
00225 Tclthread::Tclthread(int argc_, const char **argv_)
00226 {
00227 int result;
00228 argc=argc_;
00229 argv=argv_;
00230
00231
00232 Tcl_FindExecutable(argv[0]);
00233 Tcl_MutexLock(&threadMutex);
00234 result=Tcl_CreateThread(&displaythreadId, slaveinterpreter, (ClientData)0, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
00235
00236
00237
00238 int nr=0;
00239 while (!started) {
00240 Tcl_ConditionWait(&startup_condition, &threadMutex, NULL);
00241 nr++;
00242 }
00243
00244 operator() (
00245 #include "inlinedisplay.c++"
00246 );
00247
00248 Tcl_MutexUnlock(&threadMutex);
00249 cout<<"T1 "<<nr<<endl<<flush;
00250 }
00251
00252
00253 void Tclthread::operator () (const char *script) {
00254 tcl_thread_send(displaythreadId, interp, script);
00255
00256 }
00257
00258