예제 #1
0
 //Creates a compute list with reference of indirect info to this list.
 public ComputeList Clone()
 {
     ComputeList computeList = new ComputeList();
     return computeList;
 }
예제 #2
0
        public void Optimize()
        {
            if (m_calculator == null)
            {
                System.Diagnostics.Debug.WriteLine("OptimizeManager.Optimize: m_calculator == null");
                return;
            }

            //Contains dependices linked to expressions in calculator.
            Hashtable optimizables = new Hashtable();
            // If FindDependices returns false, the key is marked as not-optimizable.
            Hashtable notOptimizables = new Hashtable();
            //(28.07.2006 11:58)
            //Reduce unecessary calls to the property.
            m_functions = m_calculator.Functions;

            #region "Finding Dependicies"
            //Find all dependicies.
            Expression[] expressions = m_calculator.GetExpressions();
            foreach (Expression exp in expressions)
            {
                ArrayList deps = new ArrayList();
                // Get all the dependices of expression.
                // Use the variable name of expression key as relative.
                if (!FindDependices(exp.Key, exp.Tree, deps, exp.Key.Substring(0, exp.Key.IndexOf(Calculator.PROPERTY_CHAR)), null, false))
                {
                    // Mark as not optimizable.
                    if (!notOptimizables.Contains(exp.Key))
                    {
                        notOptimizables.Add(exp.Key, exp.Key);
                    }
                }
                else
                {
                    // Check for direct property dependence.
                    object expObject = exp.Variable;
                    if (expObject is IOptimizable)
                    {
                        IOptimizable expOpt = (IOptimizable)expObject;
                        PropertyDependicy[] propDeps = expOpt.PropertyDependices;
                        if (propDeps != null)
                        {
                            foreach (PropertyDependicy propDep in propDeps)
                            {
                                if (propDep.ParentProperty == exp.PropName)
                                {
                                    deps.Add(exp.Variable.Name + Calculator.PROPERTY_CHAR + propDep.ChildProperty);
                                }
                            }
                        }
                    }
                    if (deps.Count != 0)
                    {
                        DependicyInfo dependicy = new DependicyInfo();
                        dependicy.Key = exp.Key;
                        //Analyse each dependicy.
                        string[] depsTable = new string[deps.Count];
                        bool optimizable = true;
                        for (int i = 0; i <= depsTable.Length - 1; i++)
                        {
                            string nodeValue = (string)deps[i];
                            if (!optimizables.Contains(nodeValue))
                            {
                                //Create dependicy info.
                                DependicyInfo depNode = new DependicyInfo();
                                depNode.Key = nodeValue;
                                //Detect type.
                                depNode.Type = DependicyType(nodeValue);
                                //See if the dependicy is not optimizable.
                                if (depNode.Type == DependicyInfo.DEPENDICY_TYPE_NOT_LEGAL)
                                {
                                    optimizable = false;
                                    break;
                                }
                                else if (depNode.Type == DependicyInfo.DEPENDICY_TYPE_VARIABLE)
                                {
                                    //See if variable inherits from IOptimizable.
                                    object obj = m_calculator.Variable(depNode.Key);
                                    if (!(obj is IOptimizable))
                                    {
                                        optimizable = false;
                                        break;
                                    }
                                }
                                else if (depNode.Type == DependicyInfo.DEPENDICY_TYPE_PROPERTY)
                                {
                                    //See if variable inherits from IOptimizable.
                                    int dotIndex = depNode.Key.IndexOf(Calculator.PROPERTY_CHAR);
                                    string varName = depNode.Key.Substring(0, dotIndex);
                                    object obj = m_calculator.Variable(varName);
                                    if (!(obj is IOptimizable))
                                    {
                                        optimizable = false;
                                        break;
                                    }
                                }
                                //Add dependicy as optimizable.
                                optimizables.Add(nodeValue, depNode);
                                depsTable[i] = depNode.Key;
                            }
                            else
                            {
                                //Optimizable already exists.
                                depsTable[i] = nodeValue;
                            }
                        }
                        if (!optimizable)
                        {
                            notOptimizables.Add(exp.Key, exp.Key);
                        }
                        else
                        {
                            //Add as optimizable.
                            dependicy.Type = DependicyInfo.DEPENDICY_TYPE_EXPRESSION;
                            dependicy.Deps = depsTable;
                            //Remove temporary optimizable.
                            if (optimizables.Contains(exp.Key))
                            {
                                optimizables.Remove(exp.Key);
                            }
                            optimizables.Add(exp.Key, dependicy);
                        }
                    }
                    else
                    {
                        // Expression depends on no other.
                        DependicyInfo dep = new DependicyInfo();
                        dep.Deps = new string[] {};
                        dep.Type = DependicyInfo.DEPENDICY_TYPE_EXPRESSION;
                        dep.Key = exp.Key;
                        // Remove temporary optimizable.
                        if (optimizables.Contains(exp.Key))
                        {
                            optimizables.Remove(exp.Key);
                        }
                        optimizables.Add(dep.Key, dep);
                    }
                }
            }
            #endregion

            // Remove all not-optimizables from optimizables.
            foreach (string key in notOptimizables.Values)
            {
                if (optimizables.Contains(key))
                {
                    optimizables.Remove(key);
                }
            }
            //Remove all optimalizables that depends on not-optimalizables.
            Hashtable lastNotOptimizables = notOptimizables;
            //Continue to remove optimizables that depends on not-optimizables
            //until table of optimizables is clean.
            while (lastNotOptimizables.Count != 0)
            {
                //Find all optimizables that depends on newly removed optimizables.
                Hashtable tempNotOptimizables = new Hashtable();
                foreach (DependicyInfo dep in optimizables.Values)
                {
                    if (dep.Type == DependicyInfo.DEPENDICY_TYPE_EXPRESSION)
                    {
                        foreach (string depName in dep.Deps)
                        {
                            if (lastNotOptimizables[depName] != null)
                            {
                                tempNotOptimizables.Add(dep.Key, dep.Key);
                                //Remove child property dependices of dependicy.
                                int propIndex = depName.IndexOf(Calculator.PROPERTY_CHAR);
                                string variableName = depName.Substring(0, propIndex);
                                object obj = m_calculator.Variable(variableName);
                                if (obj is IOptimizable)
                                {
                                    IOptimizable opt = (IOptimizable)obj;
                                    if (opt.PropertyDependices != null)
                                    {
                                        foreach (PropertyDependicy propertyDep in opt.PropertyDependices)
                                        {
                                            if (propertyDep.ParentProperty == depName.Substring(propIndex + 1))
                                            {
                                                string childKey = variableName + Calculator.PROPERTY_CHAR + propertyDep.ChildProperty;
                                                if (!tempNotOptimizables.Contains(childKey))
                                                {
                                                    tempNotOptimizables.Add(childKey, childKey);
                                                }
                                            }
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
                //Remove from optimizables in end to not get enumeration exception.
                foreach (string expName in tempNotOptimizables.Values)
                {
                    optimizables.Remove(expName);
                    if (!notOptimizables.Contains(expName))
                        notOptimizables.Add(expName, expName);
                }
                lastNotOptimizables = tempNotOptimizables;
            }
            //Remove recursive.
            foreach (DependicyInfo opt in optimizables.Values)
            {
                SortedList history = new SortedList();
                Hashtable processed = new Hashtable(optimizables.Count);
                RemoveRecursive(opt, optimizables, notOptimizables, history, processed);
            }
            //Remove all not-optimizables from optimizables.
            foreach (string key in notOptimizables.Values)
            {
                if (optimizables.Contains(key))
                {
                    optimizables.Remove(key);
                }
            }

            IVariable[] variables = m_calculator.GetVariables();
            foreach (IVariable variable in variables)
            {
                if (variable is IOptimizable)
                {
                    IOptimizable obj = (IOptimizable)variable;
                    obj.PropertyChanged -= new PropertyChangedEventHandler(PropertyChanged);
                }
            }

            #region "Dependicy Reversing"
            //Build optimize graphs.
            //Reverse the dependices.
            Hashtable eventGraph = new Hashtable();
            Hashtable objectMap = new Hashtable();
            //(29.11.2006 12:15)
            Hashtable processedEvents = new Hashtable();
            foreach (DependicyInfo opt in optimizables.Values)
            {
                if (opt.Deps != null)
                {
                    AddToEventList(opt, opt.Deps, optimizables, eventGraph, objectMap, processedEvents);
                    //An expression should update it self if it differ from it's previous value.
                    if (opt.Type == DependicyInfo.DEPENDICY_TYPE_EXPRESSION)
                    {
                        string varName = opt.Key.Substring(0, opt.Key.IndexOf(Calculator.PROPERTY_CHAR));
                        object obj = m_calculator.Variable(varName);
                        if (obj is IOptimizable)
                        {
                            IOptimizable optObj = (IOptimizable)obj;
                            if (!eventGraph.Contains(opt.Key))
                            {
                                if (!objectMap.Contains(optObj))
                                {
                                    optObj.PropertyChanged += new PropertyChangedEventHandler(PropertyChanged);
                                    objectMap.Add(optObj, varName);
                                }
                                eventGraph.Add(opt.Key, new ArrayList());
                            }
                            //Add to event list.
                            ArrayList events = (ArrayList)eventGraph[opt.Key];
                            if (!events.Contains(opt.Key))
                            {
                                events.Add(m_calculator.GetExpressionObject(opt.Key));
                            }
                        }
                    }
                }
            }
            #endregion

            m_computeList = new ComputeList();
            m_eventGraph = eventGraph;

            #region "Single Object Reference"
            //Single expressions using object references, are not necessary to compute.
            ArrayList objectReferences = new ArrayList();
            foreach (string key in notOptimizables.Values)
            {
                string exp = m_calculator.GetExpression(key);
                if (exp != null && System.Text.RegularExpressions.Regex.IsMatch(exp.Trim(), Calculator.NAME_REGEX))
                {
                    objectReferences.Add(key);
                }
            }
            foreach (string key in objectReferences)
            {
                notOptimizables.Remove(key);
            }
            //Remember the object references for later use.
            m_objectReferences = objectReferences;
            //Create list of not optimizable expressions.
            ArrayList expressionList = new ArrayList();
            foreach (string key in notOptimizables.Values)
            {
                Expression exp = m_calculator.GetExpressionObject(key);
                if (exp != null)
                {
                    expressionList.Add(exp);
                }
            }
            #endregion

            m_notOptimizables = new Expression[expressionList.Count];
            expressionList.CopyTo(m_notOptimizables);
        }