Example #1
0
        // 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;
		}
Example #3
0
        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);
        }