Skip to content

Commit

Permalink
wip: optimizing Defaults
Browse files Browse the repository at this point in the history
Issue #301
  • Loading branch information
ENikS committed Dec 24, 2020
1 parent 572f2b0 commit b0d9ee0
Show file tree
Hide file tree
Showing 25 changed files with 502 additions and 454 deletions.
18 changes: 0 additions & 18 deletions src/BuiltIn/Components.cs

This file was deleted.

5 changes: 1 addition & 4 deletions src/BuiltIn/Factories/Pipeline.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection;
using Unity.Container;
using Unity.Extension;
using Unity.Lifetime;
using Unity.Storage;

namespace Unity
namespace Unity.BuiltIn
{
public static class PipelineFactory
{
Expand Down
42 changes: 0 additions & 42 deletions src/Container/Defaults/Defaults.Extensions.cs

This file was deleted.

165 changes: 29 additions & 136 deletions src/Container/Defaults/Defaults.Policies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,39 @@ namespace Unity.Container
{
public partial class Defaults
{
#region Policy Change Handler
#region Constants

public delegate void PolicyChangeHandler(Type? target, Type type, object? policy);
private static uint _resolverHash = (uint)typeof(ResolveDelegate<PipelineContext>).GetHashCode();

#endregion


#region Contains

public bool Contains(Type? target, Type type)
{
var hash = (uint)(((target?.GetHashCode() ?? 0) + 37) ^ type.GetHashCode());
var position = Meta[hash % Meta.Length].Position;

while (position > 0)
{
ref var candidate = ref Data[position];
if (ReferenceEquals(candidate.Target, target) &&
ReferenceEquals(candidate.Type, type))
{
// Found existing
return true;
}

position = Meta[position].Location;
}

return false;
}

#endregion


#region Allocate

/// <summary>
Expand Down Expand Up @@ -97,49 +123,6 @@ private int Allocate(Type? target, Type type)

#region Get Or Add

public TPolicy GetOrAdd<TPolicy>(TPolicy value, PolicyChangeHandler subscriber)
where TPolicy : class
{
if (value is null) throw new ArgumentNullException(nameof(value));
var hash = (uint)(37 ^ typeof(TPolicy).GetHashCode());

lock (_syncRoot)
{
ref var bucket = ref Meta[hash % Meta.Length];
var position = bucket.Position;

while (position > 0)
{
ref var candidate = ref Data[position];
if (candidate.Target is null && ReferenceEquals(candidate.Type, typeof(TPolicy)))
{
if (candidate.Value is null) candidate.Value = value;

candidate.PolicyChanged += subscriber;
return (TPolicy)candidate.Value;
}

position = Meta[position].Location;
}

if (++Count >= Data.Length)
{
Expand();
bucket = ref Meta[hash % Meta.Length];
}

// Add new
ref var entry = ref Data[Count];
entry = new Policy(hash, typeof(TPolicy), value);
entry.PolicyChanged += subscriber;

Meta[Count].Location = bucket.Position;
bucket.Position = Count;

return value;
}
}

/// <summary>
/// Adds pipeline, if does not exist already, or returns existing
/// </summary>
Expand Down Expand Up @@ -187,96 +170,6 @@ public ResolveDelegate<PipelineContext> GetOrAdd(Type? type, ResolveDelegate<Pip
#endregion


#region Subscribe

public TPolicy? Subscribe<TTarget, TPolicy>(PolicyChangeHandler subscriber)
{
var hash = (uint)((typeof(TTarget).GetHashCode() + 37) ^ typeof(TPolicy).GetHashCode());

lock (_syncRoot)
{
ref var bucket = ref Meta[hash % Meta.Length];
var position = bucket.Position;

while (position > 0)
{
ref var candidate = ref Data[position];
if (ReferenceEquals(candidate.Target, typeof(TTarget)) &&
ReferenceEquals(candidate.Type, typeof(TPolicy)))
{
// Found existing
candidate.PolicyChanged += subscriber;
return (TPolicy)candidate.Value;
}

position = Meta[position].Location;
}

if (++Count >= Data.Length)
{
Expand();
bucket = ref Meta[hash % Meta.Length];
}

// Allocate placeholder
ref var entry = ref Data[Count];
entry = new Policy(hash, typeof(TTarget), typeof(TPolicy), default);
entry.PolicyChanged += subscriber;
Meta[Count].Location = bucket.Position;
bucket.Position = Count;
return default;
}
}

public TPolicy? Subscribe<TPolicy>(PolicyChangeHandler subscriber)
{
var hash = (uint)(37 ^ typeof(TPolicy).GetHashCode());

lock (_syncRoot)
{
ref var bucket = ref Meta[hash % Meta.Length];
var position = bucket.Position;

while (position > 0)
{
ref var candidate = ref Data[position];
if (candidate.Target is null && ReferenceEquals(candidate.Type, typeof(TPolicy)))
{
// Found existing
candidate.PolicyChanged += subscriber;
return (TPolicy)candidate.Value;
}

position = Meta[position].Location;
}

if (++Count >= Data.Length)
{
Expand();
bucket = ref Meta[hash % Meta.Length];
}

// Allocate placeholder
ref var entry = ref Data[Count];
entry = new Policy(hash, null, typeof(TPolicy), default);
entry.PolicyChanged += subscriber;
Meta[Count].Location = bucket.Position;
bucket.Position = Count;
return default;
}
}

#endregion


#region Span

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal ReadOnlySpan<Policy> Span => new ReadOnlySpan<Policy>(Data, 1, Count);

#endregion


#region Implementation

protected virtual void Expand()
Expand All @@ -295,7 +188,7 @@ protected virtual void Expand()
#endregion


#region Policy structure
#region Nested Policy

[DebuggerDisplay("Policy = { Type?.Name }", Name = "{ Target?.Name }")]
[CLSCompliant(false)]
Expand Down
79 changes: 79 additions & 0 deletions src/Container/Defaults/Defaults.PolicyObservable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using Unity.Extension;

namespace Unity.Container
{
public partial class Defaults : IPolicyObservable
{
public object? Get(Type? target, Type type, PolicyChangeHandler handler)
{
var hash = (uint)(((target?.GetHashCode() ?? 0) + 37) ^ type.GetHashCode());

ref var bucket = ref Meta[hash % Meta.Length];
var position = bucket.Position;

while (position > 0)
{
ref var candidate = ref Data[position];
if (ReferenceEquals(candidate.Target, target) &&
ReferenceEquals(candidate.Type, type))
{
// Found existing
candidate.PolicyChanged += handler;
return candidate.Value;
}

position = Meta[position].Location;
}

if (++Count >= Data.Length)
{
Expand();
bucket = ref Meta[hash % Meta.Length];
}

// Allocate placeholder
ref var entry = ref Data[Count];
entry = new Policy(hash, target, type, default);
entry.PolicyChanged += handler;
Meta[Count].Location = bucket.Position;
bucket.Position = Count;
return default;
}

public void Set(Type? target, Type type, object policy, PolicyChangeHandler handler)
{
var hash = (uint)(((target?.GetHashCode() ?? 0) + 37) ^ type.GetHashCode());

lock (_syncRoot)
{
ref var bucket = ref Meta[hash % Meta.Length];
var position = bucket.Position;

while (position > 0)
{
ref var candidate = ref Data[position];
if (ReferenceEquals(candidate.Target, target) &&
ReferenceEquals(candidate.Type, type))
{
// Found existing
if (candidate.Value is null) candidate.Value = policy;
}

position = Meta[position].Location;
}

if (++Count >= Data.Length)
{
Expand();
bucket = ref Meta[hash % Meta.Length];
}

// Add new registration
Data[Count] = new Policy(hash, target, type, policy);
Meta[Count].Location = bucket.Position;
bucket.Position = Count;
}
}
}
}
7 changes: 0 additions & 7 deletions src/Container/Defaults/Defaults.PolicySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ namespace Unity.Container
{
public partial class Defaults : IPolicySet
{
#region Constants

private static uint _resolverHash = (uint)typeof(ResolveDelegate<PipelineContext>).GetHashCode();

#endregion


///<inheritdoc/>
public void Clear(Type type) => throw new NotSupportedException();

Expand Down
8 changes: 8 additions & 0 deletions src/Container/Defaults/Defaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,13 @@ internal Defaults()
}

#endregion


#region Properties

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal ReadOnlySpan<Policy> Span => new ReadOnlySpan<Policy>(Data, 1, Count);

#endregion
}
}
Loading

0 comments on commit b0d9ee0

Please sign in to comment.