< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Runtime.ActionItem
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Runtime/ActionItem.cs
Line coverage
10%
Covered lines: 7
Uncovered lines: 61
Coverable lines: 68
Total lines: 317
Line coverage: 10.2%
Branch coverage
6%
Covered branches: 1
Total branches: 16
Branch coverage: 6.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%110%
Schedule(...)100%11100%
Schedule(...)100%11100%
Schedule()0%220%
ScheduleWithoutContext()0%220%
ScheduleCallback(...)50%2275%
ScheduleCallback(...)100%110%
InvokeWithContext(...)100%110%
InvokeWithoutContext(...)100%110%
OnContextApplied(...)100%110%
.ctor(...)100%110%
Invoke()100%110%
TraceAndInvoke()100%110%
.cctor()100%110%
.ctor()100%110%
OnTaskQueued(...)0%220%
GetScheduledTasks()100%110%
QueueTask(...)100%110%
TryExecuteTaskInline(...)0%220%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Runtime/ActionItem.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Collections.Concurrent;
 6using System.Collections.Generic;
 7using System.Threading;
 8using System.Threading.Tasks;
 9
 10namespace CoreWCF.Runtime
 11{
 12    // TODO: Make internal again. I had to expose this for cross assembly usage
 13    public abstract class ActionItem
 14    {
 15        //SecurityContext context;
 16        private bool _isScheduled;
 17
 018        protected ActionItem()
 19        {
 020        }
 21
 022        public bool LowPriority { get; protected set; }
 23
 24        public static void Schedule(Action<object> callback, object state)
 25        {
 487326            Schedule(callback, state, false);
 487327        }
 28
 29        public static void Schedule(Action<object> callback, object state, bool lowPriority)
 30        {
 31            Fx.Assert(callback != null, "A null callback was passed for Schedule!");
 32
 33            //if (Action<object>ActionItem.ShouldUseActivity ||
 34            //    Fx.Trace.IsEnd2EndActivityTracingEnabled)
 35            //{
 36            //    new DefaultActionItem(callback, state, lowPriority).Schedule();
 37            //}
 38            //else
 39            //{
 487340            ScheduleCallback(callback, state, lowPriority);
 41            //}
 487342        }
 43
 44
 45        protected abstract void Invoke();
 46
 47        protected void Schedule()
 48        {
 049            if (_isScheduled)
 50            {
 051                throw Fx.Exception.AsError(new InvalidOperationException(SR.ActionItemIsAlreadyScheduled));
 52            }
 53
 054            _isScheduled = true;
 55            //if (this.context != null)
 56            //{
 57            //    ScheduleCallback(CallbackHelper.InvokeWithContextCallback);
 58            //}
 59            //else
 60            //{
 061            ScheduleCallback(CallbackHelper.InvokeWithoutContextCallback);
 62            //}
 063        }
 64
 65        //protected void ScheduleWithContext(SecurityContext context)
 66        //{
 67        //    if (context == null)
 68        //    {
 69        //        throw Fx.Exception.ArgumentNull("context");
 70        //    }
 71        //    if (isScheduled)
 72        //    {
 73        //        throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.ActionItemIsAlreadyScheduled));
 74        //    }
 75
 76        //    this.isScheduled = true;
 77        //    this.context = context.CreateCopy();
 78        //    ScheduleCallback(CallbackHelper.InvokeWithContextCallback);
 79        //}
 80
 81        protected void ScheduleWithoutContext()
 82        {
 083            if (_isScheduled)
 84            {
 085                throw Fx.Exception.AsError(new InvalidOperationException(SR.ActionItemIsAlreadyScheduled));
 86            }
 87
 088            _isScheduled = true;
 089            ScheduleCallback(CallbackHelper.InvokeWithoutContextCallback);
 090        }
 91
 92        private static void ScheduleCallback(Action<object> callback, object state, bool lowPriority)
 93        {
 94            Fx.Assert(callback != null, "Cannot schedule a null callback");
 487395            if (lowPriority)
 96            {
 097                IOThreadScheduler.ScheduleCallbackLowPriNoFlow(callback, state);
 98            }
 99            else
 100            {
 4873101                IOThreadScheduler.ScheduleCallbackNoFlow(callback, state);
 102            }
 4873103        }
 104
 105        //SecurityContext ExtractContext()
 106        //{
 107        //    Fx.Assert(this.context != null, "Cannot bind to a null context; context should have been set by now");
 108        //    Fx.Assert(this.isScheduled, "Context is extracted only while the object is scheduled");
 109        //    SecurityContext result = this.context;
 110        //    this.context = null;
 111        //    return result;
 112        //}
 113
 114        private void ScheduleCallback(Action<object> callback)
 115        {
 0116            ScheduleCallback(callback, this, LowPriority);
 0117        }
 118
 119        private static class CallbackHelper
 120        {
 121            private static Action<object> s_invokeWithContextCallback;
 122            private static Action<object> s_invokeWithoutContextCallback;
 123            private static ContextCallback s_onContextAppliedCallback;
 124
 125            public static Action<object> InvokeWithContextCallback
 126            {
 127                get
 128                {
 0129                    if (s_invokeWithContextCallback == null)
 130                    {
 0131                        s_invokeWithContextCallback = InvokeWithContext;
 132                    }
 0133                    return s_invokeWithContextCallback;
 134                }
 135            }
 136
 137            public static Action<object> InvokeWithoutContextCallback
 138            {
 139                get
 140                {
 0141                    if (s_invokeWithoutContextCallback == null)
 142                    {
 0143                        s_invokeWithoutContextCallback = InvokeWithoutContext;
 144                    }
 0145                    return s_invokeWithoutContextCallback;
 146                }
 147            }
 148
 149            public static ContextCallback OnContextAppliedCallback
 150            {
 151                get
 152                {
 0153                    if (s_onContextAppliedCallback == null)
 154                    {
 0155                        s_onContextAppliedCallback = new ContextCallback(OnContextApplied);
 156                    }
 0157                    return s_onContextAppliedCallback;
 158                }
 159            }
 160
 161            private static void InvokeWithContext(object state)
 162            {
 0163                throw new PlatformNotSupportedException();
 164                //SecurityContext context = ((ActionItem)state).ExtractContext();
 165                //SecurityContext.Run(context, OnContextAppliedCallback, state);
 166            }
 167
 168            private static void InvokeWithoutContext(object state)
 169            {
 0170                ((ActionItem)state).Invoke();
 0171                ((ActionItem)state)._isScheduled = false;
 0172            }
 173
 174            private static void OnContextApplied(object o)
 175            {
 0176                ((ActionItem)o).Invoke();
 0177                ((ActionItem)o)._isScheduled = false;
 0178            }
 179        }
 180
 181        private class DefaultActionItem : ActionItem
 182        {
 183            private readonly Action<object> _callback;
 184            private readonly object _state;
 185
 186            //bool flowLegacyActivityId;
 187            //Guid activityId;
 188            //EventTraceActivity eventTraceActivity;
 189
 0190            public DefaultActionItem(Action<object> callback, object state, bool isLowPriority)
 191            {
 192                Fx.Assert(callback != null, "Shouldn't instantiate an object to wrap a null callback");
 0193                LowPriority = isLowPriority;
 0194                _callback = callback;
 0195                _state = state;
 196                //if (Action<object>ActionItem.ShouldUseActivity)
 197                //{
 198                //    this.flowLegacyActivityId = true;
 199                //    this.activityId = EtwDiagnosticTrace.ActivityId;
 200                //}
 201                //if (Fx.Trace.IsEnd2EndActivityTracingEnabled)
 202                //{
 203                //    this.eventTraceActivity = EventTraceActivity.GetFromThreadOrCreate();
 204                //    if (TraceCore.ActionItemScheduledIsEnabled(Fx.Trace))
 205                //    {
 206                //        TraceCore.ActionItemScheduled(Fx.Trace, this.eventTraceActivity);
 207                //    }
 208                //}
 209
 0210            }
 211
 212            protected override void Invoke()
 213            {
 214                //if (this.flowLegacyActivityId || Fx.Trace.IsEnd2EndActivityTracingEnabled)
 215                //{
 216                //    TraceAndInvoke();
 217                //}
 218                //else
 219                //{
 0220                _callback(_state);
 221                //}
 0222            }
 223
 224            private void TraceAndInvoke()
 225            {
 226                //TODO:  Consider merging these since they go through the same codepath.
 227                //if (this.flowLegacyActivityId)
 228                //{
 229                //    Guid currentActivityId = EtwDiagnosticTrace.ActivityId;
 230                //    try
 231                //    {
 232                //        EtwDiagnosticTrace.ActivityId = this.activityId;
 233                //        this.callback(this.state);
 234                //    }
 235                //    finally
 236                //    {
 237                //        EtwDiagnosticTrace.ActivityId = currentActivityId;
 238                //    }
 239                //}
 240                //else
 241                //{
 0242                Guid previous = Guid.Empty;
 0243                bool restoreActivityId = false;
 244                try
 245                {
 246                    //if (this.eventTraceActivity != null)
 247                    //{
 248                    //    previous = Trace.CorrelationManager.ActivityId;
 249                    //    restoreActivityId = true;
 250                    //    Trace.CorrelationManager.ActivityId = this.eventTraceActivity.ActivityId;
 251                    //    if (TraceCore.ActionItemCallbackInvokedIsEnabled(Fx.Trace))
 252                    //    {
 253                    //        TraceCore.ActionItemCallbackInvoked(Fx.Trace, this.eventTraceActivity);
 254                    //    }
 255                    //}
 0256                    _callback(_state);
 0257                }
 258                finally
 259                {
 0260                    if (restoreActivityId)
 261                    {
 262                        //Trace.CorrelationManager.ActivityId = previous;
 263                    }
 0264                }
 265                //}
 0266            }
 267        }
 268
 0269        public static TaskScheduler IOTaskScheduler = new IOThreadTaskScheduler();
 270
 271        internal class IOThreadTaskScheduler : TaskScheduler
 272        {
 273            [ThreadStatic]
 274            private static bool s_onSchedulerThread;
 275
 0276            internal IOThreadTaskScheduler()
 277            {
 0278                _tasks = new ConcurrentQueue<Task>();
 0279            }
 280
 281            // The queue of tasks to execute, maintained for debugging purposes
 282            // An alternative implementation would be to pass the Task directly
 283            // to the OnTaskQueued method. Using an intermediate queue might cause
 284            // a performance bottleneck. Profiling will be needed to determine.
 285            // Unless this is discovered to be a problem, using an intermediate
 286            // queue to aid in debugging.
 287            private readonly ConcurrentQueue<Task> _tasks;
 288
 289            private static void OnTaskQueued(object obj)
 290            {
 0291                var thisPtr = obj as IOThreadTaskScheduler;
 0292                if (thisPtr._tasks.TryDequeue(out Task nextTask))
 293                {
 0294                    s_onSchedulerThread = true;
 0295                    thisPtr.TryExecuteTask(nextTask);
 0296                    s_onSchedulerThread = false;
 297                }
 0298            }
 299
 300            protected override IEnumerable<Task> GetScheduledTasks()
 301            {
 0302                return _tasks;
 303            }
 304
 305            protected override void QueueTask(Task task)
 306            {
 0307                _tasks.Enqueue(task);
 0308                Schedule(OnTaskQueued, this);
 0309            }
 310
 311            protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
 312            {
 0313                return s_onSchedulerThread && TryExecuteTask(task);
 314            }
 315        }
 316    }
 317}