public void FreeSharedResources_GivenTheSharedResourceGroupHasSharedResourcesThatHaveBeenConnected_FreesThemAll()
        {
            // Arrange
            var resource1 = new SharedResource();
            var resource2 = new SharedResource();
            var resourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(resource1, resource2);
            resourceGroup.ConnectSharedResources(resource1, resource2);

            // Act
            resourceGroup.FreeSharedResources();

            // Assert
            resource1.GetCurrentRootSharedResourceIdentifier().IsAcquired().Should().BeFalse();
            resource2.GetCurrentRootSharedResourceIdentifier().IsAcquired().Should().BeFalse();
        }
        public void CreateAcquiringSharedResources_GivenASingleSharedResource_AcquiresThatSharedResource()
        {
            // Arrange
            var resource = new SharedResource();

            // Act
            var resourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(resource);

            // Assert
            resource.GetCurrentRootSharedResourceIdentifier().IsAcquiredBy(resourceGroup).Should().BeTrue();
        }
        public void CreateAcquiringSharedResources_GivenMultipleSharedResources_AcquiresTheSharedResourcesInOrderOfSharedResourceIdentifierAscending()
        {
            // Arrange
            var childResource = new SharedResource();
            var parentResource = new SharedResource();
            var child = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(childResource.GetCurrentRootSharedResourceIdentifier(), parentResource.GetCurrentRootSharedResourceIdentifier());
            var parent = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(child);
            childResource.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(child);
            parentResource.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(parent);
            var competingResourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(childResource, parentResource);

            // Act
            SharedResourceGroup resourceGroup = null;
            var thread = new Thread(() => resourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(childResource, parentResource));
            thread.Start();
            Thread.Sleep(500);

            // Assert
            child.IsAcquiredBy(competingResourceGroup).Should().BeTrue();
            parent.IsAcquiredBy(competingResourceGroup).Should().BeTrue();

            // Act
            parent.Free(competingResourceGroup);
            Thread.Sleep(500);

            // Assert
            child.IsAcquiredBy(competingResourceGroup).Should().BeTrue();
            parent.IsAcquired().Should().BeFalse();

            // Act
            parent.Acquire(competingResourceGroup);
            child.Free(competingResourceGroup);
            Thread.Sleep(500);

            // Assert
            child.IsAcquired().Should().BeTrue();
            child.IsAcquiredBy(competingResourceGroup).Should().BeFalse();
            parent.IsAcquiredBy(competingResourceGroup).Should().BeTrue();

            // Act
            parent.Free(competingResourceGroup);
            Thread.Sleep(500);

            // Assert
            resourceGroup.Should().NotBeNull();
            child.IsAcquiredBy(resourceGroup).Should().BeTrue();
            parent.IsAcquiredBy(resourceGroup).Should().BeTrue();
        }
        public void CreateAcquiringSharedResources_GivenTheSharedResourceIdentifierChangesAndThatChangesTheOrderInWhichToAcquireSharedResources_CanStillAcquireSharedResourcesEventually()
        {
            // Arrange
            var childResource = new SharedResource();
            var parentResource = new SharedResource();
            var child = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(childResource.GetCurrentRootSharedResourceIdentifier(), parentResource.GetCurrentRootSharedResourceIdentifier());
            var parent = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(child);
            var grandParent = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(parent);
            childResource.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(child);
            parentResource.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(parent);
            var competingResourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(childResource, parentResource);

            // Act
            SharedResourceGroup resourceGroup = null;
            var thread = new Thread(() => resourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(childResource, parentResource));
            thread.Start();
            Thread.Sleep(500);

            // Assert
            child.IsAcquiredBy(competingResourceGroup).Should().BeTrue();
            parent.IsAcquiredBy(competingResourceGroup).Should().BeTrue();

            // Act
            child.SetParentSharedResourceIdentifier(grandParent);
            child.Free(competingResourceGroup);
            Thread.Sleep(500);

            // Assert
            child.IsAcquired().Should().BeFalse();
            parent.IsAcquiredBy(competingResourceGroup).Should().BeTrue();
            grandParent.IsAcquired().Should().BeFalse();

            // Act
            grandParent.Acquire(competingResourceGroup);
            parent.Free(competingResourceGroup);
            Thread.Sleep(500);

            // Assert
            grandParent.IsAcquiredBy(competingResourceGroup).Should().BeTrue();
            parent.IsAcquired().Should().BeTrue();

            // Act
            grandParent.Free(competingResourceGroup);
            Thread.Sleep(500);

            // Assert
            resourceGroup.Should().NotBeNull();
            child.IsAcquired().Should().BeFalse();
            parent.IsAcquiredBy(resourceGroup).Should().BeTrue();
            grandParent.IsAcquiredBy(resourceGroup).Should().BeTrue();
        }
        public void CreateAcquiringSharedResources_GivenMultipleSharedResourcesWithNoCompetition_AcquiresThemAll()
        {
            // Arrange
            var resource1 = new SharedResource();
            var resource2 = new SharedResource();

            // Act
            var resourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(resource1, resource2);

            // Assert
            resource1.GetCurrentRootSharedResourceIdentifier().IsAcquiredBy(resourceGroup).Should().BeTrue();
            resource2.GetCurrentRootSharedResourceIdentifier().IsAcquiredBy(resourceGroup).Should().BeTrue();
        }
        public void CreateAcquiringSharedResources_GivenMultipleSharedResourcesWithTheSameSharedResourceIdentifier_CanAcquireThemAll()
        {
            // Arrange
            var resource1 = new SharedResource();
            var resource2 = new SharedResource();
            var resourceIdentifier = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(resource1.GetCurrentRootSharedResourceIdentifier(), resource2.GetCurrentRootSharedResourceIdentifier());
            resource1.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(resourceIdentifier);
            resource2.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(resourceIdentifier);

            // Act
            var resourceGroup = SharedResourceGroup.CreateAcquiringSharedResources(resource1, resource2);

            // Assert
            resource1.GetCurrentRootSharedResourceIdentifier().IsAcquiredBy(resourceGroup).Should().BeTrue();
            resource2.GetCurrentRootSharedResourceIdentifier().IsAcquiredBy(resourceGroup).Should().BeTrue();
        }
        private bool TryAcquireSharedResource(SharedResource sharedResource)
        {
            var resourceIdentifier = sharedResource.GetCurrentRootSharedResourceIdentifier();
            resourceIdentifier.Acquire(this);

            var acquiredRootResourceIdentifier = resourceIdentifier.Equals(sharedResource.GetCurrentRootSharedResourceIdentifier());

            if (!acquiredRootResourceIdentifier) resourceIdentifier.Free(this);
            return acquiredRootResourceIdentifier;
        }
        public void ConnectSharedResources(SharedResource resource1, SharedResource resource2)
        {
            CheckSharedResourcesAcquired();
            CheckSharedResourcesAreInGroup(resource1, resource2);
            if (resource1.Equals(resource2) || resource1.DirectlyConnectedSharedResources.Contains(resource2)) return;

            resource1.DirectlyConnect(resource2);

            var resource1Identifier = resource1.GetCurrentRootSharedResourceIdentifier();
            var resource2Identifier = resource2.GetCurrentRootSharedResourceIdentifier();
            if (resource1Identifier.Equals(resource2Identifier)) return;

            var parentResourceIdentifier = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(resource1Identifier, resource2Identifier);
            parentResourceIdentifier.Acquire(this);

            resource1Identifier.SetParentSharedResourceIdentifier(parentResourceIdentifier);
            resource2Identifier.SetParentSharedResourceIdentifier(parentResourceIdentifier);

            // We must free these SharedResource identifiers to ensure that we do not hold onto them after the group is freed.
            resource1Identifier.Free(this);
            resource2Identifier.Free(this);
        }
        public void DisconnectSharedResources(SharedResource resource1, SharedResource resource2)
        {
            CheckSharedResourcesAcquired();
            CheckSharedResourcesAreInGroup(resource1, resource2);
            if (resource1 == resource2) throw new ArgumentException("You cannot disconnect a shared resource form itself");
            if (!resource1.DirectlyConnectedSharedResources.Contains(resource2)) return;

            resource1.RemoveDirectConnectionTo(resource2);
            if (resource1.ConnectedSharedResources.Contains(resource2)) return;

            // All resources connected to resource 1 or 2 should have been acquired and have the same root shared resource identifier
            var originalResourceIdentifier = resource1.GetCurrentRootSharedResourceIdentifier();
            var newResourceIdentifierForResource1 = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(originalResourceIdentifier);
            newResourceIdentifierForResource1.Acquire(this);
            foreach (var resource in resource1.ConnectedSharedResources)
            {
                resource.ResetRootSharedResourceIdentifier(newResourceIdentifierForResource1);
            }
            var newResourceIdentifierForResource2 = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(newResourceIdentifierForResource1);
            newResourceIdentifierForResource2.Acquire(this);
            foreach (var resource in resource2.ConnectedSharedResources)
            {
                resource.ResetRootSharedResourceIdentifier(newResourceIdentifierForResource2);
            }
            originalResourceIdentifier.Free(this);
        }
 public SharedResource CreateAndAcquireSharedResource()
 {
     CheckSharedResourcesAcquired();
     var resource = new SharedResource();
     resource.GetCurrentRootSharedResourceIdentifier().Acquire(this);
     sharedResources.Add(resource);
     return resource;
 }
        public void ResetRootSharedResourceIdentifier_GivenASharedResourceIdentifier_SetsTheRootToBeThatSharedResourceIdentifier()
        {
            // Arrange
            var sharedResource1 = new SharedResource();
            var sharedResource2 = new SharedResource();
            var sharedRoot = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(sharedResource1.GetCurrentRootSharedResourceIdentifier(), sharedResource2.GetCurrentRootSharedResourceIdentifier());
            sharedResource1.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(sharedRoot);
            sharedResource2.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(sharedRoot);
            var newRootForSharedResource1 = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(sharedRoot);
            var newRootForSharedResource2 = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(sharedRoot);

            // Act
            sharedResource1.ResetRootSharedResourceIdentifier(newRootForSharedResource1);
            sharedResource2.ResetRootSharedResourceIdentifier(newRootForSharedResource2);

            // Assert
            sharedResource1.GetCurrentRootSharedResourceIdentifier().Should().Be(newRootForSharedResource1);
            sharedResource2.GetCurrentRootSharedResourceIdentifier().Should().Be(newRootForSharedResource2);
            sharedResource1.GetCurrentRootSharedResourceIdentifier().Should().NotBeSameAs(sharedResource2.GetCurrentRootSharedResourceIdentifier());
        }
        public void GetCurrentRootResourceIdentifier_GivenItsInitialResourceIdentifierHasAParent_ReturnsThatParent()
        {
            // Arrange
            var resource = new SharedResource();
            var child = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(resource.GetCurrentRootSharedResourceIdentifier());
            var parent = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(child);
            resource.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(child);
            child.SetParentSharedResourceIdentifier(parent);

            // Act
            var root = resource.GetCurrentRootSharedResourceIdentifier();

            // Assert
            root.Should().Be(parent);
        }
        public void GetCurrentRootResourceIdentifier_GivenAResourceJustInitialisedWithAResourceIdentifier_ReturnsThatResourceIdentifier()
        {
            // Arrange
            var resource = new SharedResource();
            var resourceIdentifier = SharedResourceIdentifier.CreateSharedResourceIdentifierBiggerThan(resource.GetCurrentRootSharedResourceIdentifier());
            resource.GetCurrentRootSharedResourceIdentifier().SetParentSharedResourceIdentifier(resourceIdentifier);

            // Act
            var root = resource.GetCurrentRootSharedResourceIdentifier();

            // Assert
            root.Should().Be(resourceIdentifier);
        }