From 438fc16aeef33fc5a505baaa3995b333d95ff904 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 10 Aug 2020 14:29:13 +0100 Subject: [PATCH] changes on expiringkey, add expiringcacheOS, alternative to libomv on (no slide expire option) --- OpenSim/Framework/ExpiringKey.cs | 110 +++++++++++++++---------------- 1 file changed, 53 insertions(+), 57 deletions(-) diff --git a/OpenSim/Framework/ExpiringKey.cs b/OpenSim/Framework/ExpiringKey.cs index 27f64a8bec..ac02a67804 100644 --- a/OpenSim/Framework/ExpiringKey.cs +++ b/OpenSim/Framework/ExpiringKey.cs @@ -25,44 +25,44 @@ */ using System; -using System.Timers; using System.Threading; using System.Collections.Generic; -using Timer = System.Timers.Timer; +using Timer = System.Threading.Timer ; namespace OpenSim.Framework { - public class ExpiringKey : IDisposable + public sealed class ExpiringKey : IDisposable { - private Dictionary m_dictionary; + private const int MINEXPIRE = 500; - private ReaderWriterLockSlim m_rwLock = new ReaderWriterLockSlim(); - private readonly double m_startTS; - private readonly int expire; private Timer m_purgeTimer; + private ReaderWriterLockSlim m_rwLock; + private readonly Dictionary m_dictionary; + private readonly double m_startTS; + private readonly int m_expire; + + public ExpiringKey() + { + m_dictionary = new Dictionary(); + m_rwLock = new ReaderWriterLockSlim(); + m_expire = MINEXPIRE; + m_startTS = Util.GetTimeStampMS(); + } public ExpiringKey(int expireTimeinMS) { m_dictionary = new Dictionary(); + m_rwLock = new ReaderWriterLockSlim(); m_startTS = Util.GetTimeStampMS(); - expire = expireTimeinMS; - if(expire < 500) - expire = 500; + m_expire = (expireTimeinMS > MINEXPIRE) ? m_expire = expireTimeinMS : MINEXPIRE; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] - private void SetTimer() + private void CheckTimer() { if (m_purgeTimer == null) { - m_purgeTimer = new Timer() - { - Interval = expire, - AutoReset = false // time drift is not a issue. - - }; - m_purgeTimer.Elapsed += Purge; - m_purgeTimer.Start(); + m_purgeTimer = new Timer(Purge, null, m_expire, Timeout.Infinite); } } @@ -71,7 +71,6 @@ namespace OpenSim.Framework { if (m_purgeTimer != null) { - m_purgeTimer.Stop(); m_purgeTimer.Dispose(); m_purgeTimer = null; } @@ -88,24 +87,18 @@ namespace OpenSim.Framework GC.SuppressFinalize(this); } - protected void Dispose(bool disposing) + private void Dispose(bool disposing) { if (m_rwLock != null) { + DisposeTimer(); m_rwLock.Dispose(); m_rwLock = null; - DisposeTimer(); } } - private void Purge(object source, ElapsedEventArgs e) + private void Purge(object ignored) { - if (m_dictionary.Count == 0) - { - DisposeTimer(); - return; - } - bool gotLock = false; int now = (int)(Util.GetTimeStampMS() - m_startTS); @@ -117,6 +110,13 @@ namespace OpenSim.Framework m_rwLock.EnterWriteLock(); gotLock = true; } + + if (m_dictionary.Count == 0) + { + DisposeTimer(); + return; + } + List expired = new List(m_dictionary.Count); foreach(KeyValuePair kvp in m_dictionary) { @@ -128,7 +128,7 @@ namespace OpenSim.Framework if(m_dictionary.Count == 0) DisposeTimer(); else - m_purgeTimer.Start(); + m_purgeTimer.Change(m_expire, Timeout.Infinite); } finally { @@ -140,13 +140,10 @@ namespace OpenSim.Framework public void Add(Tkey1 key) { bool gotLock = false; - int now = (int)(Util.GetTimeStampMS() - m_startTS) + expire; + int now = (int)(Util.GetTimeStampMS() - m_startTS) + m_expire; try { - // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing - // the acquision inside the main try. The inner finally block is needed because thread aborts cannot - // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). try { } finally { @@ -155,7 +152,7 @@ namespace OpenSim.Framework } m_dictionary[key] = now; - SetTimer(); + CheckTimer(); } finally { @@ -167,17 +164,11 @@ namespace OpenSim.Framework public void Add(Tkey1 key, int expireMS) { bool gotLock = false; - int now; - if (expireMS > 500) - now = (int)(Util.GetTimeStampMS() - m_startTS) + expire; - else - now = (int)(Util.GetTimeStampMS() - m_startTS) + 500; + expireMS = (expireMS > m_expire) ? expireMS : m_expire; + int now = (int)(Util.GetTimeStampMS() - m_startTS) + expireMS; try { - // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing - // the acquision inside the main try. The inner finally block is needed because thread aborts cannot - // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). try { } finally { @@ -186,7 +177,7 @@ namespace OpenSim.Framework } m_dictionary[key] = now; - SetTimer(); + CheckTimer(); } finally { @@ -202,9 +193,6 @@ namespace OpenSim.Framework try { - // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing - // the acquision inside the main try. The inner finally block is needed because thread aborts cannot - // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). try {} finally { @@ -224,24 +212,20 @@ namespace OpenSim.Framework return success; } - public void Clear() { bool gotLock = false; try { - // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing - // the acquision inside the main try. The inner finally block is needed because thread aborts cannot - // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). try {} finally { m_rwLock.EnterWriteLock(); gotLock = true; - m_dictionary.Clear(); - DisposeTimer(); } + m_dictionary.Clear(); + DisposeTimer(); } finally { @@ -257,7 +241,22 @@ namespace OpenSim.Framework public bool ContainsKey(Tkey1 key) { - return m_dictionary.ContainsKey(key); + bool gotLock = false; + try + { + try { } + finally + { + m_rwLock.EnterReadLock(); + gotLock = true; + } + return m_dictionary.ContainsKey(key); + } + finally + { + if (gotLock) + m_rwLock.ExitReadLock(); + } } public bool TryGetValue(Tkey1 key, out int value) @@ -267,9 +266,6 @@ namespace OpenSim.Framework try { - // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing - // the acquision inside the main try. The inner finally block is needed because thread aborts cannot - // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). try {} finally {