internal void EnableCacheMemoryTimer(bool enable) { object timerLock = _timerLock; lock (timerLock) { if (enable) { if (_timerHandleRef == null) { Timer t = new Timer(new TimerCallback(this.CacheManagerTimerCallback), null, _currentPollInterval, _currentPollInterval); _timerHandleRef = new DisposableGCHandleRef <Timer>(t); } else { _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval); } } else { DisposableGCHandleRef <Timer> timerHandleRef = _timerHandleRef; if (timerHandleRef != null && Interlocked.CompareExchange <DisposableGCHandleRef <Timer> >(ref _timerHandleRef, null, timerHandleRef) == timerHandleRef) { timerHandleRef.Dispose(); } } } if (!enable) { while (_inCacheManagerThread != 0) { Thread.Sleep(100); } } }
internal void EnableCacheMemoryTimer(bool enable) { lock (_timerLock) { #if DBG if (Debug.IsTagPresent("Timer") && !Debug.IsTagEnabled("Timer")) { enable = false; } #endif if (enable) { if (_timerHandleRef == null) { // <cache privateBytesPollTime> has not been read yet Timer timer = new Timer(new TimerCallback(this.CacheManagerTimerCallback), null, _currentPollInterval, _currentPollInterval); _timerHandleRef = new DisposableGCHandleRef<Timer>(timer); Debug.Trace("Cache", "Started CacheMemoryTimers"); } else { _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval); } } else { var timerHandleRef = _timerHandleRef; if (timerHandleRef != null && Interlocked.CompareExchange(ref _timerHandleRef, null, timerHandleRef) == timerHandleRef) { timerHandleRef.Dispose(); Debug.Trace("Cache", "Stopped CacheMemoryTimers"); } } } if (!enable) { // wait for CacheManagerTimerCallback to finish while(_inCacheManagerThread != 0) { Thread.Sleep(100); } } }
internal CacheMultiple(CacheCommon cacheCommon, int numSingleCaches) : base(cacheCommon) { Debug.Assert(numSingleCaches > 1, "numSingleCaches is not greater than 1"); Debug.Assert((numSingleCaches & (numSingleCaches - 1)) == 0, "numSingleCaches is not a power of 2"); _cacheIndexMask = numSingleCaches - 1; // Each CacheSingle will have its own SRef reporting the size of the data it references. // Objects in this CacheSingle may have refs to the root Cache and therefore reference other instances of CacheSingle. // This leads to an unbalanced tree of SRefs and makes GC less efficient while calculating multiple SRefs on multiple cores. // Using DisposableGCHandleRef here prevents SRefs from calculating data that does not belong to other CacheSingle instances. _cachesRefs = new DisposableGCHandleRef<CacheSingle>[numSingleCaches]; for (int i = 0; i < numSingleCaches; i++) { _cachesRefs[i] = new DisposableGCHandleRef<CacheSingle>(new CacheSingle(cacheCommon, this, i)); } }