// MainThread code can call everything, AllowEveryCaller code can be called by // everything, SingleThread can call SingleThread/Serializable/Concurrent, and Serializable/ // Concurrent can call Serializable/Concurrent. static bool IsValidCall(ThreadModel caller, ThreadModel target) { // MainThread code can call everything if (caller.Is(ThreadModel.MainThread)) { return(true); } // AllowEveryCaller code can be called by everything else if (target.AllowsEveryCaller()) { return(true); } // SingleThread can call SingleThread/Serializable/Concurrent else if (caller.Is(ThreadModel.SingleThread) && (target.Is(ThreadModel.SingleThread) || target.Is(ThreadModel.Serializable) || target.Is(ThreadModel.Concurrent))) { return(true); } // Serializable/Concurrent can call Serializable/Concurrent else if ((caller.Is(ThreadModel.Serializable) || caller.Is(ThreadModel.Concurrent)) && (target.Is(ThreadModel.Serializable) || target.Is(ThreadModel.Concurrent))) { return(true); } return(false); }
// MainThread code can call everything, AllowEveryCaller code can be called by // everything, SingleThread can call SingleThread/Serializable/Concurrent, and Serializable/ // Concurrent can call Serializable/Concurrent. static bool IsValidCall (ThreadModel caller, ThreadModel target) { // MainThread code can call everything if (caller.Is (ThreadModel.MainThread)) return true; // AllowEveryCaller code can be called by everything else if (target.AllowsEveryCaller ()) return true; // SingleThread can call SingleThread/Serializable/Concurrent else if (caller.Is (ThreadModel.SingleThread) && (target.Is (ThreadModel.SingleThread) || target.Is (ThreadModel.Serializable) || target.Is (ThreadModel.Concurrent))) return true; // Serializable/Concurrent can call Serializable/Concurrent else if ((caller.Is (ThreadModel.Serializable) || caller.Is (ThreadModel.Concurrent)) && (target.Is (ThreadModel.Serializable) || target.Is (ThreadModel.Concurrent))) return true; return false; }
public RuleResult CheckMethod(MethodDefinition method) { if (ThreadRocks.ThreadedNamespace(method.DeclaringType.Namespace)) { return(RuleResult.DoesNotApply); } Log.WriteLine(this); Log.WriteLine(this, "---------------------------------------"); Log.WriteLine(this, method); string name = method.Name; IList <ParameterDefinition> pdc = method.HasParameters ? method.Parameters : null; // Finalizers need to be single threaded. ThreadModel model = method.ThreadingModel(); if (method.IsFinalizer()) { if ((model & ~ThreadModel.AllowEveryCaller) != ThreadModel.SingleThread) { string mesg = "Finalizers should be decorated with [ThreadModel (ThreadModel.SingleThreaded)]."; ReportDefect(method, Severity.High, Confidence.High, mesg); } } // Make sure all of the thread entry points are properly decorated and // that all calls are legit. if (method.HasBody && opcodes_mask.Intersect(OpCodeEngine.GetBitmask(method))) { CheckMethodBody(method); } // A delegate used with a threaded event must use the same threading model // as the event. if (method.IsAddOn) { ParameterDefinition p = pdc [0]; TypeDefinition delegateType = p.ParameterType.Resolve(); if (delegateType != null && !ThreadRocks.ThreadedNamespace(delegateType.Namespace)) { ThreadModel delegateModel = delegateType.ThreadingModel(); if (model != delegateModel && !delegateModel.AllowsEveryCaller()) { string mesg = String.Format(CultureInfo.InvariantCulture, "{0} event must match {1} delegate.", model, delegateModel); ReportDefect(method, Severity.High, Confidence.High, mesg); } } } // An override of a base method or an implementation of an interface method // must use the same threading model as the original method. if (method.IsVirtual) { IEnumerable <TypeDefinition> superTypes = method.DeclaringType.AllSuperTypes(); bool new_slot = method.IsNewSlot; superTypes = from s in superTypes where (s.IsInterface == new_slot) select s; string [] parameters = pdc != null ? (from p in pdc.Cast <ParameterDefinition> () select p.ParameterType.GetFullName()).ToArray() : null; string return_type_name = method.ReturnType.GetFullName(); foreach (TypeDefinition type in superTypes) { MethodDefinition superMethod = type.GetMethod(name, return_type_name, parameters); if (superMethod != null && !ThreadRocks.ThreadedNamespace(superMethod.DeclaringType.Namespace)) { ThreadModel superModel = superMethod.ThreadingModel(); if (model != superModel) { string mesg = String.Format(CultureInfo.InvariantCulture, "{0} {1} must match {2} {3} method.", model, name, superModel, new_slot ? "interface" : "base"); ReportDefect(method, Severity.High, Confidence.High, mesg); } } } } // Serializable cannot be applied to static methods, but can be applied to // operators because they're just sugar for normal calls. if (method.IsStatic && model.Is(ThreadModel.Serializable) && !name.StartsWith("op_", StringComparison.Ordinal)) { string mesg = "Static members cannot be decorated with Serializable."; ReportDefect(method, Severity.High, Confidence.High, mesg); } return(Runner.CurrentRuleResult); }