Skip to content

Commit

Permalink
cache added to FindContext
Browse files Browse the repository at this point in the history
  • Loading branch information
Saeed Barari committed Jul 28, 2023
1 parent ea220e9 commit 9bfd95e
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 78 deletions.
66 changes: 39 additions & 27 deletions BContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ public sealed class BContext : MonoBehaviour {


[NonSerialized] readonly List<IValueHolder> _structDependencies = new( 8 );
[NonSerialized] readonly HashSet<TypeHandle> _dependencyTypes = new( 16 );
[NonSerialized] bool _syncedDependencyTypes;
[NonSerialized] readonly HashSet<Type> _dependencyTypes = new( 16, new TypeComparer() );
[NonSerialized] bool _inited;
[NonSerialized] bool _addedToManager;

SceneHandle _lastSceneHandle;
Transform _lastParent;
int _lastSiblingIndex;

#if UNITY_EDITOR
/// <summary>
Expand Down Expand Up @@ -90,19 +92,20 @@ void OnValidate() {
Debug.LogWarning( $"Binject Context of {name} removed some dependencies:\n{sb}" );

// support in-editor injection
SyncDependencyTypesIfHaveNot();
SaveLastScene();
InitializeIfHaveNot();
AddToManagerIfNotAddedTo();
ReportSceneChangeOrRemoveFromManagerIfPossible();
ReportTransformHierarchyChangeIfPossible();
}

#endif

void Awake() {
_structDependencies.Clear();
ApplyAllSerializedStructs();
SyncDependencyTypesIfHaveNot();
InitializeIfHaveNot();
SaveLastScene();
SaveLastHierarchyState();
AddToManagerIfNotAddedTo();
}

Expand All @@ -111,11 +114,9 @@ void Awake() {
void OnDestroy() => RemoveFromManagerIfAddedTo();

void LateUpdate() {
#if UNITY_EDITOR
if (!Application.isPlaying) return;
#endif
// TODO: come up with a better way of handling scene-change
ReportSceneChangeOrRemoveFromManagerIfPossible();
ReportTransformHierarchyChangeIfPossible();
}


Expand All @@ -124,7 +125,7 @@ void LateUpdate() {
/// the old one.
/// </summary>
public void Bind<T>(T dependency) {
if (_dependencyTypes.Add( new( typeof(T) ))) {
if (_dependencyTypes.Add( typeof(T) )) {
// new type
if (typeof(T).IsValueType) {
_structDependencies.Add( new RealValueHolder<T>( dependency ) );
Expand Down Expand Up @@ -181,7 +182,7 @@ public void Bind<T>(T dependency) {
/// Unbinds a dependency from this context.
/// </summary>
public void Unbind<T>() {
if (_dependencyTypes.Remove( new( typeof(T) ))) {
if (_dependencyTypes.Remove( typeof(T) )) {
if (typeof(T).IsValueType) {
for (int i = 0; i < _structDependencies.Count; i++) {
if (_structDependencies[i].GetValueType() == typeof(T)) {
Expand Down Expand Up @@ -215,7 +216,7 @@ public void Unbind<T>() {
/// <summary>
/// Checks if this context has a dependency of type <see cref="T"/>
/// </summary>
public bool HasDependency<T>() => _dependencyTypes.Contains( new( typeof(T) ));
public bool HasDependency<T>() => _dependencyTypes.Contains( typeof(T) );

/// <summary>
/// Returns the dependency of type <see cref="T"/> if it exists, otherwise returns <c>default</c>.
Expand Down Expand Up @@ -249,6 +250,21 @@ internal void PopulateSerializedStructs() {
}


/// <summary>
/// updates manager to adapt for the new transform hierarchy change
/// </summary>
void ReportTransformHierarchyChangeIfPossible() {
if (transform.GetSiblingIndex() != _lastSiblingIndex || !ReferenceEquals( _lastParent, transform.parent )) {
BinjectManager.UpdateAllRootContextsAndTopmostScene();
SaveLastHierarchyState();
}
}

void SaveLastHierarchyState() {
_lastParent = transform.parent;
_lastSiblingIndex = transform.GetSiblingIndex();
}

/// <summary>
/// Reports scene change to <see cref="BinjectManager"/> if it happened, or removes this from it if it has
/// moved to an invalid scene.
Expand All @@ -264,6 +280,7 @@ void ReportSceneChangeOrRemoveFromManagerIfPossible() {
BinjectManager.UpdateContextScene( this, _lastSceneHandle );
}
SaveLastScene();
SaveLastHierarchyState();
}
}

Expand All @@ -290,10 +307,12 @@ void RemoveFromManagerIfAddedTo() {
}

[MethodImpl( MethodImplOptions.AggressiveInlining )]
void SyncDependencyTypesIfHaveNot() {
if (!_syncedDependencyTypes) {
void InitializeIfHaveNot() {
if (!_inited) {
SyncAllDependencyTypes( true );
_syncedDependencyTypes = true;
SaveLastHierarchyState();
SaveLastScene();
_inited = true;
}
}

Expand All @@ -313,11 +332,11 @@ void ApplyAllSerializedStructs() {
void SyncAllDependencyTypes(bool clear) {
if (clear) _dependencyTypes.Clear();
for (int i = 0; i < ClassDependencies.Count; i++)
_dependencyTypes.Add( new( ClassDependencies[i].GetType() ));
_dependencyTypes.Add( ClassDependencies[i].GetType() );
for (int i = 0; i < UnityObjectDependencies.Count; i++)
_dependencyTypes.Add( new( UnityObjectDependencies[i].GetType() ));
_dependencyTypes.Add( UnityObjectDependencies[i].GetType() );
for (int i = 0; i < _structDependencies.Count; i++)
_dependencyTypes.Add( new( _structDependencies[i].GetValueType() ));
_dependencyTypes.Add( _structDependencies[i].GetValueType() );
}

/// <summary>
Expand Down Expand Up @@ -360,15 +379,8 @@ bool TryFindDependency<T>(out T result) {
}


struct TypeHandle : IEquatable<TypeHandle> {
public IntPtr Value;

public TypeHandle(Type type) => Value = type.TypeHandle.Value;
public TypeHandle(IntPtr handle) => Value = handle;

public bool Equals(TypeHandle other) => Value == other.Value;
public override int GetHashCode() => Value.ToInt32();
public static bool operator ==(TypeHandle left, TypeHandle right) => left.Equals( right );
public static bool operator !=(TypeHandle left, TypeHandle right) => !left.Equals( right );
class TypeComparer : IEqualityComparer<Type> {
public bool Equals(Type x, Type y) => ReferenceEquals( x, y );
public int GetHashCode(Type obj) => obj.GetHashCode();
}
}
55 changes: 55 additions & 0 deletions BContextList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;

namespace Binject {
/// <summary>
/// A list specifically designed for <see cref="BinjectManager"/>. it holds a <see cref="RootIndex"/> and sorts
/// contexts by their use count.
/// </summary>
public class BContextList : List<BContext> {
public int RootIndex;
List<int> _points;
HashSet<Transform> _transforms;

public BContextList(int capacity) : base( capacity ) => Init();

void Init() {
_points = new( Capacity );
_transforms = new( Capacity, new ObjectReferenceEquality<Transform>() );
}

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public BContext GetRoot() => this[RootIndex];

public new void Add(BContext context) {
base.Add( context );
_points.Add( 0 );
_transforms.Add( context.transform );
}

public new bool Remove(BContext context) {
_points.RemoveAt( IndexOf( context ) );
_transforms.Remove( context.transform );
return base.Remove( context );
}

public bool ContainsTransform(Transform transform) => _transforms.Contains( transform );

public void AddPoint(int index) {
if (index == 0) return;
_points[index]++;
while (index > 0 && _points[index] > _points[index - 1]) {
(this[index], this[index - 1]) = (this[index - 1], this[index]);
(_points[index], _points[index - 1]) = (_points[index - 1], _points[index]);
index--;
}
}
}


class ObjectReferenceEquality<T> : IEqualityComparer<T> {
public bool Equals(T x, T y) => ReferenceEquals( x, y );
public int GetHashCode(T obj) => obj.GetHashCode();
}
}
3 changes: 3 additions & 0 deletions BContextList.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 9bfd95e

Please sign in to comment.