< Summary

Class:GDX.Threading.TaskBase
Assembly:GDX
File(s):./Packages/com.dotbunny.gdx/GDX/Threading/TaskBase.cs
Covered lines:81
Uncovered lines:0
Coverable lines:81
Total lines:305
Line coverage:100% (81 of 81)
Covered branches:0
Total branches:0
Covered methods:16
Total methods:16
Method coverage:100% (16 of 16)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
TaskBase()0%110100%
Complete()0%110100%
Enqueue()0%110100%
GetBits()0%110100%
GetBlockedBits()0%110100%
GetBlockingModes()0%110100%
GetException()0%110100%
GetName()0%110100%
IsBlockingAllTasks()0%110100%
IsBlockingBits()0%110100%
IsBlockingSameName()0%110100%
IsBlockingUserInterface()0%110100%
IsDone()0%110100%
IsExecuting()0%110100%
IsFaulted()0%110100%
Run()0%55096.97%

File(s)

./Packages/com.dotbunny.gdx/GDX/Threading/TaskBase.cs

#LineLine coverage
 1using System;
 2using System.Diagnostics;
 3using GDX.Collections;
 4
 5namespace GDX.Threading
 6{
 7    /// <summary>
 8    ///     The base of a task used by <see cref="TaskDirector" />.
 9    /// </summary>
 10    public abstract class TaskBase
 11    {
 12        /// <summary>
 13        ///     A set of flags indicating what type of blocking this task does when it comes to other tasks,
 14        ///     or even user experience.
 15        /// </summary>
 16        [Flags]
 17        public enum BlockingModeFlags : ushort
 18        {
 19            None = 0,
 20            All = 1,
 21            SameName = 2,
 22            Bits = 4,
 23            UserInteraction = 8
 24        }
 25
 26        /// <summary>
 27        ///     The default user-friendly name given to <see cref="TaskBase" />.
 28        /// </summary>
 29        const string k_DefaultName = "GDX Task";
 30
 31        /// <summary>
 32        ///     A timing mechanism to measure the duration of execution of the <see cref="TaskBase" />.
 33        /// </summary>
 2034        readonly Stopwatch m_Stopwatch = new Stopwatch();
 35
 36        /// <summary>
 37        ///     An event that is triggered when the <see cref="TaskBase" /> has finished its execution.
 38        /// </summary>
 39        /// <remarks>
 40        ///     It is <b>super important</b> to remember that subscribed actions will invoke off of the main thread.
 41        ///     Any logic that requires the main thread will not work. Many of Unity's APIs are not safe for this.
 42        /// </remarks>
 43        public Action<TaskBase> completed;
 44
 45        /// <summary>
 46        ///     An event that is triggered once the <see cref="TaskBase" /> has finished, during the next tick of the
 47        ///     <see cref="TaskDirector" />.
 48        /// </summary>
 49        /// <remarks>
 50        ///     This is a safe way to do work which requires being executed on the main thread.
 51        /// </remarks>
 52        public Action<TaskBase> completedMainThread;
 53
 54        /// <summary>
 55        ///     The <see cref="TaskBase" />'s descriptive bits.
 56        /// </summary>
 57        protected BitArray16 m_Bits;
 58
 59        /// <summary>
 60        ///     A quick set of bits used to describe tasks that should be blocked when
 61        ///     <see cref="m_BlockingModes" /> contains <see cref="BlockingModeFlags.Bits" />. The opposing
 62        ///     <see cref="TaskBase" /> will have its <see cref="m_Bits" /> checked for positives that match.
 63        /// </summary>
 64        /// <remarks>If any of them are the sam</remarks>
 65        protected BitArray16 m_BlockingBits;
 66
 67        /// <summary>
 68        ///     The <see cref="TaskBase" />'s blocking modes for other tasks.
 69        /// </summary>
 2070        protected BlockingModeFlags m_BlockingModes = BlockingModeFlags.None;
 71
 72        /// <summary>
 73        ///     The exception that occured.
 74        /// </summary>
 75        /// <remarks>See <see cref="IsFaulted" />.</remarks>
 76        protected Exception m_Exception;
 77
 78        /// <summary>
 79        ///     Has the task finished its execution/work.
 80        /// </summary>
 81        bool m_IsDone;
 82
 83        /// <summary>
 84        ///     A flag indicating if the task is executing, or if it is still waiting.
 85        /// </summary>
 86        bool m_IsExecuting;
 87
 88        /// <summary>
 89        ///     Did an exception occur while executing this <see cref="TaskBase" />?
 90        /// </summary>
 91        bool m_IsFaulted;
 92
 93        /// <summary>
 94        ///     Should the task report information to the <see cref="TaskDirector" /> log.
 95        /// </summary>
 2096        protected bool m_IsLogging = false;
 97
 98        /// <summary>
 99        ///     The user-friendly name of the task, used by different feedback systems.
 100        /// </summary>
 101        /// <remarks>It's important to set this in inherited constructors.</remarks>
 20102        protected string m_Name = k_DefaultName;
 103
 104        /// <summary>
 105        ///     Forcibly completes the task on the given thread where the method is invoked.
 106        /// </summary>
 107        /// <remarks>
 108        ///     This will also forcibly tick the <see cref="TaskDirector" /> upon completion to trigger callbacks. You
 109        ///     should not be using this unless you have an explicit purpose too.
 110        /// </remarks>
 111        public void Complete()
 1112        {
 1113            Enqueue();
 1114            DoWork();
 1115            TaskDirector.Tick();
 1116        }
 117
 118        /// <summary>
 119        ///     The core logic to be defined for a task.
 120        /// </summary>
 121        public abstract void DoWork();
 122
 123        /// <summary>
 124        ///     Enqueue the current <see cref="TaskBase" /> with the <see cref="TaskDirector" /> for execution.
 125        /// </summary>
 126        public void Enqueue()
 19127        {
 19128            TaskDirector.QueueTask(this);
 19129        }
 130
 131        /// <summary>
 132        ///     Gets the associated <see cref="BitArray16" /> with this task.
 133        /// </summary>
 134        /// <returns>The defined flags.</returns>
 135        public BitArray16 GetBits()
 26136        {
 26137            return m_Bits;
 26138        }
 139
 140        /// <summary>
 141        ///     Gets the <see cref="BitArray16" /> to evaluate other tasks against.
 142        /// </summary>
 143        /// <returns>The defined bits.</returns>
 144        public BitArray16 GetBlockedBits()
 4145        {
 4146            return m_BlockingBits;
 4147        }
 148
 149        /// <summary>
 150        ///     Returns the <see cref="BlockingModeFlags" /> used to determine other task execution.
 151        /// </summary>
 152        /// <returns>A set of flags indicating if other tasks should be able to start execution.</returns>
 153        public BlockingModeFlags GetBlockingModes()
 1154        {
 1155            return m_BlockingModes;
 1156        }
 157
 158        /// <summary>
 159        ///     Returns the <see cref="Exception" /> that was created when the task faulted.
 160        /// </summary>
 161        /// <remarks>See <see cref="IsFaulted" />.</remarks>
 162        /// <returns>An <see cref="Exception" /> object.</returns>
 163        public Exception GetException()
 2164        {
 2165            return m_Exception;
 2166        }
 167
 168        /// <summary>
 169        ///     Gets the user-friendly name of the task.
 170        /// </summary>
 171        /// <returns>The defined <see cref="string" /> name of the task.</returns>
 172        public string GetName()
 73173        {
 73174            return m_Name;
 73175        }
 176
 177        /// <summary>
 178        ///     Does this <see cref="TaskBase" /> block all other tasks after it from starting execution?
 179        /// </summary>
 180        /// <remarks>
 181        ///     This will keep all tasks after it sitting waiting for this task to complete.
 182        /// </remarks>
 183        /// <returns>true if this task blocks all after it, otherwise false.</returns>
 184        public bool IsBlockingAllTasks()
 40185        {
 40186            return m_BlockingModes.HasFlags(BlockingModeFlags.All);
 40187        }
 188
 189        /// <summary>
 190        ///     Does this <see cref="TaskBase" /> block other tasks from executing based on its
 191        ///     <see cref="m_BlockingBits" />?
 192        /// </summary>
 193        /// <returns>true if this tasks blocks based on bits, otherwise false.</returns>
 194        public bool IsBlockingBits()
 40195        {
 40196            return m_BlockingModes.HasFlags(BlockingModeFlags.Bits);
 40197        }
 198
 199        /// <summary>
 200        ///     Does this <see cref="TaskBase" /> block all other tasks of the same name from starting during
 201        ///     its execution?
 202        /// </summary>
 203        /// <returns>true if this tasks blocks same named tasks, otherwise false.</returns>
 204        public bool IsBlockingSameName()
 40205        {
 40206            return m_BlockingModes.HasFlags(BlockingModeFlags.SameName);
 40207        }
 208
 209        /// <summary>
 210        ///     Should the execution of this <see cref="TaskBase" /> prevent the user from providing input to the
 211        ///     user interface?
 212        /// </summary>
 213        /// <remarks>
 214        ///     This directly relates to the <see cref="TaskDirector.inputBlocked" />, altering the count used
 215        ///     to trigger that particular event.
 216        /// </remarks>
 217        /// <returns>true if this task should prevent user input, otherwise false.</returns>
 218        public bool IsBlockingUserInterface()
 40219        {
 40220            return m_BlockingModes.HasFlags(BlockingModeFlags.UserInteraction);
 40221        }
 222
 223        /// <summary>
 224        ///     Is the <see cref="TaskBase" /> finished executing?
 225        /// </summary>
 226        /// <returns>
 227        ///     Returns true if the execution phase of the task has been completed. This will be
 228        ///     true if an exception has occured.
 229        /// </returns>
 230        public bool IsDone()
 40231        {
 40232            return m_IsDone;
 40233        }
 234
 235        /// <summary>
 236        ///     Is the <see cref="TaskBase" /> currently executing on the thread pool?
 237        /// </summary>
 238        /// <returns>Returns true if the task is executing, otherwise false.</returns>
 239        public bool IsExecuting()
 42240        {
 42241            return m_IsExecuting;
 42242        }
 243
 244        /// <summary>
 245        ///     Did an exception occur while executing off thread?
 246        /// </summary>
 247        /// <returns>Returns true if an exception occured.</returns>
 248        public bool IsFaulted()
 20249        {
 20250            return m_IsFaulted;
 20251        }
 252
 253        /// <summary>
 254        ///     Execute task logic.
 255        /// </summary>
 256        public void Run()
 20257        {
 258            // Set flag at the start of the execution
 20259            m_IsExecuting = true;
 20260            m_IsDone = false;
 261
 262            // Start timing
 20263            m_Stopwatch.Start();
 264
 265            // Update task
 20266            TaskDirector.UpdateTask(this);
 267
 268            try
 20269            {
 20270                if (m_IsLogging)
 1271                {
 1272                    TaskDirector.Log($"Starting {m_Name}");
 1273                }
 274
 20275                DoWork();
 18276            }
 2277            catch (Exception e)
 2278            {
 2279                m_IsFaulted = true;
 2280                m_Exception = e;
 2281                if (m_IsLogging)
 1282                {
 1283                    TaskDirector.Log(e.Message);
 1284                }
 2285            }
 286            finally
 20287            {
 20288                m_IsDone = true;
 20289                m_IsExecuting = false;
 290
 291                // Invoke off thread (before main thread)
 20292                completed?.Invoke(this);
 293
 20294                TaskDirector.UpdateTask(this);
 295
 20296                m_Stopwatch.Stop();
 297
 20298                if (m_IsLogging)
 1299                {
 1300                    TaskDirector.Log($"{m_Name} finished in {m_Stopwatch.ElapsedMilliseconds}ms.");
 1301                }
 20302            }
 20303        }
 304    }
 305}

Coverage by test methods

















Methods/Properties

TaskBase()
Complete()
Enqueue()
GetBits()
GetBlockedBits()
GetBlockingModes()
GetException()
GetName()
IsBlockingAllTasks()
IsBlockingBits()
IsBlockingSameName()
IsBlockingUserInterface()
IsDone()
IsExecuting()
IsFaulted()
Run()