protected bool ConfirmShutdown()
        {
            if (!this.IsShuttingDown)
            {
                return(false);
            }

            Contract.Assert(this.InEventLoop, "must be invoked from an event loop");

            this.CancelScheduledTasks();

            if (this.gracefulShutdownStartTime == PreciseTimeSpan.Zero)
            {
                this.gracefulShutdownStartTime = PreciseTimeSpan.FromStart;
            }

            if (this.RunAllTasks() || this.RunShutdownHooks())
            {
                if (this.IsShutdown)
                {
                    // Executor shut down - no new tasks anymore.
                    return(true);
                }

                // There were tasks in the queue. Wait a little bit more until no tasks are queued for the quiet period.
                this.WakeUp(true);
                return(false);
            }

            PreciseTimeSpan nanoTime = PreciseTimeSpan.FromStart;

            if (this.IsShutdown || (nanoTime - this.gracefulShutdownStartTime > this.gracefulShutdownTimeout))
            {
                return(true);
            }

            if (nanoTime - this.lastExecutionTime <= this.gracefulShutdownQuietPeriod)
            {
                // Check if any tasks were added to the queue every 100ms.
                // TODO: Change the behavior of takeTask() so that it returns on timeout.
                // todo: ???
                this.WakeUp(true);
                Thread.Sleep(100);

                return(false);
            }

            // No tasks were added for last quiet period - hopefully safe to shut down.
            // (Hopefully because we really cannot make a guarantee that there will be no execute() calls by a user.)
            return(true);
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="pool"></param>
 /// <param name="threadName"></param>
 /// <param name="breakoutInterval"></param>
 /// <param name="taskQueue"></param>
 protected SingleThreadEventExecutor(IThreadPoolExecutor pool, string threadName, TimeSpan breakoutInterval, IQueue <IRunnable> taskQueue)
     : base(pool)
 {
     this.terminationCompletionSource = new TaskCompletionSource();
     this.taskQueue = taskQueue;
     this.preciseBreakoutInterval = PreciseTimeSpan.FromTimeSpan(breakoutInterval);
     this.scheduler = new ExecutorTaskScheduler(this);
     this.thread    = new Thread(this.Loop);
     if (string.IsNullOrEmpty(threadName))
     {
         this.thread.Name = DefaultWorkerThreadName;
     }
     else
     {
         this.thread.Name = threadName;
     }
     this.thread.Start();
 }
 /// <inheritdoc cref="IEventExecutor"/>
 public abstract bool IsInEventLoop(Thread thread);
 /// <inheritdoc cref="IEventExecutor"/>
 public override bool IsInEventLoop(Thread t) => this.thread == t;