static void _p5_core_null_active_event(ApplicationContext context, ActiveEventArgs e) { // Acquire read lock, since we're consuming object shared amongst more than one thread (_events). // This lock must be released before event is invoked, and is only here since we're consuming Node lambda = null; _lock.EnterReadLock(); try { // Checking if there's an event with given name in dynamically created events. // To avoid creating a lock on every single event invocation in system, we create a "double check" // here, first checking for existance of key, then to create lock, for then to re-check again, which // should significantly improve performance of event invocations in the system if (_events.ContainsKey(e.Name)) { // Keep a reference to all lambda objects in current event, such that we can later delete them lambda = _events [e.Name].Clone(); } } finally { // Making sure we release lock in a finally, such that we can never exit method, without releasing our lock. _lock.ExitReadLock(); } // Raising Active Event, if it exists. if (lambda != null) { XUtil.EvaluateLambda(context, lambda, e.Args); } }
void null_handler(ApplicationContext context, ActiveEventArgs e) { // Checking if we have a lambda event with the specified name. var enumerable = Manager.WidgetLambdaEventStorage [e.Name]; if (enumerable != null) { // Used to store return values to return to caller after all invocations have been evaluated. var retVal = new Node(); // Used to hold original arguments. Node argsClone = null; // Iterating through each lambda event, invoking it with the specified arguments. // Notice the ToList invocation, which is necessary in case the lambda creates a new lambda event with the same name, possibly // on a different widget, which would kill our IEnumerable object unless we made sure it was made into a list first. var list = enumerable.ToList(); foreach (var idxLambda in list) { // In case this is a second invocation, to the same lambda event, for a different widget, we reset the original args, to // make sure each invocation gets the same set of arguments. // If it is not a second invocation, we check to see if we have more than one invocation, and if so, we clone the original args, // such that we can keep them around to our next invocation. if (argsClone != null) { e.Args.Value = argsClone.Value; e.Args.AddRange(argsClone.Clone().Children); } else if (list.Count > 1) { argsClone = e.Args.Clone(); } // Creating a clone of currently evaluated lambda object. var clone = idxLambda.Clone(); // Evaluating lambda event. XUtil.EvaluateLambda(context, clone, e.Args); // Moving returned nodes from invocation into retVal. retVal.AddRange(e.Args.Children); // Then making sure we return the value returned by invocation, if any. // Notice, only the last lambda event handler, if there are multiple lambda events, will be able to return anything as value. retVal.Value = e.Args.Value; } // Returning all return values, from all invocations to caller. e.Args.Clear().AddRange(retVal.Children); e.Args.Value = retVal.Value; } }