/////////////////////////////////////////////////////////////////////// #region Private Constructors private Event( object syncRoot, /* in: OPTIONAL */ Delegate @delegate, /* in: OPTIONAL */ EventType type, /* in */ EventFlags flags, /* in */ EventPriority priority, /* in */ Interpreter interpreter, /* in: OPTIONAL */ string name, /* in: OPTIONAL */ DateTime dateTime, /* in */ EventCallback callback, /* in: OPTIONAL */ IClientData clientData /* in: OPTIONAL */ ) { this.syncRoot = syncRoot; this.@delegate = @delegate; this.type = type; this.flags = flags; this.priority = priority; this.interpreter = interpreter; this.name = name; this.dateTime = dateTime; this.callback = callback; this.clientData = clientData; // // NOTE: Setup inter-thread communication event. // doneEventName = FormatOps.EventName(interpreter, typeof(Event).Name, name, GlobalState.NextEventId( interpreter)); doneEvent = ThreadOps.CreateEvent(doneEventName); // // NOTE: Setup the initial result state. // ResetResultData(); // // NOTE: Keep track of how many event objects are created // within this AppDomain. // Interlocked.Increment(ref createCount); }
/////////////////////////////////////////////////////////////////////// private /* protected virtual */ void Dispose( bool disposing ) /* throw */ { if (!disposed) { if (disposing) { //////////////////////////////////// // dispose managed resources here... //////////////////////////////////// // // NOTE: Dispose of the "done" inter-thread communication // event. // /* NO RESULT */ ThreadOps.CloseEvent(ref doneEvent); // // NOTE: Keep track of how many event objects are disposed // within this AppDomain. This is applicable only // when the object is explicitly disposed, not merely // finalized. // Interlocked.Increment(ref disposeCount); } #if DEBUG else { DebugOps.MaybeBreak(); } #endif ////////////////////////////////////// // release unmanaged resources here... ////////////////////////////////////// disposed = true; } }
/////////////////////////////////////////////////////////////////////// private bool WaitOnEventHandle( int milliseconds, ref Result error ) { EventWaitHandle doneEvent = null; try { doneEvent = ThreadOps.OpenEvent(doneEventName); if (doneEvent != null) { if (ThreadOps.WaitEvent( doneEvent, milliseconds)) { return(true); } else { error = String.Format( "timed wait of {0} milliseconds for event {1} failed", milliseconds, FormatOps.WrapOrNull(doneEventName)); } } else { error = String.Format( "cannot open event {0} in order to wait", FormatOps.WrapOrNull(doneEventName)); } } finally { /* NO RESULT */ ThreadOps.CloseEvent(ref doneEvent); } return(false); }
/////////////////////////////////////////////////////////////////////// private bool SetEventHandle( ref Result error ) { EventWaitHandle doneEvent = null; try { doneEvent = ThreadOps.OpenEvent(doneEventName); if (doneEvent != null) { if (ThreadOps.SetEvent(doneEvent)) { return(true); } else { error = String.Format( "set for event {0} failed", FormatOps.WrapOrNull(doneEventName)); } } else { error = String.Format( "cannot open event {0} in order to set", FormatOps.WrapOrNull(doneEventName)); } } finally { /* NO RESULT */ ThreadOps.CloseEvent(ref doneEvent); } return(false); }
/////////////////////////////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { // // NOTE: Grab the variable and event wait flags from the // interpreter and use them as the defaults for the // associated options. // EventWaitFlags eventWaitFlags = interpreter.EventWaitFlags; VariableFlags variableFlags = interpreter.EventVariableFlags; OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.MustHaveObjectValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-handle", null), new Option(typeof(EventWaitFlags), OptionFlags.MustHaveEnumValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-eventwaitflags", new Variant(eventWaitFlags)), new Option(typeof(VariableFlags), OptionFlags.MustHaveEnumValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-variableflags", new Variant(variableFlags)), new Option(null, OptionFlags.MustHaveIntegerValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-limit", null), new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-force", null), new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-nocomplain", null), new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-leaveresult", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; code = interpreter.GetOptions( options, arguments, 0, 1, Index.Invalid, false, ref argumentIndex, ref result); if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) == arguments.Count)) { Variant value = null; EventWaitHandle @event = null; if (options.IsPresent("-handle", ref value)) { IObject @object = (IObject)value.Value; if ((@object.Value == null) || (@object.Value is EventWaitHandle)) { @event = (EventWaitHandle)@object.Value; } else { result = "option value has invalid EventWaitHandle"; code = ReturnCode.Error; } } if (code == ReturnCode.Ok) { int limit = 0; if (options.IsPresent("-limit", ref value)) { limit = (int)value.Value; } if (options.IsPresent("-eventwaitflags", ref value)) { eventWaitFlags = (EventWaitFlags)value.Value; } if (options.IsPresent("-variableflags", ref value)) { variableFlags = (VariableFlags)value.Value; } bool force = false; if (options.IsPresent("-force")) { force = true; } bool noComplain = false; if (options.IsPresent("-nocomplain")) { noComplain = true; } bool leaveResult = false; if (options.IsPresent("-leaveresult")) { leaveResult = true; } // // NOTE: Typically, we do not want to enter a wait state if // there are no events queued because there would be // no possible way to ever (gracefully) exit the wait; // however, there are exceptions to this. // if (force || interpreter.ShouldWaitVariable()) { // // HACK: The call to ThreadOps.IsStaThread here is made // under the assumption that no user-interface // thread can exist without also being an STA // thread. This may eventually prove to be false; // however, currently WinForms, WPF, et al require // this (i.e. an STA thread). // if (!FlagOps.HasFlags( eventWaitFlags, EventWaitFlags.UserInterface, true) && ThreadOps.IsStaThread()) { eventWaitFlags |= EventWaitFlags.UserInterface; } code = interpreter.WaitVariable(eventWaitFlags, variableFlags, arguments[argumentIndex], limit, @event, ref result); if ((code != ReturnCode.Ok) && noComplain) { code = ReturnCode.Ok; } if ((code == ReturnCode.Ok) && !leaveResult) { Engine.ResetResult(interpreter, ref result); } } else { result = String.Format( "can't wait for variable \"{0}\": would wait forever", arguments[1]); code = ReturnCode.Error; } } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption( options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"vwait ?options? varName\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"vwait ?options? varName\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }