Exemple #1
0
        private void ClearCacheIfNeeded()
        {
            long Timestamp = PerformanceCounter.ElapsedMilliseconds;

            int Count = 0;

            while (Count++ < MaxRemovalsPerRun)
            {
                LinkedListNode <long> Node = SortedCache.First;

                if (Node == null)
                {
                    break;
                }

                CacheBucket Bucket = Cache[Node.Value];

                long TimeDelta = Timestamp - Bucket.Timestamp;

                if (TimeDelta <= MinTimeDelta && !UnderMemoryPressure())
                {
                    break;
                }

                SortedCache.Remove(Node);

                Cache.Remove(Node.Value);

                DeleteValueCallback(Bucket.Value);

                TotalSize -= Bucket.DataSize;
            }
        }
Exemple #2
0
        private void ClearCacheIfNeeded()
        {
            int Timestamp = Environment.TickCount;

            int Count = 0;

            while (Count++ < MaxRemovalsPerRun)
            {
                LinkedListNode <long> Node = SortedCache.First;

                if (Node == null)
                {
                    break;
                }

                CacheBucket Bucket = Cache[Node.Value];

                int TimeDelta = RingDelta(Bucket.Timestamp, Timestamp);

                if ((uint)TimeDelta <= (uint)MaxTimeDelta)
                {
                    break;
                }

                SortedCache.Remove(Node);

                Cache.Remove(Node.Value);

                DeleteValueCallback(Bucket.Value);
            }
        }
Exemple #3
0
        private void ClearCacheIfNeeded()
        {
            int Timestamp = Environment.TickCount;

            while (TotalSize > MaxTotalSize)
            {
                lock (SortedCache)
                {
                    LinkedListNode <long> Node = SortedCache.First;

                    if (Node == null)
                    {
                        break;
                    }

                    CacheBucket Bucket = Cache[Node.Value];

                    int TimeDelta = RingDelta(Bucket.Timestamp, Timestamp);

                    if ((uint)TimeDelta <= (uint)MaxTimeDelta)
                    {
                        break;
                    }

                    if (Cache.TryRemove(Node.Value, out Bucket))
                    {
                        TotalSize -= Bucket.Size;

                        SortedCache.Remove(Bucket.Node);
                    }
                }
            }
        }
Exemple #4
0
        public void AddOrUpdate(long Key, T Value, long Size)
        {
            if (!Locked)
            {
                ClearCacheIfNeeded();
            }

            LinkedListNode <long> Node = SortedCache.AddLast(Key);

            CacheBucket NewBucket = new CacheBucket(Value, Size, Node);

            if (Cache.TryGetValue(Key, out CacheBucket Bucket))
            {
                if (Locked)
                {
                    DeletePending.Enqueue(Bucket.Value);
                }
                else
                {
                    DeleteValueCallback(Bucket.Value);
                }

                SortedCache.Remove(Bucket.Node);

                Cache[Key] = NewBucket;
            }
            else
            {
                Cache.Add(Key, NewBucket);
            }
        }
Exemple #5
0
        private void ClearCacheIfNeeded()
        {
            long Timestamp = PerformanceCounter.ElapsedMilliseconds;

            int Count = 0;

            while (Count++ < MaxRemovalsPerRun)
            {
                LinkedListNode <long> Node = SortedCache.First;

                if (Node == null)
                {
                    break;
                }

                CacheBucket Bucket = Cache[Node.Value];

                long TimeDelta = Timestamp - Bucket.Timestamp;

                if ((uint)TimeDelta <= (uint)MaxTimeDelta)
                {
                    break;
                }

                SortedCache.Remove(Node);

                Cache.Remove(Node.Value);

                DeleteValueCallback(Bucket.Value);
            }
        }
Exemple #6
0
        private void ClearCacheIfNeeded()
        {
            long timestamp = PerformanceCounter.ElapsedMilliseconds;

            int count = 0;

            while (count++ < MaxRemovalsPerRun)
            {
                LinkedListNode <long> node = _sortedCache.First;

                if (node == null)
                {
                    break;
                }

                CacheBucket bucket = _cache[node.Value];

                long timeDelta = timestamp - bucket.Timestamp;

                if (timeDelta <= MinTimeDelta && !UnderMemoryPressure())
                {
                    break;
                }

                _sortedCache.Remove(node);

                _cache.Remove(node.Value);

                _deleteValueCallback(bucket.Value);

                _totalSize -= bucket.DataSize;
            }
        }
Exemple #7
0
        public void AddOrUpdate(long key, T value, long size)
        {
            if (!_locked)
            {
                ClearCacheIfNeeded();
            }

            LinkedListNode <long> node = _sortedCache.AddLast(key);

            CacheBucket newBucket = new CacheBucket(value, size, node);

            if (_cache.TryGetValue(key, out CacheBucket bucket))
            {
                if (_locked)
                {
                    _deletePending.Enqueue(bucket.Value);
                }
                else
                {
                    _deleteValueCallback(bucket.Value);
                }

                _sortedCache.Remove(bucket.Node);

                _totalSize -= bucket.DataSize;

                _cache[key] = newBucket;
            }
            else
            {
                _cache.Add(key, newBucket);
            }

            _totalSize += size;
        }
Exemple #8
0
        private void ClearCacheIfNeeded()
        {
            long timestamp = GetTimestamp();

            while (_totalSize > MaxTotalSize)
            {
                lock (_sortedCache)
                {
                    LinkedListNode <long> node = _sortedCache.First;

                    if (node == null)
                    {
                        break;
                    }

                    CacheBucket bucket = _cache[node.Value];

                    long timeDelta = timestamp - bucket.Timestamp;

                    if (timeDelta <= MinTimeDelta)
                    {
                        break;
                    }

                    if (_cache.TryRemove(node.Value, out bucket))
                    {
                        _totalSize -= bucket.Size;

                        _sortedCache.Remove(bucket.Node);
                    }
                }
            }
        }
Exemple #9
0
        public void should_return_value_in_other_class()
        {
            // Arrange
            var storage   = new InMemoryCacheStorage();
            var testKey   = "A";
            var testValue = "B";

            // Actions
            var bucket  = new CacheBucket(BUCKET_NAME_1, storage);
            var bucket2 = new CacheBucket(BUCKET_NAME_1, storage);

            bucket.SetValue(testKey, testValue);

            // Asserts
            bucket2.GetValue(testKey).Should().Be(testValue);
        }
Exemple #10
0
        public void should_create_bucket_success()
        {
            // Arrange
            var storage   = new InMemoryCacheStorage();
            var testKey   = "A";
            var testValue = "B";

            // Actions
            var bucket = new CacheBucket(BUCKET_NAME_1, storage);

            bucket.SetValue(testKey, testValue);

            // Asserts
            bucket.Name.Should().Be(BUCKET_NAME_1);
            bucket.GetValue(testKey).Should().Be(testValue);
        }
Exemple #11
0
        public CacheBucket Create(string name)
        {
            var names       = BucketNameHelper.ExtractBucketNames(name);
            var rootName    = names[0];
            var storageType = CacheStorageMapping.Instance.GetStorageType(rootName);
            var storage     = _sp.GetService(storageType) as ICacheStorage;

            var parent = GetParentBucket(name, storage, out var lastName);

            var bucket = new CacheBucket(lastName, storage)
            {
                Parent = parent
            };

            return(bucket);
        }
Exemple #12
0
        public bool TryGetValue(long Key, out T Value)
        {
            if (Cache.TryGetValue(Key, out CacheBucket Bucket))
            {
                Value = Bucket.Value;

                SortedCache.Remove(Bucket.Node);

                LinkedListNode <long> Node = SortedCache.AddLast(Key);

                Cache[Key] = new CacheBucket(Value, Bucket.DataSize, Node);

                return(true);
            }

            Value = default(T);

            return(false);
        }
Exemple #13
0
        public bool TryGetValue(long key, out T value)
        {
            if (_cache.TryGetValue(key, out CacheBucket bucket))
            {
                value = bucket.Value;

                _sortedCache.Remove(bucket.Node);

                LinkedListNode <long> node = _sortedCache.AddLast(key);

                _cache[key] = new CacheBucket(value, bucket.DataSize, node);

                return(true);
            }

            value = default(T);

            return(false);
        }
Exemple #14
0
        public void should_return_correct_values()
        {
            // Arrange
            var storage        = new InMemoryCacheStorage();
            var testKey        = "A";
            var childContainer = "1";
            var testValue      = "B";
            var testValue2     = "C";

            // Actions
            var bucket = new CacheBucket(BUCKET_NAME_1, storage);

            bucket.SetValue(testKey, testValue);
            bucket.In(childContainer).SetValue(testKey, testValue2);

            // Asserts
            testValue.Should().NotBe(testValue2);
            bucket.GetValue(testKey).Should().Be(testValue);
            bucket.In(childContainer).GetValue(testKey).Should().Be(testValue2);
        }
Exemple #15
0
        public void should_return_correct_value_when_quick_access()
        {
            // Arrange
            var storage        = new InMemoryCacheStorage();
            var testKey        = "A";
            var childContainer = "1";
            var testValue2     = "C";

            // Actions
            var bucket = new CacheBucket(BUCKET_NAME_1, storage);

            bucket.In(childContainer).SetValue(testKey, testValue2);

            var childBucket = new CacheBucket(new[] { BUCKET_NAME_1, childContainer }.ToBucketName(), storage);


            // Asserts
            bucket.In(childContainer).GetValue(testKey).Should().Be(testValue2);
            childBucket.GetValue(testKey).Should().Be(testValue2);
        }
Exemple #16
0
        public void Should_consitent_value_between_2_instances()
        {
            // Arrange
            var storage    = new InMemoryCacheStorage();
            var testKey    = "A";
            var testValue  = "B";
            var testValue2 = "C";

            // Actions
            var bucket  = new CacheBucket(BUCKET_NAME_1, storage);
            var bucket2 = new CacheBucket(BUCKET_NAME_1, storage);

            bucket.SetValue(testKey, testValue);
            bucket2.SetValue(testKey, testValue2);

            // Asserts
            bucket.GetValue(testKey)
            .Should().Be(bucket2.GetValue(testKey))
            .And.Subject.Should().Be(testValue2);
        }
Exemple #17
0
        public void should_return_different_value_from_different_buckets()
        {
            // Arrange
            var storage    = new InMemoryCacheStorage();
            var testKey    = "A";
            var testValue  = "B";
            var testValue2 = "C";

            // Actions
            var bucket  = new CacheBucket(BUCKET_NAME_1, storage);
            var bucket2 = new CacheBucket(BUCKET_NAME_2, storage);

            bucket.SetValue(testKey, testValue);
            bucket2.SetValue(testKey, testValue2);

            // Asserts
            testValue.Should().NotBe(testValue2);
            bucket.GetValue(testKey).Should().Be(testValue);
            bucket2.GetValue(testKey).Should().Be(testValue2);
        }
Exemple #18
0
        private CacheBucket GetParentBucket(string name, ICacheStorage storage, out string lastName)
        {
            var bucketNames = BucketNameHelper.ExtractBucketNames(name);

            lastName = bucketNames.Last();
            if (bucketNames.Length <= 1)
            {
                return(null);
            }
            CacheBucket parent = null;

            foreach (var bucketName in bucketNames.Skip(0).Take(bucketNames.Length - 1).Reverse())
            {
                var bucket = new CacheBucket(bucketName, storage)
                {
                    Parent = parent
                };
                parent = bucket;
            }

            return(parent);
        }
Exemple #19
0
        public void AddOrUpdate(long Position, ATranslatedSub Subroutine, int Size)
        {
            ClearCacheIfNeeded();

            TotalSize += Size;

            lock (SortedCache)
            {
                LinkedListNode <long> Node = SortedCache.AddLast(Position);

                CacheBucket NewBucket = new CacheBucket(Subroutine, Node, Size);

                Cache.AddOrUpdate(Position, NewBucket, (Key, Bucket) =>
                {
                    TotalSize -= Bucket.Size;

                    SortedCache.Remove(Bucket.Node);

                    return(NewBucket);
                });
            }
        }
Exemple #20
0
        public void AddOrUpdate(long position, TranslatedSub subroutine, int size)
        {
            ClearCacheIfNeeded();

            lock (_sortedCache)
            {
                _totalSize += size;

                LinkedListNode <long> node = _sortedCache.AddLast(position);

                CacheBucket newBucket = new CacheBucket(subroutine, node, size);

                _cache.AddOrUpdate(position, newBucket, (key, bucket) =>
                {
                    _totalSize -= bucket.Size;

                    _sortedCache.Remove(bucket.Node);

                    return(newBucket);
                });
            }
        }
Exemple #21
0
        public TranslatedSub GetOrAdd(long position, TranslatedSub subroutine, int size)
        {
            ClearCacheIfNeeded();

            lock (_sortedCache)
            {
                LinkedListNode <long> node = _sortedCache.AddLast(position);

                CacheBucket bucket = new CacheBucket(subroutine, node, size);

                bucket = _cache.GetOrAdd(position, bucket);

                if (bucket.Node == node)
                {
                    _totalSize += size;
                }
                else
                {
                    _sortedCache.Remove(node);
                }

                return(bucket.Subroutine);
            }
        }
Exemple #22
0
 public Enumerator(CacheBucket newBucket)
 {
     bucket = newBucket;
     idx    = -1;
 }
Exemple #23
0
            /// <summary>
            /// The time thread loop
            /// </summary>
            private void TimeThread()
            {
                log.InfoFormat("started timer thread {0} (ID:{1})", m_name, Thread.CurrentThread.ManagedThreadId);

                int       timeBalance = 0;
                uint      workStart, workEnd;
                GameTimer chain, next, bucketTimer;

                workStart = workEnd = (uint)GetTickCount();

#if MonitorCallbacks
                Timer t = new Timer(new TimerCallback(SlowTimerCallback), null, Timeout.Infinite, Timeout.Infinite);
#endif

                while (m_running)
                {
                    try
                    {
                        // fire timers
                        lock (m_buckets)
                        {
                            if (DOL.GS.GameEvents.RegionTimersResynch.watch != null)
                            {
                                m_time = DOL.GS.GameEvents.RegionTimersResynch.watch.ElapsedMilliseconds;
                            }
                            else
                            {
                                m_time++;
                            }

                            int newTick = m_tick = (m_tick + 1) & TICK_MASK;
                            if ((newTick & BUCKET_MASK) == 0)
                            {
                                // cache next bucket
                                int index = newTick >> BUCKET_BITS;
                                next = m_buckets[index];
                                if (next != null)
                                {
                                    m_buckets[index] = null;

                                    // sort the new cached bucket
                                    do
                                    {
                                        GameTimer timer = next;
                                        next = next.m_nextTimer;
                                        long index2 = timer.m_tick;
                                        if ((index2 & LONGTERM_MASK) != 0 &&
                                            ((index2 -= 1 << TABLE_BITS + BUCKET_BITS) & LONGTERM_MASK) != 0)
                                        {
                                            // reinsert longterm timers back
                                            timer.m_tick     = index2;
                                            bucketTimer      = m_buckets[index];
                                            m_buckets[index] = timer;
                                        }
                                        else
                                        {
                                            timer.m_tick = index2;
                                            index2      &= CACHE_MASK;
                                            bucketTimer  = m_cachedBucket[index2].FirstTimer;
                                            m_cachedBucket[index2].FirstTimer = timer;
                                            if (m_cachedBucket[index2].LastTimer == null)
                                            {
                                                m_cachedBucket[index2].LastTimer = timer;
                                            }
                                        }

                                        if (bucketTimer == null)
                                        {
                                            timer.m_nextTimer = null;
                                        }
                                        else
                                        {
                                            timer.m_nextTimer = bucketTimer;
                                        }
                                    }while (next != null);
                                }
                            }

                            int cacheIndex = m_tick & CACHE_MASK;
                            chain = m_cachedBucket[cacheIndex].FirstTimer;
                            if (chain != null)
                            {
                                m_cachedBucket[cacheIndex] = CacheBucket.EmptyBucket;
                            }
                        }

                        GameTimer current          = chain;
                        int       curTick          = m_tick;
                        int       currentBucketMax = (curTick & ~BUCKET_MASK) + BUCKET_MASK;
                        while (current != null)
                        {
                            if (current.m_tick == curTick)
                            {
                                try
                                {
                                    long callbackStart = GetTickCount();

#if MonitorCallbacks
                                    m_currentTimer   = current;
                                    m_timerTickStart = callbackStart;
                                    t.Change(200, 100);
#endif

                                    current.OnTick();

#if MonitorCallbacks
                                    m_currentTimer = null;
                                    t.Change(Timeout.Infinite, Timeout.Infinite);
                                    if (GetTickCount() - callbackStart > 200)
                                    {
                                        lock (m_delayLog)
                                        {
                                            m_delayLog.Write("\n========================================================\n\n");
                                        }
                                    }
#endif

                                    if (GetTickCount() - callbackStart > 250)
                                    {
                                        if (log.IsWarnEnabled)
                                        {
                                            string curStr;
                                            try { curStr = current.ToString(); }
                                            catch (Exception ee) { curStr = "error in timer.ToString(): " + current.GetType().FullName + "; " + ee.ToString(); }
                                            string warning = "callback took " + (GetTickCount() - callbackStart) + "ms! " + curStr;
                                            log.Warn(warning);
                                        }
                                    }

#if CollectStatistic
                                    // statistic
                                    int    start = GetTickCount();
                                    string callback;
                                    if (current is RegionTimer)
                                    {
                                        callback = ((RegionTimer)current).Callback.Method.ToString();
                                    }
                                    else
                                    {
                                        callback = current.GetType().FullName;
                                    }
                                    lock (m_timerCallbackStatistic)
                                    {
                                        object obj = m_timerCallbackStatistic[callback];
                                        if (obj == null)
                                        {
                                            m_timerCallbackStatistic[callback] = 1;
                                        }
                                        else
                                        {
                                            m_timerCallbackStatistic[callback] = ((int)obj) + 1;
                                        }
                                    }
                                    if (GetTickCount() - start > 500)
                                    {
                                        if (log.IsWarnEnabled)
                                        {
                                            log.Warn("Ticker statistic " + callback + " took more than 500ms!");
                                        }
                                    }
#endif
                                }
                                catch (Exception e)
                                {
                                    string curStr;
                                    try { curStr = current.ToString(); }
                                    catch (Exception ee) { curStr = "error in timer.ToString(): " + current.GetType().FullName + "; " + ee.ToString(); }
                                    if (log.IsErrorEnabled)
                                    {
                                        log.Error("Timer callback (" + curStr + ")", e);
                                    }

                                    current.m_tick = TIMER_DISABLED | TIMER_RESCHEDULED;
                                }

                                m_invokedCount++;
                            }
                            else if ((current.m_tick & TIMER_RESCHEDULED) == 0)
                            {
                                // log.ErrorFormat("timer tick != current tick (0x{0:X4}), fired anyway: {1}", curTick, current);
                                try
                                {
                                    current.OnTick();
                                }
                                catch (Exception e)
                                {
                                    log.Error("timer error", e);
                                    current.m_tick = TIMER_DISABLED | TIMER_RESCHEDULED;
                                }
                            }

                            lock (m_buckets)
                            {
                                next = current.m_nextTimer;
                                long tick     = current.m_tick;
                                long interval = current.m_interval;

                                if ((tick & TIMER_DISABLED) != 0 || (interval == 0 && (tick & TIMER_RESCHEDULED) == 0))
                                {
                                    m_activeTimers--;
                                    current.m_nextTimer  = null;
                                    current.m_tick       = TIMER_DISABLED;
                                    current.m_targetTime = -1;
                                }
                                else
                                {
                                    ///// REINSERT all including rescheduled timers
                                    if ((tick & TIMER_RESCHEDULED) != 0)
                                    {
                                        current.m_tick = tick &= ~TIMER_RESCHEDULED;
                                    }
                                    else
                                    {
                                        current.m_targetTime = (int)(CurrentTime + interval);
                                        current.m_tick       = tick = curTick + interval;
                                    }

                                    if (tick - curTick <= CACHE_MASK + 1)
                                    {
                                        tick           &= CACHE_MASK;
                                        current.m_tick &= TICK_MASK;
                                        CacheBucket bucket = m_cachedBucket[tick];
                                        GameTimer   prev   = bucket.LastTimer;
                                        current.m_nextTimer = null;
                                        if (prev != null)
                                        {
                                            prev.m_nextTimer = current;
                                            bucket.LastTimer = current;
                                        }
                                        else
                                        {
                                            bucket.FirstTimer = current;
                                            bucket.LastTimer  = current;
                                        }

                                        m_cachedBucket[tick] = bucket;
                                    }
                                    else
                                    {
                                        if ((tick & TICK_MASK) > currentBucketMax)
                                        {
                                            current.m_tick = tick += TICK_MASK + 1; // extra pass if the timer is ahead of current tick
                                        }

                                        tick        = (tick >> BUCKET_BITS) & TABLE_MASK;
                                        bucketTimer = m_buckets[tick];
                                        if (bucketTimer == null)
                                        {
                                            current.m_nextTimer = null;
                                        }
                                        else
                                        {
                                            current.m_nextTimer = bucketTimer;
                                        }

                                        m_buckets[tick] = current;
                                    }

                                    /////
                                }
                            }

                            current = next;
                        }

                        bucketTimer = null;

                        workEnd      = (uint)GetTickCount();
                        timeBalance += 1 - (int)(workEnd - workStart);

                        if (timeBalance > 0)
                        {
                            Thread.Sleep(timeBalance);
                            workStart    = (uint)GetTickCount();
                            timeBalance -= (int)(workStart - workEnd);
                        }
                        else
                        {
                            if (timeBalance < -1000)
                            {
                                // We can not increase forever if we get out of
                                // sync. At some point we have to print out a warning
                                // and catch up some time!
                                if (log.IsWarnEnabled && timeBalance < -2000)
                                {
                                    // Again, too much warning spam is meaningless.  Will warn if time sync is more than the typical 1 to 2 seconds
                                    // -tolakram
                                    log.Warn(Name + " out of sync, over 2000ms lost! " + timeBalance.ToString());
                                }

                                timeBalance += 1000;
                            }

                            workStart = workEnd;
                        }
                    }
                    catch (ThreadAbortException e)
                    {
                        if (log.IsWarnEnabled)
                        {
                            log.Warn("Time manager thread \"" + m_name + "\" was aborted", e);
                        }

                        m_running = false;
                        break;
                    }
                    catch (Exception e)
                    {
                        if (log.IsErrorEnabled)
                        {
                            log.Error("Exception in time manager \"" + m_name + "\"!", e);
                        }
                    }
                }

                log.InfoFormat("stopped timer thread {0} (ID:{1})", m_name, Thread.CurrentThread.ManagedThreadId);
            }
Exemple #24
0
            /// <summary>
            /// Removes the timer from the table without locking the table
            /// </summary>
            /// <param name="timer">The timer to remove</param>
            private void RemoveTimerUnsafe(GameTimer timer)
            {
                GameTimer t    = timer;
                long      tick = t.m_tick;

                if ((tick & TIMER_DISABLED) != 0)
                {
                    return;
                }

                timer.m_targetTime = -1;

                // never change the active chain
                if (tick == m_tick || (tick & TIMER_RESCHEDULED) != 0)
                {
                    t.m_tick = TIMER_DISABLED | TIMER_RESCHEDULED;
                    return;
                }

                m_activeTimers--;

                // check the cache first
                long        cachedIndex = tick & CACHE_MASK;
                CacheBucket bucket      = m_cachedBucket[cachedIndex];

                if (bucket.FirstTimer == t)
                {
                    t.m_tick          = TIMER_DISABLED;
                    bucket.FirstTimer = t.m_nextTimer;
                    if (bucket.LastTimer == t)
                    {
                        bucket.LastTimer = t.m_nextTimer;
                    }

                    t.m_nextTimer = null;
                    m_cachedBucket[cachedIndex] = bucket;
                    return;
                }

                GameTimer timerChain = bucket.FirstTimer;
                GameTimer prev;

                while (timerChain != null)
                {
                    prev       = timerChain;
                    timerChain = timerChain.m_nextTimer;
                    if (timerChain == t)
                    {
                        prev.m_nextTimer = t.m_nextTimer;
                        t.m_nextTimer    = null;
                        t.m_tick         = TIMER_DISABLED;
                        if (bucket.LastTimer == t)
                        {
                            bucket.LastTimer            = prev;
                            m_cachedBucket[cachedIndex] = bucket;
                        }

                        return;
                    }
                }

                // check the buckets
                tick       = (tick >> BUCKET_BITS) & TABLE_MASK;
                timerChain = m_buckets[tick];
                if (timerChain == t)
                {
                    timerChain      = timerChain.m_nextTimer;
                    m_buckets[tick] = timerChain;
                    t.m_nextTimer   = null;
                    t.m_tick        = TIMER_DISABLED;
                    return;
                }

                while (timerChain != null)
                {
                    prev       = timerChain;
                    timerChain = timerChain.m_nextTimer;
                    if (timerChain == t)
                    {
                        prev.m_nextTimer = t.m_nextTimer;
                        break;
                    }
                }

                t.m_nextTimer = null;
                t.m_tick      = TIMER_DISABLED;
            }
Exemple #25
0
            /// <summary>
            /// Inserts the timer into the table.
            /// </summary>
            /// <param name="t">The timer to insert</param>
            /// <param name="offsetTick">The offset from current tick. min value=1, max value&lt;MaxInterval</param>
            internal void InsertTimer(GameTimer t, int offsetTick)
            {
                if (offsetTick > MaxInterval || offsetTick < 1)
                {
                    throw new ArgumentOutOfRangeException("offsetTick", offsetTick.ToString(), "Offset must be in range from 1 to " + MaxInterval);
                }

                GameTimer timer = t;

                lock (m_buckets)
                {
                    long timerTick  = timer.m_tick;
                    long targetTick = m_tick + offsetTick;

                    if (timerTick == m_tick || (timerTick & TIMER_RESCHEDULED) != 0)
                    {
                        timer.m_targetTime = (int)(CurrentTime + offsetTick);
                        timer.m_tick       = targetTick | TIMER_RESCHEDULED;
                        return;
                    }

                    if ((timerTick & TIMER_DISABLED) == 0)
                    {
                        RemoveTimerUnsafe(timer);
                    }

                    timer.m_targetTime = (int)(CurrentTime + offsetTick);
                    m_activeTimers++;

                    if (offsetTick <= CACHE_MASK + 1)
                    {
                        timer.m_tick = targetTick & TICK_MASK;
                        targetTick  &= CACHE_MASK;
                        CacheBucket bucket = m_cachedBucket[targetTick];
                        GameTimer   prev   = bucket.LastTimer;
                        if (prev != null)
                        {
                            prev.m_nextTimer = timer;
                            m_cachedBucket[targetTick].LastTimer = timer;
                        }
                        else
                        {
                            bucket.FirstTimer          = timer;
                            bucket.LastTimer           = timer;
                            m_cachedBucket[targetTick] = bucket;
                        }
                    }
                    else
                    {
                        if ((targetTick & TICK_MASK) > (m_tick & ~BUCKET_MASK) + BUCKET_MASK)
                        {
                            targetTick += TICK_MASK + 1; // extra pass if the timer is ahead of current tick
                        }

                        timer.m_tick = targetTick;
                        targetTick   = (targetTick >> BUCKET_BITS) & TABLE_MASK;
                        GameTimer next = m_buckets[targetTick];
                        m_buckets[targetTick] = timer;
                        if (next != null)
                        {
                            timer.m_nextTimer = next;
                        }
                    }
                }
            }