This commit is contained in:
Eugene Sadovoi 2019-06-09 21:17:21 -04:00
Родитель 9e6bf0fc4a
Коммит 7cd989876b
5 изменённых файлов: 146 добавлений и 70 удалений

Просмотреть файл

@ -136,7 +136,7 @@ namespace Unity
keyDefault = new HashKey(generic);
}
// Factory with the same name
// Generic Factory
targetBucket = keyGeneric.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
@ -144,11 +144,11 @@ namespace Unity
if (candidate.Key != keyGeneric)
continue;
// Found a factory
// Found a generic factory
return container.PipelineFromOpenGeneric(ref key, candidate.Registration);
}
// Default factory
// Default Factory
targetBucket = keyDefault.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
@ -156,9 +156,8 @@ namespace Unity
if (candidate.Key != keyDefault)
continue;
// Found a factory
var typeFactory = (TypeFactoryDelegate)candidate.Policies.Get(typeof(TypeFactoryDelegate));
return container.PipelineFromTypeFactory(ref key, container, typeFactory);
// Found a default
return container.PipelineFromTypeFactory(ref key, container, candidate.Policies);
}
}

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Threading;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Registration;
@ -18,10 +19,12 @@ namespace Unity
var type = key.Type;
var name = key.Name;
var owner = this;
bool AddNew = true;
bool adding = true;
int position = 0;
var collisions = 0;
LifetimeManager? manager = null;
ResolveDelegate<BuilderContext>? pipeline = null;
// Add Pipeline to the Registry
lock (_syncRegistry)
@ -39,17 +42,18 @@ namespace Unity
// Pipeline already been created
if (null != candidate.Pipeline) return candidate.Pipeline;
// Empty Registration with Policies
// Lifetime Manager
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
// Type has not been registered
if (null == candidate.Registration) candidate.Pipeline = manager.Pipeline;
AddNew = false;
adding = false;
break;
}
if (AddNew)
if (adding)
{
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
@ -58,8 +62,9 @@ namespace Unity
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create a Lifetime Manager
// Lifetime Manager
manager = factory.LifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
@ -75,10 +80,32 @@ namespace Unity
Debug.Assert(null != manager);
PipelineBuilder builder = new PipelineBuilder(key.Type, factory, manager, this);
manager.PipelineDelegate = builder.Pipeline();
lock (manager)
{
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
{
PipelineBuilder builder = new PipelineBuilder(key.Type, factory, manager, this);
manager.PipelineDelegate = builder.Pipeline();
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
}
}
return manager.Pipeline;
object? SpinWait(ref BuilderContext context)
{
while (null == pipeline)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
Thread.SpinWait(100);
#endif
}
return pipeline(ref context);
}
}
}
}

Просмотреть файл

@ -1,7 +1,7 @@
using System;
using System.Diagnostics;
using System.Threading;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Registration;
using Unity.Resolution;
using Unity.Storage;
@ -17,19 +17,46 @@ namespace Unity
var manager = registration.LifetimeManager;
ResolveDelegate<BuilderContext>? pipeline = null;
lock (_syncRegistry)
{
ref var entry = ref _registry.Entries[position];
if (ReferenceEquals(entry.Registration, registration)) entry.Pipeline = manager.Pipeline;
if (ReferenceEquals(entry.Registration, registration) && null == entry.Pipeline)
{
entry.Pipeline = manager.Pipeline;
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
}
}
if (null == manager.PipelineDelegate)
lock (manager)
{
PipelineBuilder builder = new PipelineBuilder(key.Type, registration);
manager.PipelineDelegate = builder.Pipeline();
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
{
PipelineBuilder builder = new PipelineBuilder(key.Type, registration);
manager.PipelineDelegate = builder.Pipeline();
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
}
}
return manager.Pipeline;
object? SpinWait(ref BuilderContext context)
{
while (null == pipeline)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
Thread.SpinWait(100);
#endif
}
return pipeline(ref context);
}
}
}
}

Просмотреть файл

@ -1,6 +1,9 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.Threading;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Policy;
using Unity.Resolution;
using Unity.Storage;
@ -8,7 +11,7 @@ namespace Unity
{
public partial class UnityContainer
{
private ResolveDelegate<BuilderContext> PipelineFromTypeFactory(ref HashKey key, UnityContainer container, TypeFactoryDelegate typeFactory)
private ResolveDelegate<BuilderContext> PipelineFromTypeFactory(ref HashKey key, UnityContainer container, IPolicySet set)
{
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
@ -17,10 +20,14 @@ namespace Unity
var name = key.Name;
var owner = this;
int count = -1;
int position = 0;
var collisions = 0;
bool adding = true;
LifetimeManager? manager = null;
ResolveDelegate<BuilderContext>? pipeline = null;
var typeFactory = (TypeFactoryDelegate)set.Get(typeof(TypeFactoryDelegate));
// Add Pipeline to the Registry
lock (_syncRegistry)
@ -35,39 +42,64 @@ namespace Unity
continue;
}
Debug.Assert(null != candidate.Pipeline);
// Pipeline already been created
if (null != candidate.Pipeline) return candidate.Pipeline;
// Has already been created
return candidate.Pipeline;
// Lifetime Manager
manager = (LifetimeManager)set.Get(typeof(LifetimeManager)) ??
Context.TypeLifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
// Type has not been registered
if (null == candidate.Registration) candidate.Pipeline = manager.Pipeline;
adding = false;
break;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
if (adding)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Pipeline = BuildPipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
// Lifetime Manager
manager = (LifetimeManager)set.Get(typeof(LifetimeManager)) ??
Context.TypeLifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Pipeline = manager.Pipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
}
}
// Return temporary pipeline
return BuildPipeline;
Debug.Assert(null != manager);
// Create pipeline and add to Registry
object? BuildPipeline(ref BuilderContext context)
lock (manager)
{
// Wait for right moment
while (0 != Interlocked.Increment(ref count))
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
{
manager.PipelineDelegate = typeFactory(type, this);
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
}
}
return manager.Pipeline;
object? SpinWait(ref BuilderContext context)
{
while (null == pipeline)
{
Interlocked.Decrement(ref count);
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
@ -75,22 +107,8 @@ namespace Unity
#endif
}
try
{
// Create if required
if (null == pipeline)
{
pipeline = typeFactory(type, container);
Debug.Assert(null != pipeline);
}
return pipeline(ref context);
}
finally
{
Interlocked.Decrement(ref count);
}
};
return pipeline(ref context);
}
}
}
}

Просмотреть файл

@ -20,7 +20,7 @@ namespace Unity
lock (_syncRegistry)
{
var AddNew = true;
var adding = true;
var collisions = 0;
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
@ -35,7 +35,7 @@ namespace Unity
// Pipeline already been created
if (null != existing.Pipeline) return existing.Pipeline;
// Empty Registration with Policies
// Lifetime Manager
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
@ -43,11 +43,11 @@ namespace Unity
if (null == existing.Registration) existing.Pipeline = manager.Pipeline;
// Skip to creation part
AddNew = false;
adding = false;
break;
}
if (AddNew)
if (adding)
{
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
@ -56,6 +56,7 @@ namespace Unity
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Lifetime Manager
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
@ -72,14 +73,18 @@ namespace Unity
Debug.Assert(null != manager);
PipelineBuilder builder = new PipelineBuilder(key.Type, this, Context.TypePipelineCache);
lock (manager)
{
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
{
PipelineBuilder builder = new PipelineBuilder(key.Type, this, Context.TypePipelineCache);
manager.PipelineDelegate = builder.Pipeline();
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
}
}
var newPipeline = builder.Pipeline();
return manager.Pipeline;
manager.PipelineDelegate = newPipeline;
pipeline = newPipeline;
return pipeline;
object? SpinWait(ref BuilderContext context)
{