예제 #1
0
 private void WriteInt96(BinaryWriter writer, SchemaElement schema, IList data)
 {
     if (schema.ElementType == typeof(DateTimeOffset))
     {
         foreach (DateTimeOffset dto in data)
         {
             var nano = new NanoTime(dto);
             nano.Write(writer);
         }
     }
     else if (schema.ElementType == typeof(DateTime))
     {
         foreach (DateTime dtm in data)
         {
             var nano = new NanoTime(dtm.ToUniversalTime());
             nano.Write(writer);
         }
     }
     else
     {
         foreach (byte[] dto in data)
         {
             writer.Write(dto);
         }
     }
 }
        private void WorkLoop()
        {
            var test = Interlocked.CompareExchange(ref workerState, -1, -1);

            //if (Interlocked.CompareExchange(ref workerState, -1, -1) != WORKER_INIT)
            if (test == WORKER_KILLED)
            {
                throw new InvalidOperationException($"This should not happen! {test}");
            }

            while (Interlocked.CompareExchange(ref workerState, 0, 0) != WORKER_KILLED)
            {
                ExpireTimeouts();
                long newDeadline = CalcNewDeadline();
                var  sleepTime   = newDeadline - time.Elapsed;
                // tick before sleep so that timeout added while sleeping
                // will be delayed by a tick to avoid early wake up.
                Sleep(NanoTime.ToMilliseconds(sleepTime));
                Interlocked.Increment(ref ticked);
            }

            unprocessedTimeouts = new HashSet <TimedCallback>();
            foreach (var slot in slots)
            {
                TimedCallback timeout = null;
                while ((timeout = slot.TryPop()) != null)
                {
                    unprocessedTimeouts.Add(timeout);
                }
            }
            stopBarier.Signal();
        }
        public void TestExecutionOnTime()
        {
            var tickDuration       = TimeSpan.FromMilliseconds(200);
            var timeout            = TimeSpan.FromMilliseconds(125);
            var nanoTimeout        = NanoTime.FromMilliseconds(125);
            var maxTimeout         = 2 * (tickDuration + timeout);
            var nanoMaxTimeout     = NanoTime.FromMilliseconds(maxTimeout.TotalMilliseconds);
            HashedWheelTimer timer = new HashedWheelTimer(tickDuration);
            var queue = new BlockingCollection <long>();

            var watch = new ConcurrentStopwatch();

            watch.Start();
            int scheduledTasks = 100000;

            for (int i = 0; i < scheduledTasks; i++)
            {
                var start = watch.Elapsed;
                timer.ScheduleTimeout(() =>
                {
                    queue.Add(watch.Elapsed - start);
                }, timeout);
            }

            for (int i = 0; i < scheduledTasks; i++)
            {
                long delay = queue.Take();
                Assert.True(delay >= nanoTimeout && delay < nanoMaxTimeout, i + ": Timeout + " + scheduledTasks + " delay " + delay + " must be " + timeout + " < " + maxTimeout);
            }

            timer.Stop();
        }
예제 #4
0
 private void WriteAsInt96(BinaryWriter writer, IList values)
 {
     foreach (DateTimeOffset dto in values)
     {
         var nano = new NanoTime(dto);
         nano.Write(writer);
     }
 }
예제 #5
0
 private void ReadAsInt96(BinaryReader reader, IList result)
 {
     while (reader.BaseStream.Position + 12 <= reader.BaseStream.Length)
     {
         var            nano = new NanoTime(reader.ReadBytes(12), 0);
         DateTimeOffset dt   = nano;
         result.Add(dt.UtcDateTime);
     }
 }
예제 #6
0
        public void ConvertToDateTimeOffset_PreservesTicks()
        {
            var dto = new DateTimeOffset(2021, 05, 14, 17, 52, 31, TimeSpan.Zero);

            dto = dto.Add(TimeSpan.FromTicks(1234567));
            var nanoTime     = new NanoTime(dto);
            var convertedDto = (DateTimeOffset)nanoTime;

            Assert.Equal(dto, convertedDto);
        }
 private void DefaultInitialize()
 {
     DefaultTimeout = NanoTime.FromSeconds(10);
     TicksInterval  = NanoTime.FromMilliseconds(50);
     InitializeSlots();
     workerThread = new Thread(WorkLoop);
     time.Start();
     workerThread.Start();
     ticked = 0;
 }
 /// <summary>
 /// Create a timer with custamizable ticks interval and default timeout of TimedCallback.
 /// </summary>
 /// <param name="interval"></param>
 /// <param name="defaultTimeout"></param>
 /// <param name="policy"></param>
 public HashedWheelTimer(TimeSpan interval, TimeSpan defaultTimeout, SleepPolicy policy = SleepPolicy.Default)
 {
     TicksInterval  = NanoTime.FromMilliseconds(interval.TotalMilliseconds);
     DefaultTimeout = NanoTime.FromMilliseconds(defaultTimeout.TotalMilliseconds);
     ticked         = 0;
     SetSleep(policy);
     InitializeSlots();
     workerThread = new Thread(WorkLoop);
     time.Start();
     workerThread.Start();
 }
예제 #9
0
        private int ReadAsInt96(BinaryReader reader, DateTimeOffset[] dest, int offset)
        {
            int idx = offset;

            while (reader.BaseStream.Position + 12 <= reader.BaseStream.Length)
            {
                var            nano = new NanoTime(reader.ReadBytes(12), 0);
                DateTimeOffset dt   = nano;
                dest[idx++] = dt;
            }
            return(idx - offset);
        }
        public void TestDelayTimeoutShouldNotLargerThanSingleTickDuration(int tickInterval, int timeout)
        {
            var  watch   = new ConcurrentStopwatch();
            var  barrier = new CountdownEvent(1);
            var  timer   = new HashedWheelTimer(interval: TimeSpan.FromMilliseconds(tickInterval));
            long elapsed = 0;

            watch.Start();
            timer.ScheduleTimeout(() =>
            {
                Interlocked.Exchange(ref elapsed, watch.Elapsed);
                barrier.Signal();
            }, TimeSpan.FromMilliseconds(timeout));

            Assert.True(barrier.Wait(tickInterval * 2 + timeout), $"Elapsed: {NanoTime.ToMilliseconds(elapsed)}, ticks interval: {tickInterval}, timeout: {timeout}.");
        }
        /// <summary>
        /// Schedule a new callback with specified timeout in milliseconds.
        /// </summary>
        /// <param name="action">Callback function to be fired when timeout.</param>
        /// <returns>A callback wrapper which allow user to cancel timeout.</returns>
        public TimedCallback ScheduleTimeout(Action action, double milliseconds)
        {
            if (milliseconds < 0)
            {
                throw new ArgumentException("Expiry time cannot be negative.", "timeout");
            }
            CheckTimerState();

            var nanoTimeout   = NanoTime.FromMilliseconds(milliseconds);
            var actualTimeout = time.Elapsed + nanoTimeout;
            var callback      = new TimedCallback(action, actualTimeout, this);

            Interlocked.Increment(ref timeoutsCount);
            Interlocked.Increment(ref activeTimeoutsCount);
            ScheduleTimeoutImpl(callback, actualTimeout);

            return(callback);
        }
예제 #12
0
 private void ReadInt96(byte[] data, SchemaElement schema, IList destination)
 {
     for (int i = 0; i < data.Length; i += 12)
     {
         if (!_options.TreatBigIntegersAsDates)
         {
             byte[] v96 = new byte[12];
             Array.Copy(data, i, v96, 0, 12);;
             destination.Add(new BigInteger(v96));
         }
         else
         {
             var            nano = new NanoTime(data, i);
             DateTimeOffset dt   = nano;
             destination.Add(dt);
         }
     }
 }
        private void ScheduleTimeoutImpl(TimedCallback callback, long nanoseconds)
        {
            // TODO: Should always schedule to next tick
            var             differredTimeout = nanoseconds + TicksInterval;
            var             diff             = ToWheelTicks(differredTimeout);
            var             deadline         = NanoTime.ToMilliseconds(CalculateDeadline());
            var             due = diff + deadline;
            HashedWheelSlot slot;

            if (diff < WHEEL_SIZE)
            {
                var _ = (due & WHEEL_MASK);
                slot = slots[0, due & WHEEL_MASK];
            }
            else if (diff < 1 << (2 * WHEEL_BITS))
            {
                var _ = ((due >> WHEEL_BITS) & WHEEL_MASK);
                slot = slots[1, (due >> WHEEL_BITS) & WHEEL_MASK];
            }
            else if (diff < 1 << (3 * WHEEL_BITS))
            {
                var _ = ((due >> 2 * WHEEL_BITS) & WHEEL_MASK);
                slot = slots[2, (due >> 2 * WHEEL_BITS) & WHEEL_MASK];
            }
            else
            {
                if (diff > 0xffffffff)
                {
                    diff = 0xffffffff;
                    due  = NanoTime.ToMilliseconds(diff + deadline);
                }
                var _ = ((due >> 3 * WHEEL_BITS) & WHEEL_MASK);
                slot = slots[3, (due >> 3 * WHEEL_BITS) & WHEEL_MASK];
            }
            slot.Push(callback);
        }
 /// <summary>
 /// Create a timer with specified tick interval and sleep policy.
 /// </summary>
 /// <param name="interval">ticks interval</param>
 /// <param name="policy">Sleep policy</param>
 public HashedWheelTimer(TimeSpan interval, SleepPolicy policy = SleepPolicy.Default)
     : this(policy)
 {
     TicksInterval = NanoTime.FromMilliseconds(interval.TotalMilliseconds);
 }