private readonly long _tickDuration; // a timespan expressed as ticks

        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="scheduler">TBD</param>
        /// <param name="log">TBD</param>
        /// <exception cref="ArgumentOutOfRangeException">TBD</exception>
        public HashedWheelTimerScheduler(Config scheduler, ILoggingAdapter log) : base(scheduler, log)
        {
            var ticksPerWheel = SchedulerConfig.GetInt("akka.scheduler.ticks-per-wheel");
            var tickDuration  = SchedulerConfig.GetTimeSpan("akka.scheduler.tick-duration");

            if (tickDuration.TotalMilliseconds < 10.0d)
            {
                throw new ArgumentOutOfRangeException("minimum supported akka.scheduler.tick-duration on Windows is 10ms");
            }

            // convert tick-duration to ticks
            _tickDuration = tickDuration.Ticks;

            // Normalize ticks per wheel to power of two and create the wheel
            _wheel = CreateWheel(ticksPerWheel, log);
            _mask  = _wheel.Length - 1;

            // prevent overflow
            if (_tickDuration >= long.MaxValue / _wheel.Length)
            {
                throw new ArgumentOutOfRangeException("akka.scheduler.tick-duration", _tickDuration,
                                                      $"akka.scheduler.tick-duration: {_tickDuration} (expected: 0 < tick-duration in ticks < {long.MaxValue / _wheel.Length}");
            }

            _shutdownTimeout = SchedulerConfig.GetTimeSpan("akka.scheduler.shutdown-timeout");
        }
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="config">TBD</param>
        /// <param name="log">TBD</param>
        public DedicatedThreadScheduler(Config config, ILoggingAdapter log) : base(config, log)
        {
            var precision = SchedulerConfig.GetTimeSpan("akka.scheduler.tick-duration");

            _shutdownTimeout = SchedulerConfig.GetTimeSpan("akka.scheduler.shutdown-timeout");
            var thread = new Thread(_ =>
            {
                var allWork = new List <ScheduledWork>();
                while (_stopped.Value == null)
                {
                    Thread.Sleep(precision);
                    var now = HighResMonotonicClock.Ticks;
                    ScheduledWork work;
                    while (_workQueue.TryDequeue(out work))
                    {
                        //has work already expired?
                        if (work.TickExpires < now)
                        {
                            work.Action();
                        }
                        else
                        {
                            //buffer it for later
                            allWork.Add(work);
                        }
                    }
                    //this is completely stupid, but does work..
                    if (allWork.Count > 0)
                    {
                        var tmp = allWork;
                        allWork = new List <ScheduledWork>();
                        foreach (var bufferedWork in tmp)
                        {
                            if (bufferedWork.TickExpires < now)
                            {
                                bufferedWork.Action();
                            }
                            else
                            {
                                allWork.Add(bufferedWork);
                            }
                        }
                    }
                }

                // shutdown has been signaled
                FireStopSignal();
            })
            {
                IsBackground = true
            };

            thread.Start();
        }