diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs index 2193f1ed..cd1f658d 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs @@ -27,6 +27,7 @@ using Spring.Objects.Factory.Config; using Spring.Objects.Factory.Support; using Spring.Threading; using System.Threading; +using System.Diagnostics; #endregion @@ -556,7 +557,6 @@ namespace Spring.Objects.Factory theSpouse.IsSingleton = false; ObjectFactory.RegisterObjectDefinition("theSpouse", theSpouse); - GenericObjectDefinition theObject = new GenericObjectDefinition(); theObject.ObjectTypeName = typeof(TestObject).FullName; theObject.IsSingleton = false; @@ -575,4 +575,106 @@ namespace Spring.Objects.Factory } } + + [TestFixture] + [Ignore] + public class SPRNET_1338 + { + private static AbstractObjectFactory _cachedFactory; + + protected static AbstractObjectFactory ObjectFactory + { + get { return _cachedFactory; } + set { _cachedFactory = value; } + } + + [SetUp] + public void _SetUp() + { + ObjectFactory = CreateObjectFactory(true); + + GenericObjectDefinition threadCreatorInsideConstructor = new GenericObjectDefinition(); + threadCreatorInsideConstructor.ObjectTypeName = typeof(ThreadCreatorInsideConstructor).FullName; + threadCreatorInsideConstructor.IsSingleton = true; + ObjectFactory.RegisterObjectDefinition("threadCreatorInsideConstructor", threadCreatorInsideConstructor); + + GenericObjectDefinition threadCreatorInsideDispose = new GenericObjectDefinition(); + threadCreatorInsideDispose.ObjectTypeName = typeof(ThreadCreatorInsideDispose).FullName; + threadCreatorInsideDispose.IsSingleton = true; + ObjectFactory.RegisterObjectDefinition("threadCreatorInsideDispose", threadCreatorInsideDispose); + } + + [Test] + public void CanAvoidLockContentionDuringObjectFactoryDisposal() + { + Thread t = new Thread(CreateThreadContentionFromDispose); + t.Start(); + t.Join(20000); + + if (t.ThreadState == System.Threading.ThreadState.WaitSleepJoin) + Assert.Fail("Lock Contention Blocked Successful Dispose of ObjectFactory!"); + } + + [Test] + public void CanAvoidLockContentionDuringObjectInstantiation() + { + Thread t = new Thread(CreateThreadContentionFromConstructor); + t.Start(); + t.Join(20000); + + if (t.ThreadState == System.Threading.ThreadState.WaitSleepJoin) + Assert.Fail("Lock Contention Blocked Successful Instantiation of Singleton Test Object!"); + } + + public static AbstractObjectFactory CreateObjectFactory(bool caseSensitive) + { + return new DefaultListableObjectFactory(caseSensitive); + } + + private void CreateThreadContentionFromConstructor() + { + ObjectFactory.GetObject("threadCreatorInsideConstructor"); + } + + private void CreateThreadContentionFromDispose() + { + ObjectFactory.GetObject("threadCreatorInsideDispose"); + ObjectFactory.Dispose(); + } + + internal class ThreadCreatorInsideDispose : IDisposable + { + public ThreadCreatorInsideDispose() + { + } + + public void Dispose() + { + Thread t = new Thread(ConcurentThreadDisposeProc); + t.Start(); + t.Join(); + } + + private static void ConcurentThreadDisposeProc() + { + ObjectFactory.GetObject("threadCreatorInsideConstructor"); + } + } + + internal class ThreadCreatorInsideConstructor + { + public ThreadCreatorInsideConstructor() + { + Thread t = new Thread(ConcurentThreadProc); + t.Start(); + t.Join(); + } + + private static void ConcurentThreadProc() + { + ObjectFactory.GetObject("threadCreatorInsideDispose"); + } + } + + } } \ No newline at end of file