<commit_before>using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using UnityEditor;

/*

    Scenarios:
    Quitting mid-operation both a Blocking and a Critical task.
    Implement escalating re-start delay on the main queue pumpt.
    Detect bad state quit - prompt to resume or halt operations.
    Detect git lock, offer to run cleanup or halt operations.
    Implement ability to resume after halted operations.
    Implement ability to skip a long fetch operation, so we can keep working.

*/

namespace GitHub.Unity
{
    class TaskQueueScheduler : ITaskQueueScheduler
    {
        public void Queue(ITask task)
        {
            Tasks.Add(task);
        }
    }

    class Tasks
    {
        private static readonly ILogging logger = Logging.GetLogger<Tasks>();

        internal const string TypeKey = "type";

        private const int NoTasksSleep = 15;
        private const int BlockingTaskWaitSleep = 10;
        private const int FailureDelayDefault = 1;
        private const int FailureDelayLong = 5000;
        private const string CacheFileName = "GitHubCache";
        private const string TaskThreadExceptionRestartError = "GitHub task thread restarting after encountering an exception: {0}";
        private const string TaskCacheWriteExceptionError = "GitHub: Exception when writing task cache: {0}";
        private const string TaskCacheParseError = "GitHub: Failed to parse task cache";
        private const string TaskParseUnhandledTypeError = "GitHub: Trying to parse unhandled cached task: {0}";
        private const string TaskFailureTitle = "GitHub";
        private const string TaskFailureMessage = "{0} failed:\n{1}";
        private const string TaskFailureOK = "OK";
        private const string TaskProgressTitle = "GitHub";
        private const string TaskBlockingTitle = "Critical GitHub task";
        private const string TaskBlockingDescription = "A critical GitHub task ({0}) has yet to complete. What would you like to do?";
        private const string TaskBlockingComplete = "Complete";
        private const string TaskBlockingInterrupt = "Interrupt";

        private static ProgressBarDisplayMethod displayBackgroundProgressBar;
        private static Action clearBackgroundProgressBar;
        private ITask activeTask;
        private Exception lastException;

        private bool running = false;
        private ConcurrentQueue<ITask> tasks;
        private object tasksLock = new object();
        private Thread thread;
        private readonly MainThreadSynchronizationContext context;
        private readonly CancellationToken cancellationToken;

        public Tasks(MainThreadSynchronizationContext context, CancellationToken cancellationToken)
        {
            this.context = context;
            this.cancellationToken = cancellationToken;

            tasks = new ConcurrentQueue<ITask>();
            Instance = this;
            //if (File.Exists(CacheFilePath))
            //{
            //    ReadCache();
            //    File.Delete(CacheFilePath);

            //    OnSessionRestarted();
            //}
        }

        public void Shutdown()
        {
            // Stop the queue
            running = false;

            if (activeTask != null && activeTask.Critical)
            {
                WaitForTask(activeTask, WaitMode.Blocking);
            }
        }

        public void Run()
        {
            thread = new Thread(Start);
            thread.Start();
        }

        public static void Add(ITask task)
        {
            Instance.AddTask(task);
        }

        private void AddTask(ITask task)
        {
            lock (tasksLock)
            {
                if ((task.Queued == TaskQueueSetting.NoQueue && tasks.Count > 0) ||
                    (task.Queued == TaskQueueSetting.QueueSingle && tasks.Any(t => t.GetType() == task.GetType())))
                {
                    return;
                }

                logger.Debug("Adding Task: \"{0}\" Label: \"{1}\"", task.GetType().Name, task.Label);
                tasks.Enqueue(task);<commit_msg>Don't queue multiple copies of the same task if it's single and currently running<commit_after>using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using UnityEditor;

/*

    Scenarios:
    Quitting mid-operation both a Blocking and a Critical task.
    Implement escalating re-start delay on the main queue pumpt.
    Detect bad state quit - prompt to resume or halt operations.
    Detect git lock, offer to run cleanup or halt operations.
    Implement ability to resume after halted operations.
    Implement ability to skip a long fetch operation, so we can keep working.

*/

namespace GitHub.Unity
{
    class TaskQueueScheduler : ITaskQueueScheduler
    {
        public void Queue(ITask task)
        {
            Tasks.Add(task);
        }
    }

    class Tasks
    {
        private static readonly ILogging logger = Logging.GetLogger<Tasks>();

        internal const string TypeKey = "type";

        private const int NoTasksSleep = 15;
        private const int BlockingTaskWaitSleep = 10;
        private const int FailureDelayDefault = 1;
        private const int FailureDelayLong = 5000;
        private const string CacheFileName = "GitHubCache";
        private const string TaskThreadExceptionRestartError = "GitHub task thread restarting after encountering an exception: {0}";
        private const string TaskCacheWriteExceptionError = "GitHub: Exception when writing task cache: {0}";
        private const string TaskCacheParseError = "GitHub: Failed to parse task cache";
        private const string TaskParseUnhandledTypeError = "GitHub: Trying to parse unhandled cached task: {0}";
        private const string TaskFailureTitle = "GitHub";
        private const string TaskFailureMessage = "{0} failed:\n{1}";
        private const string TaskFailureOK = "OK";
        private const string TaskProgressTitle = "GitHub";
        private const string TaskBlockingTitle = "Critical GitHub task";
        private const string TaskBlockingDescription = "A critical GitHub task ({0}) has yet to complete. What would you like to do?";
        private const string TaskBlockingComplete = "Complete";
        private const string TaskBlockingInterrupt = "Interrupt";

        private static ProgressBarDisplayMethod displayBackgroundProgressBar;
        private static Action clearBackgroundProgressBar;
        private ITask activeTask;
        private Exception lastException;

        private bool running = false;
        private ConcurrentQueue<ITask> tasks;
        private object tasksLock = new object();
        private Thread thread;
        private readonly MainThreadSynchronizationContext context;
        private readonly CancellationToken cancellationToken;

        public Tasks(MainThreadSynchronizationContext context, CancellationToken cancellationToken)
        {
            this.context = context;
            this.cancellationToken = cancellationToken;

            tasks = new ConcurrentQueue<ITask>();
            Instance = this;
            //if (File.Exists(CacheFilePath))
            //{
            //    ReadCache();
            //    File.Delete(CacheFilePath);

            //    OnSessionRestarted();
            //}
        }

        public void Shutdown()
        {
            // Stop the queue
            running = false;

            if (activeTask != null && activeTask.Critical)
            {
                WaitForTask(activeTask, WaitMode.Blocking);
            }
        }

        public void Run()
        {
            thread = new Thread(Start);
            thread.Start();
        }

        public static void Add(ITask task)
        {
            Instance.AddTask(task);
        }

        private void AddTask(ITask task)
        {
            lock (tasksLock)
            {
                if ((task.Queued == TaskQueueSetting.NoQueue && tasks.Count > 0) ||
                    (task.Queued == TaskQueueSetting.QueueSingle &&
                        ((activeTask != null && activeTask.GetType() == task.GetType()) ||
                        tasks.Any(t => t.GetType() == task.GetType()))))
                {
                    return;
                }

                logger.Trace("Adding Task: \"{0}\" Label: \"{1}\" ActiveTask: \"{2}\"", task.GetType().Name, task.Label, activeTask);
                tasks.Enqueue(task);
{'fraction_non_alphanumeric': 0.07856315179606026, 'fraction_numerical': 0.004287369640787949, 'mean_word_length': 2.2386491557223263, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3434075', 'n_tokens_mistral': 2150, 'n_tokens_neox': 2049, 'n_words': 687}