public IdleHandler( Notifier n ) { notifier = (Notifier)n; isCancelled = false; lock ( notifier ) { notifier.idleList.Add( this ); generation = notifier.idleGeneration; if ( System.Threading.Thread.CurrentThread != notifier.primaryThread ) { System.Threading.Monitor.PulseAll( notifier ); } } }
public TimerHandler( Notifier n, int milliseconds ) { int i; atTime = ( System.DateTime.Now.Ticks - 621355968000000000 ) / 10000 + milliseconds; notifier = (Notifier)n; isCancelled = false; /* * Add the event to the queue in the correct position (ordered by * event firing time). * * NOTE: it's very important that if two timer handlers have the * same atTime, the newer timer handler always goes after the * older handler in the list. See comments in * Notifier.TimerEvent.processEvent() for details. */ lock ( notifier ) { generation = notifier.timerGeneration; for ( i = 0; i < notifier.timerList.Count; i++ ) { TimerHandler q = (TimerHandler)notifier.timerList[i]; if ( atTime < q.atTime ) { break; } } notifier.timerList.Insert( i, this ); if ( System.Threading.Thread.CurrentThread != notifier.primaryThread ) { System.Threading.Monitor.PulseAll( notifier ); } } }
public static Notifier getNotifierForThread(System.Threading.Thread thread) // The thread that owns this Notifier. { lock (typeof(tcl.lang.Notifier)) { Notifier notifier = (Notifier) notifierTable[thread]; if (notifier == null) { notifier = new Notifier(thread); SupportClass.PutElement(notifierTable, thread, notifier); } return notifier; } }
internal BgError( BgErrorMgr enclosingInstance, Notifier n ) : base( n ) { InitBlock( enclosingInstance ); }
internal TimerInfo( AfterCmd enclosingInstance, Notifier n, int milliseconds ) : base(n, milliseconds) { InitBlock( enclosingInstance ); }
internal IdleInfo( AfterCmd enclosingInstance, Notifier n ) : base(n) { InitBlock( enclosingInstance ); }
public override void eventuallyDispose() { if ( deleted ) { return; } deleted = true; if ( nestLevel > 0 ) { //-- TODO -- Determine why this is an error throw new TclRuntimeError("dispose() called with active evals"); } // Remove our association with the notifer (if we had one). if ( notifier != null ) { notifier.release(); notifier = null; } // Dismantle everything in the global namespace except for the // "errorInfo" and "errorCode" variables. These might be needed // later on if errors occur while deleting commands. We are careful // to destroy and recreate the "errorInfo" and "errorCode" // variables, in case they had any traces on them. // // Dismantle the namespace here, before we clear the assocData. If any // background errors occur here, they will be deleted below. // FIXME : check impl of TclTeardownNamespace NamespaceCmd.teardownNamespace( globalNs ); // Delete all variables. TclObject errorInfoObj = null, errorCodeObj = null; try { errorInfoObj = getVar( "errorInfo", null, TCL.VarFlag.GLOBAL_ONLY ); } catch ( TclException e ) { // Do nothing when var does not exist. } if ( errorInfoObj != null ) { errorInfoObj.preserve(); } try { errorCodeObj = getVar( "errorCode", null, TCL.VarFlag.GLOBAL_ONLY ); } catch ( TclException e ) { // Do nothing when var does not exist. } if ( errorCodeObj != null ) { errorCodeObj.preserve(); } frame = null; varFrame = null; try { if ( errorInfoObj != null ) { setVar( "errorInfo", null, errorInfoObj, TCL.VarFlag.GLOBAL_ONLY ); errorInfoObj.release(); } if ( errorCodeObj != null ) { setVar( "errorCode", null, errorCodeObj, TCL.VarFlag.GLOBAL_ONLY ); errorCodeObj.release(); } } catch ( TclException e ) { // Ignore it -- same behavior as Tcl 8.0. } // Tear down the math function table. expr = null; // Remove all the assoc data tied to this interp and invoke // deletion callbacks; note that a callback can create new // callbacks, so we iterate. // ATK The java code was somethink strong if ( assocData != null ) { foreach ( AssocData data in assocData.Values ) { data.disposeAssocData( this ); } assocData.Clear(); } // Close any remaining channels for ( IDictionaryEnumerator e = interpChanTable.GetEnumerator(); e.MoveNext(); ) { Object key = e.Key; Channel chan = (Channel)e.Value; try { chan.close(); } catch ( IOException ex ) { // Ignore any IO errors } } // Finish deleting the global namespace. // FIXME : check impl of Tcl_DeleteNamespace NamespaceCmd.deleteNamespace( globalNs ); globalNs = null; // Free up the result *after* deleting variables, since variable // deletion could have transferred ownership of the result string // to Tcl. frame = null; varFrame = null; resolvers = null; resetResult(); }
public Interp() { InitBlock(); //freeProc = null; errorLine = 0; // An empty result is used pretty often. We will use a shared // TclObject instance to represent the empty result so that we // don't need to create a new TclObject instance every time the // interpreter result is set to empty. m_nullResult = TclString.newInstance( "" ); m_nullResult.preserve(); // Increment refCount to 1 m_nullResult.preserve(); // Increment refCount to 2 (shared) m_result = TclString.newInstance( "" ); //m_nullResult; // correcponds to iPtr->objResultPtr m_result.preserve(); expr = new Expression(); nestLevel = 0; maxNestingDepth = 1000; frame = null; varFrame = null; returnCode = TCL.CompletionCode.OK; errorInfo = null; errorCode = null; packageTable = new Hashtable(); packageUnknown = null; cmdCount = 0; termOffset = 0; resolvers = null; evalFlags = 0; scriptFile = null; flags = 0; isSafe = false; assocData = null; globalNs = null; // force creation of global ns below globalNs = NamespaceCmd.createNamespace( this, null, null ); if ( globalNs == null ) { throw new TclRuntimeError( "Interp(): can't create global namespace" ); } // Init things that are specific to the Jacl implementation workingDir = new FileInfo( System.Environment.CurrentDirectory ); noEval = 0; notifier = Notifier.getNotifierForThread( System.Threading.Thread.CurrentThread ); notifier.preserve(); randSeedInit = false; deleted = false; errInProgress = false; errAlreadyLogged = false; errCodeSet = false; dbg = initDebugInfo(); slaveTable = new Hashtable(); targetTable = new Hashtable(); aliasTable = new Hashtable(); // init parser variables Parser.init( this ); TclParse.init( this ); // Initialize the Global (static) channel table and the local // interp channel table. interpChanTable = TclIO.getInterpChanTable( this ); // Sets up the variable trace for tcl_precision. Util.setupPrecisionTrace( this ); // Create the built-in commands. createCommands(); try { // Set up tcl_platform, tcl_version, tcl_library and other // global variables. setVar( "tcl_platform", "platform", "windows", TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "byteOrder", "bigEndian", TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "os", Environment.OSVersion.Platform.ToString(), TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "osVersion", Environment.OSVersion.Version.ToString(), TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "machine", Util.tryGetSystemProperty( "os.arch", "?" ), TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_version", TCL_VERSION, TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_patchLevel", TCL_PATCH_LEVEL, TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_library", "resource:/tcl/lang/library", TCL.VarFlag.GLOBAL_ONLY ); if ( Util.Windows ) { setVar( "tcl_platform", "host_platform", "windows", TCL.VarFlag.GLOBAL_ONLY ); } else if ( Util.Mac ) { setVar( "tcl_platform", "host_platform", "macintosh", TCL.VarFlag.GLOBAL_ONLY ); } else { setVar( "tcl_platform", "host_platform", "unix", TCL.VarFlag.GLOBAL_ONLY ); } // Create the env array an populated it with proper // values. Env.initialize( this ); // Register Tcl's version number. Note: This MUST be // done before the call to evalResource, otherwise // calls to "package require tcl" will fail. pkgProvide( "Tcl", TCL_VERSION ); // Source the init.tcl script to initialize auto-loading. evalResource( "/tcl/lang/library/init.tcl" ); } catch ( TclException e ) { System.Diagnostics.Debug.WriteLine( getResult().ToString() ); SupportClass.WriteStackTrace( e, Console.Error ); throw new TclRuntimeError( "unexpected TclException: " + e.Message, e ); } }
internal IdleInfo(AfterCmd enclosingInstance, Notifier n) : base(n) { InitBlock(enclosingInstance); }
public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv) { int i; Notifier notifier = (Notifier)interp.getNotifier(); Object info; if (assocData == null) { /* * Create the "after" information associated for this * interpreter, if it doesn't already exist. */ assocData = (AfterAssocData)interp.getAssocData("tclAfter"); if (assocData == null) { assocData = new AfterAssocData(this); interp.setAssocData("tclAfter", assocData); } } if (argv.Length < 2) { throw new TclNumArgsException(interp, 1, argv, "option ?arg arg ...?"); } /* * First lets see if the command was passed a number as the first argument. */ bool isNumber = false; int ms = 0; if (argv[1].InternalRep is TclInteger) { ms = TclInteger.get(interp, argv[1]); isNumber = true; } else { string s = argv[1].ToString(); if ((s.Length > 0) && (System.Char.IsDigit(s[0]))) { ms = TclInteger.get(interp, argv[1]); isNumber = true; } } if (isNumber) { if (ms < 0) { ms = 0; } if (argv.Length == 2) { /* * Sleep for at least the given milliseconds and return. */ long endTime = System.DateTime.Now.Ticks / 10000 + ms; while (true) { try { System.Threading.Thread.Sleep(ms); return(TCL.CompletionCode.RETURN); } catch (System.Threading.ThreadInterruptedException e) { /* * We got interrupted. Sleep again if we havn't slept * long enough yet. */ long sysTime = System.DateTime.Now.Ticks / 10000; if (sysTime >= endTime) { return(TCL.CompletionCode.RETURN); } ms = (int)(endTime - sysTime); continue; } } } TclObject cmd = getCmdObject(argv); cmd.preserve(); assocData.lastAfterId++; TimerInfo timerInfo = new TimerInfo(this, notifier, ms); timerInfo.interp = interp; timerInfo.command = cmd; timerInfo.id = assocData.lastAfterId; assocData.handlers.Add(timerInfo); interp.setResult("after#" + timerInfo.id); return(TCL.CompletionCode.RETURN); } /* * If it's not a number it must be a subcommand. */ int index; try { index = TclIndex.get(interp, argv[1], validOpts, "option", 0); } catch (TclException e) { throw new TclException(interp, "bad argument \"" + argv[1] + "\": must be cancel, idle, info, or a number"); } switch (index) { case OPT_CANCEL: if (argv.Length < 3) { throw new TclNumArgsException(interp, 2, argv, "id|command"); } TclObject arg = getCmdObject(argv); arg.preserve(); /* * Search the timer/idle handler by id or by command. */ info = null; for (i = 0; i < assocData.handlers.Count; i++) { Object obj = assocData.handlers[i]; if (obj is TimerInfo) { TclObject cmd = ((TimerInfo)obj).command; if ((cmd == arg) || cmd.ToString().Equals(arg.ToString())) { info = obj; break; } } else { TclObject cmd = ((IdleInfo)obj).command; if ((cmd == arg) || cmd.ToString().Equals(arg.ToString())) { info = obj; break; } } } if (info == null) { info = getAfterEvent(arg.ToString()); } arg.release(); /* * Cancel the handler. */ if (info != null) { if (info is TimerInfo) { ((TimerInfo)info).cancel(); ((TimerInfo)info).command.release(); } else { ((IdleInfo)info).cancel(); ((IdleInfo)info).command.release(); } SupportClass.VectorRemoveElement(assocData.handlers, info); } break; case OPT_IDLE: if (argv.Length < 3) { throw new TclNumArgsException(interp, 2, argv, "script script ..."); } TclObject cmd2 = getCmdObject(argv); cmd2.preserve(); assocData.lastAfterId++; IdleInfo idleInfo = new IdleInfo(this, notifier); idleInfo.interp = interp; idleInfo.command = cmd2; idleInfo.id = assocData.lastAfterId; assocData.handlers.Add(idleInfo); interp.setResult("after#" + idleInfo.id); break; case OPT_INFO: if (argv.Length == 2) { /* * No id is given. Return a list of current after id's. */ TclObject list = TclList.newInstance(); for (i = 0; i < assocData.handlers.Count; i++) { int id; Object obj = assocData.handlers[i]; if (obj is TimerInfo) { id = ((TimerInfo)obj).id; } else { id = ((IdleInfo)obj).id; } TclList.append(interp, list, TclString.newInstance("after#" + id)); } interp.resetResult(); interp.setResult(list); return(TCL.CompletionCode.RETURN); } if (argv.Length != 3) { throw new TclNumArgsException(interp, 2, argv, "?id?"); } /* * Return command and type of the given after id. */ info = getAfterEvent(argv[2].ToString()); if (info == null) { throw new TclException(interp, "event \"" + argv[2] + "\" doesn't exist"); } TclObject list2 = TclList.newInstance(); TclList.append(interp, list2, ((info is TimerInfo) ? ((TimerInfo)info).command : ((IdleInfo)info).command)); TclList.append(interp, list2, TclString.newInstance((info is TimerInfo) ? "timer" : "idle")); interp.resetResult(); interp.setResult(list2); break; } return(TCL.CompletionCode.RETURN); }
internal TimerInfo(AfterCmd enclosingInstance, Notifier n, int milliseconds) : base(n, milliseconds) { InitBlock(enclosingInstance); }
internal BgError(BgErrorMgr enclosingInstance, Notifier n) : base(n) { InitBlock(enclosingInstance); }