private static IWorkspaceService GetVisualStudioProjectCache(HostWorkspaceServices workspaceServices)
        {
            var projectCacheService = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);

            var documentTrackingService = workspaceServices.GetService<IDocumentTrackingService>();

            // Subscribe to events so that we can cache items from the active document's project
            var manager = new ActiveProjectCacheManager(documentTrackingService, projectCacheService);

            // Subscribe to requests to clear the cache
            var workspaceCacheService = workspaceServices.GetService<IWorkspaceCacheService>();
            if (workspaceCacheService != null)
            {
                workspaceCacheService.CacheFlushRequested += (s, e) => manager.Clear();
            }

            // Also clear the cache when the solution is cleared or removed.
            workspaceServices.Workspace.WorkspaceChanged += (s, e) =>
            {
                if (e.Kind == WorkspaceChangeKind.SolutionCleared || e.Kind == WorkspaceChangeKind.SolutionRemoved)
                {
                    manager.Clear();
                }
            };

            return projectCacheService;
        }
        public void TestEjectFromImplicitCache()
        {
            List <Compilation> compilations = new List <Compilation>();

            for (int i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                compilations.Add(CSharpCompilation.Create(i.ToString()));
            }

            var weakFirst = ObjectReference.Create(compilations[0]);
            var weakLast  = ObjectReference.Create(compilations[compilations.Count - 1]);

            var workspace = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
            var cache     = new ProjectCacheService(workspace, int.MaxValue);

            for (int i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                cache.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, compilations[i]);
            }

            compilations = null;

            weakFirst.AssertReleased();
            weakLast.AssertHeld();

            GC.KeepAlive(cache);
        }
Beispiel #3
0
        public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
        {
            // we support active document tracking only for visual studio workspace host.
            if (workspaceServices.Workspace is MonoDevelopWorkspace)
            {
                // We will finish setting this up in VisualStudioWorkspaceImpl.DeferredInitializationState
                var projectCacheService     = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);
                var documentTrackingService = workspaceServices.GetService <IDocumentTrackingService> ();

                // Subscribe to events so that we can cache items from the active document's project
                var manager = new ActiveProjectCacheManager(documentTrackingService, projectCacheService);

                // Subscribe to requests to clear the cache
                var workspaceCacheService = workspaceServices.GetService <IWorkspaceCacheService> ();
                if (workspaceCacheService != null)
                {
                    workspaceCacheService.CacheFlushRequested += (s, e) => manager.Clear();
                }

                // Also clear the cache when the solution is cleared or removed.
                workspaceServices.Workspace.WorkspaceChanged += (s, e) => {
                    if (e.Kind == WorkspaceChangeKind.SolutionCleared || e.Kind == WorkspaceChangeKind.SolutionRemoved)
                    {
                        manager.Clear();
                    }
                };
            }

            // TODO: Handle miscellaneous files workspace later on.
            return(new ProjectCacheService(workspaceServices.Workspace));
        }
Beispiel #4
0
        public void TestEjectFromImplicitCache()
        {
            ProjectCacheService           cache = null;
            ObjectReference <Compilation> weakFirst = null, weakLast = null;

            FinalizerHelpers.PerformNoPinAction(() => {
                int total        = ProjectCacheService.ImplicitCacheSize + 1;
                var compilations = new Compilation [total];
                for (int i = 0; i < total; i++)
                {
                    compilations [i] = CSharpCompilation.Create(i.ToString());
                }

                weakFirst = ObjectReference.Create(compilations [0]);
                weakLast  = ObjectReference.Create(compilations [total - 1]);

                var workspace = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
                cache         = new ProjectCacheService(workspace, int.MaxValue);
                for (int i = 0; i < total; i++)
                {
                    cache.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, compilations [i]);
                }
            });

            weakFirst.AssertReleased();
            weakLast.AssertHeld();

            GC.KeepAlive(cache);
        }
Beispiel #5
0
        public static async Task <ProjectCacheService> FromDescriptorAsync(
            ProjectCacheDescriptor pluginDescriptor,
            BuildManager buildManager,
            ILoggingService loggingService,
            CancellationToken cancellationToken)
        {
            var plugin = await Task.Run(() => GetPluginInstance(pluginDescriptor), cancellationToken)
                         .ConfigureAwait(false);

            // TODO: Detect and use the highest verbosity from all the user defined loggers. That's tricky because right now we can't query loggers about
            // their verbosity levels.
            var loggerFactory = new Func <PluginLoggerBase>(() => new LoggingServiceToPluginLoggerAdapter(LoggerVerbosity.Normal, loggingService));

            var service = new ProjectCacheService(plugin, buildManager, loggerFactory, pluginDescriptor, cancellationToken);

            // TODO: remove the if after we change VS to set the cache descriptor via build parameters and always call BeginBuildAsync in FromDescriptorAsync.
            // When running under VS we can't initialize the plugin until we evaluate a project (any project) and extract
            // further information (set by VS) from it required by the plugin.
            if (!pluginDescriptor.VsWorkaround)
            {
                await service.BeginBuildAsync();
            }

            return(service);
        }
Beispiel #6
0
        public void TestP2PReference()
        {
            var workspace = new AdhocWorkspace();

            var project1     = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "proj1", "proj1", LanguageNames.CSharp);
            var project2     = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "proj2", "proj2", LanguageNames.CSharp, projectReferences: SpecializedCollections.SingletonEnumerable(new ProjectReference(project1.Id)));
            var solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, projects: new ProjectInfo[] { project1, project2 });

            var solution = workspace.AddSolution(solutionInfo);

            var instance = new object();
            var weak     = new WeakReference(instance);

            var cacheService = new ProjectCacheService(workspace, int.MaxValue);

            using (var cache = cacheService.EnableCaching(project2.Id))
            {
                cacheService.CacheObjectIfCachingEnabledForKey(project1.Id, (object)null, instance);
                instance = null;
                solution = null;

                workspace.OnProjectRemoved(project1.Id);
                workspace.OnProjectRemoved(project2.Id);
            }

            // make sure p2p reference doesn't go to implicit cache
            CollectGarbage();
            Assert.False(weak.IsAlive);
        }
Beispiel #7
0
        public void TestCacheCompilationTwice()
        {
            var comp1 = CSharpCompilation.Create("1");
            var comp2 = CSharpCompilation.Create("2");
            var comp3 = CSharpCompilation.Create("3");

            var weak3 = new WeakReference(comp3);
            var weak1 = new WeakReference(comp1);

            var cache = new ProjectCacheService(null, int.MaxValue);
            var key   = ProjectId.CreateNewId();
            var owner = new object();

            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp1);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp2);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);

            // When we cache 3 again, 1 should stay in the cache
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);
            comp1 = null;
            comp2 = null;
            comp3 = null;

            CollectGarbage();

            Assert.True(weak1.IsAlive);
            Assert.True(weak3.IsAlive);
            GC.KeepAlive(cache);
        }
Beispiel #8
0
        public void TestEjectFromImplicitCache()
        {
            List <Compilation> compilations = new List <Compilation>();

            for (int i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                compilations.Add(CSharpCompilation.Create(i.ToString()));
            }

            var weakFirst = new WeakReference(compilations[0]);
            var weakLast  = new WeakReference(compilations[compilations.Count - 1]);

            var cache = new ProjectCacheService(null, int.MaxValue);

            for (int i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                cache.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, compilations[i]);
            }

            compilations = null;
            CollectGarbage();

            Assert.False(weakFirst.IsAlive);
            Assert.True(weakLast.IsAlive);
            GC.KeepAlive(cache);
        }
Beispiel #9
0
        public void TestP2PReference()
        {
            var workspace = new AdhocWorkspace();

            var project1     = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "proj1", "proj1", LanguageNames.CSharp);
            var project2     = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "proj2", "proj2", LanguageNames.CSharp, projectReferences: SpecializedCollections.SingletonEnumerable(new ProjectReference(project1.Id)));
            var solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, projects: new ProjectInfo[] { project1, project2 });

            var solution = workspace.AddSolution(solutionInfo);

            var instanceTracker = ObjectReference.CreateFromFactory(() => new object());

            var cacheService = new ProjectCacheService(workspace, TimeSpan.MaxValue);

            using (var cache = cacheService.EnableCaching(project2.Id))
            {
                instanceTracker.UseReference(r => cacheService.CacheObjectIfCachingEnabledForKey(project1.Id, (object)null, r));
                solution = null;

                workspace.OnProjectRemoved(project1.Id);
                workspace.OnProjectRemoved(project2.Id);
            }

            // make sure p2p reference doesn't go to implicit cache
            instanceTracker.AssertReleased();
        }
Beispiel #10
0
        public void TestEjectFromImplicitCache()
        {
            var compilations = new List <Compilation>();

            for (var i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                compilations.Add(CSharpCompilation.Create(i.ToString()));
            }

            var weakFirst = ObjectReference.Create(compilations[0]);
            var weakLast  = ObjectReference.Create(compilations[compilations.Count - 1]);

            var workspace = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
            var cache     = new ProjectCacheService(workspace, TimeSpan.MaxValue);

            for (var i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                cache.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, compilations[i]);
            }

#pragma warning disable IDE0059 // Unnecessary assignment of a value - testing weak reference to compilations
            compilations = null;
#pragma warning restore IDE0059 // Unnecessary assignment of a value

            weakFirst.AssertReleased();
            weakLast.AssertHeld();

            GC.KeepAlive(cache);
        }
Beispiel #11
0
        public void TestCacheCompilationTwice()
        {
            var comp1 = CSharpCompilation.Create("1");
            var comp2 = CSharpCompilation.Create("2");
            var comp3 = CSharpCompilation.Create("3");

            var weak3 = ObjectReference.Create(comp3);
            var weak1 = ObjectReference.Create(comp1);

            var workspace = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
            var cache     = new ProjectCacheService(workspace, TimeSpan.MaxValue);
            var key       = ProjectId.CreateNewId();
            var owner     = new object();

            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp1);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp2);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);

            // When we cache 3 again, 1 should stay in the cache
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);
#pragma warning disable IDE0059 // Unnecessary assignment of a value - testing weak references to compilations
            comp1 = null;
            comp2 = null;
            comp3 = null;
#pragma warning restore IDE0059 // Unnecessary assignment of a value

            weak3.AssertHeld();
            weak1.AssertHeld();

            GC.KeepAlive(cache);
        }
        public void TestImplicitCacheMonitoring()
        {
            var workspace    = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
            var cacheService = new ProjectCacheService(workspace, 10);
            var weak         = PutObjectInImplicitCache(cacheService);

            var timeout = TimeSpan.FromSeconds(10);
            var current = DateTime.UtcNow;

            do
            {
                Thread.Sleep(100);
                CollectGarbage();

                if (DateTime.UtcNow - current > timeout)
                {
                    break;
                }
            }while (weak.IsAlive);

            // FailFast (and thereby capture a dump) to investigate what's
            // rooting the object.
            if (weak.IsAlive)
            {
                CodeAnalysis.Test.Utilities.ExceptionUtilities.FailFast(new Exception("Please investigate why the object wasn't collected!"));
            }

            GC.KeepAlive(cacheService);
        }
        public void TestCacheCompilationTwice()
        {
            var comp1 = CSharpCompilation.Create("1");
            var comp2 = CSharpCompilation.Create("2");
            var comp3 = CSharpCompilation.Create("3");

            var weak3 = ObjectReference.Create(comp3);
            var weak1 = ObjectReference.Create(comp1);

            var workspace = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
            var cache     = new ProjectCacheService(workspace, int.MaxValue);
            var key       = ProjectId.CreateNewId();
            var owner     = new object();

            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp1);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp2);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);

            // When we cache 3 again, 1 should stay in the cache
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);
            comp1 = null;
            comp2 = null;
            comp3 = null;

            weak3.AssertHeld();
            weak1.AssertHeld();

            GC.KeepAlive(cache);
        }
Beispiel #14
0
        private static ObjectReference <object> PutObjectInImplicitCache(ProjectCacheService cacheService)
        {
            var reference = ObjectReference.CreateFromFactory(() => new object());

            reference.UseReference(r => cacheService.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, r));

            return(reference);
        }
Beispiel #15
0
        private static WeakReference PutObjectInImplicitCache(ProjectCacheService cacheService)
        {
            var instance = new object();
            var weak     = new WeakReference(instance);

            cacheService.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, instance);
            instance = null;

            return(weak);
        }
Beispiel #16
0
        public void TestImplicitCacheMonitoring()
        {
            var workspace    = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
            var cacheService = new ProjectCacheService(workspace, TimeSpan.FromMilliseconds(10));
            var weak         = PutObjectInImplicitCache(cacheService);

            weak.AssertReleased();

            GC.KeepAlive(cacheService);
        }
            public ActiveProjectCacheManager(IDocumentTrackingService documentTrackingService, ProjectCacheService projectCacheService)
            {
                _documentTrackingService = documentTrackingService;
                _projectCacheService = projectCacheService;

                if (documentTrackingService != null)
                {
                    documentTrackingService.ActiveDocumentChanged += UpdateCache;
                    UpdateCache(null, documentTrackingService.GetActiveDocument());
                }
            }
            public ActiveProjectCacheManager(IDocumentTrackingService documentTrackingService, ProjectCacheService projectCacheService)
            {
                _documentTrackingService = documentTrackingService;
                _projectCacheService     = projectCacheService;

                if (documentTrackingService != null)
                {
                    documentTrackingService.ActiveDocumentChanged += UpdateCache;
                    UpdateCache(null, documentTrackingService.GetActiveDocument());
                }
            }
Beispiel #19
0
        public void TestImplicitCacheKeepsObjectAlive1()
        {
            var workspace    = new AdhocWorkspace(MockHostServices.Instance, workspaceKind: WorkspaceKind.Host);
            var cacheService = new ProjectCacheService(workspace, TimeSpan.MaxValue);
            var reference    = ObjectReference.CreateFromFactory(() => new object());

            reference.UseReference(r => cacheService.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, r));
            reference.AssertHeld();

            GC.KeepAlive(cacheService);
        }
Beispiel #20
0
        public void TestImplicitCacheKeepsObjectAlive1()
        {
            var cacheService = new ProjectCacheService(null, int.MaxValue);
            var instance     = new object();
            var weak         = new WeakReference(instance);

            cacheService.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, instance);
            instance = null;
            CollectGarbage();
            Assert.True(weak.IsAlive);
            GC.KeepAlive(cacheService);
        }
        private void Test(Action<IProjectCacheHostService, ProjectId, ICachedObjectOwner, ObjectReference> action)
        {
            // Putting cacheService.CreateStrongReference in a using statement
            // creates a temporary local that isn't collected in Debug builds
            // Wrapping it in a lambda allows it to get collected.
            var cacheService = new ProjectCacheService(null, int.MaxValue);
            var projectId = ProjectId.CreateNewId();
            var owner = new Owner();
            var instance = new ObjectReference();

            action(cacheService, projectId, owner, instance);
        }
Beispiel #22
0
        private static void Test(Action <IProjectCacheHostService, ProjectId, ICachedObjectOwner, ObjectReference <object> > action)
        {
            // Putting cacheService.CreateStrongReference in a using statement
            // creates a temporary local that isn't collected in Debug builds
            // Wrapping it in a lambda allows it to get collected.
            var cacheService = new ProjectCacheService(null, TimeSpan.MaxValue);
            var projectId    = ProjectId.CreateNewId();
            var owner        = new Owner();
            var instance     = ObjectReference.CreateFromFactory(() => new object());

            action(cacheService, projectId, owner, instance);
        }
        public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
        {
            var service = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);

            // Also clear the cache when the solution is cleared or removed.
            workspaceServices.Workspace.WorkspaceChanged += (s, e) =>
            {
                if (e.Kind == WorkspaceChangeKind.SolutionCleared || e.Kind == WorkspaceChangeKind.SolutionRemoved)
                {
                    service.ClearImplicitCache();
                }
            };

            return service;
        }
        private static IWorkspaceService GetMiscProjectCache(HostWorkspaceServices workspaceServices)
        {
            if (workspaceServices.Workspace.Kind != WorkspaceKind.Host)
            {
                return new ProjectCacheService(workspaceServices.Workspace);
            }

            var projectCacheService = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);

            // Also clear the cache when the solution is cleared or removed.
            workspaceServices.Workspace.WorkspaceChanged += (s, e) =>
            {
                if (e.Kind == WorkspaceChangeKind.SolutionCleared || e.Kind == WorkspaceChangeKind.SolutionRemoved)
                {
                    projectCacheService.ClearImplicitCache();
                }
            };

            return projectCacheService;
        }
Beispiel #25
0
        public static async Task <ProjectCacheService> FromDescriptorAsync(
            ProjectCacheDescriptor pluginDescriptor,
            BuildManager buildManager,
            ILoggingService loggingService,
            CancellationToken cancellationToken)
        {
            var plugin = await Task.Run(() => GetPluginInstance(pluginDescriptor), cancellationToken)
                         .ConfigureAwait(false);

            var service = new ProjectCacheService(plugin, buildManager, loggingService, pluginDescriptor, cancellationToken);

            // TODO: remove the if after we change VS to set the cache descriptor via build parameters and always call BeginBuildAsync in FromDescriptorAsync.
            // When running under VS we can't initialize the plugin until we evaluate a project (any project) and extract
            // further information (set by VS) from it required by the plugin.
            if (!pluginDescriptor.VsWorkaround)
            {
                await service.BeginBuildAsync();
            }

            return(service);
        }
Beispiel #26
0
        public void TestImplicitCacheMonitoring()
        {
            var cacheService = new ProjectCacheService(null, 10, forceCleanup: true);
            var weak         = PutObjectInImplicitCache(cacheService);

            var timeout = TimeSpan.FromSeconds(10);
            var current = DateTime.UtcNow;

            do
            {
                Thread.Sleep(100);
                CollectGarbage();

                if (DateTime.UtcNow - current > timeout)
                {
                    break;
                }
            }while (weak.IsAlive);

            Assert.False(weak.IsAlive);
            GC.KeepAlive(cacheService);
        }
        public void TestP2PReference()
        {
            var workspace = new AdhocWorkspace();

            var project1 = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "proj1", "proj1", LanguageNames.CSharp);
            var project2 = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "proj2", "proj2", LanguageNames.CSharp, projectReferences: SpecializedCollections.SingletonEnumerable(new ProjectReference(project1.Id)));
            var solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, projects: new ProjectInfo[] { project1, project2 });

            var solution = workspace.AddSolution(solutionInfo);

            var instance = new object();
            var weak = new WeakReference(instance);

            var cacheService = new ProjectCacheService(workspace, int.MaxValue);
            using (var cache = cacheService.EnableCaching(project2.Id))
            {
                cacheService.CacheObjectIfCachingEnabledForKey(project1.Id, (object)null, instance);
                instance = null;
                solution = null;

                workspace.OnProjectRemoved(project1.Id);
                workspace.OnProjectRemoved(project2.Id);
            }

            // make sure p2p reference doesnt go to implicit cache
            CollectGarbage();
            Assert.False(weak.IsAlive);

        }
            public ImplicitCacheMonitor(ProjectCacheService owner, int backOffTimeSpanInMS) :
                base(AggregateAsynchronousOperationListener.CreateEmptyListener(),
                     backOffTimeSpanInMS,
                     CancellationToken.None)
            {
                _owner = owner;
                _gate = new SemaphoreSlim(0);

                Start();
            }
 public void TestImplicitCacheKeepsObjectAlive1()
 {
     var cacheService = new ProjectCacheService(null, int.MaxValue);
     var instance = new object();
     var weak = new WeakReference(instance);
     cacheService.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, instance);
     instance = null;
     CollectGarbage();
     Assert.True(weak.IsAlive);
     GC.KeepAlive(cacheService);
 }
        public void TestImplicitCacheMonitoring()
        {
            var cacheService = new ProjectCacheService(null, 10, forceCleanup: true);
            var weak = PutObjectInImplicitCache(cacheService);

            var timeout = TimeSpan.FromSeconds(10);
            var current = DateTime.UtcNow;
            do
            {
                Thread.Sleep(100);
                CollectGarbage();

                if (DateTime.UtcNow - current > timeout)
                {
                    break;
                }
            }
            while (weak.IsAlive);

            Assert.False(weak.IsAlive);
            GC.KeepAlive(cacheService);
        }
        private static WeakReference PutObjectInImplicitCache(ProjectCacheService cacheService)
        {
            var instance = new object();
            var weak = new WeakReference(instance);

            cacheService.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, instance);
            instance = null;

            return weak;
        }
        public void TestCacheCompilationTwice()
        {
            var comp1 = CSharpCompilation.Create("1");
            var comp2 = CSharpCompilation.Create("2");
            var comp3 = CSharpCompilation.Create("3");

            var weak3 = new WeakReference(comp3);
            var weak1 = new WeakReference(comp1);

            var cache = new ProjectCacheService(null, int.MaxValue);
            var key = ProjectId.CreateNewId();
            var owner = new object();
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp1);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp2);
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);

            // When we cache 3 again, 1 should stay in the cache
            cache.CacheObjectIfCachingEnabledForKey(key, owner, comp3);
            comp1 = null;
            comp2 = null;
            comp3 = null;

            CollectGarbage();

            Assert.True(weak1.IsAlive);
            Assert.True(weak3.IsAlive);
            GC.KeepAlive(cache);
        }
        public void TestImplicitCacheMonitoring()
        {
            var cacheService = new ProjectCacheService(null, 10, forceCleanup: true);
            var weak = PutObjectInImplicitCache(cacheService);

            var timeout = TimeSpan.FromSeconds(10);
            var current = DateTime.UtcNow;
            do
            {
                Thread.Sleep(100);
                CollectGarbage();

                if (DateTime.UtcNow - current > timeout)
                {
                    break;
                }
            }
            while (weak.IsAlive);

            // FailFast (and thereby capture a dump) to investigate what's
            // rooting the object.
            if (weak.IsAlive)
            {
                CodeAnalysis.Test.Utilities.ExceptionUtilities.FailFast(new Exception("Please investigate why the object wasn't collected!"));
            }

            GC.KeepAlive(cacheService);
        }
        public void TestEjectFromImplicitCache()
        {
            List<Compilation> compilations = new List<Compilation>();
            for (int i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                compilations.Add(CSharpCompilation.Create(i.ToString()));
            }

            var weakFirst = new WeakReference(compilations[0]);
            var weakLast = new WeakReference(compilations[compilations.Count - 1]);

            var cache = new ProjectCacheService(null, int.MaxValue);
            for (int i = 0; i < ProjectCacheService.ImplicitCacheSize + 1; i++)
            {
                cache.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, compilations[i]);
            }

            compilations = null;
            CollectGarbage();

            Assert.False(weakFirst.IsAlive);
            Assert.True(weakLast.IsAlive);
            GC.KeepAlive(cache);
        }