Skip to content

Commit

Permalink
Some hot fixes of possible memory leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
CrackAndDie committed May 7, 2024
1 parent 63beb19 commit a18c7a0
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Hypocrite.Avalonia/Hypocrite.Avalonia.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageDescription>A powerful base for Mvvm apps with Prism</PackageDescription>
<Copyright>Copyright © 2023</Copyright>
<PackageTags>Prism Mvvm DI Reactive</PackageTags>
<PackageVersion>1.2.7</PackageVersion>
<PackageVersion>1.2.9</PackageVersion>
<PackageProjectUrl>https://github.com/CrackAndDie/Hypocrite.Services</PackageProjectUrl>
<RepositoryUrl>https://github.com/CrackAndDie/Hypocrite.Services</RepositoryUrl>
<PackageIconUrl>https://raw.githubusercontent.com/CADindustries/container/main/logos/AbdrakovSolutions.png</PackageIconUrl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ public object CreateInstance(IContainerRegistration registration, bool withInjec
object instance = CreatePureInstance(registration);

if (withInjections && registration.MemberInjectionInfo.RequireInjection)
ResolveInjections(instance, registration.MemberInjectionInfo);
{
ResolveInjections(instance, registration.MemberInjectionInfo);
registration.MemberInjectionInfo.IsInjected = true;
}

return instance;
}
Expand Down
51 changes: 29 additions & 22 deletions Hypocrite.Core/Reactive/Observable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,48 @@ namespace Hypocrite.Core.Reactive
{
public class Observable<T> : IObservable<T>, IDisposable
{
private IDictionary<int, IObserver<T>> subscribers = new Dictionary<int, IObserver<T>>();
private readonly object thisLock = new object();
private int key;
private bool isDisposed;
private readonly IDictionary<int, IObserver<T>> _subscribers = new Dictionary<int, IObserver<T>>();
private readonly object _thisLock = new object();
private int _key;
private bool _isDisposed;

public void Dispose()
{
Dispose(true);
}
// подавляем финализацию
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (disposing && !isDisposed)
if (disposing && !_isDisposed)
{
OnCompleted();
isDisposed = true;
_isDisposed = true;
}
}

protected void OnNext(T value)
~Observable()
{
Dispose(false);
}

protected void OnNext(T value)
{
if (isDisposed)
if (_isDisposed)
{
throw new ObjectDisposedException("Observable<T>");
}

foreach (IObserver<T> observer in subscribers.Select(kv => kv.Value))
foreach (IObserver<T> observer in _subscribers.Select(kv => kv.Value))
{
observer.OnNext(value);
}
}

protected void OnError(Exception exception)
{
if (isDisposed)
if (_isDisposed)
{
throw new ObjectDisposedException("Observable<T>");
}
Expand All @@ -51,20 +58,20 @@ protected void OnError(Exception exception)
throw new ArgumentNullException(nameof(exception));
}

foreach (IObserver<T> observer in subscribers.Select(kv => kv.Value))
foreach (IObserver<T> observer in _subscribers.Select(kv => kv.Value))
{
observer.OnError(exception);
}
}

protected void OnCompleted()
{
if (isDisposed)
if (_isDisposed)
{
return;
}

foreach (IObserver<T> observer in subscribers.Select(kv => kv.Value))
foreach (IObserver<T> observer in _subscribers.Select(kv => kv.Value))
{
observer.OnCompleted();
}
Expand All @@ -77,18 +84,18 @@ public IDisposable Subscribe(IObserver<T> observer)
throw new ArgumentNullException(nameof(observer));
}

lock (thisLock)
lock (_thisLock)
{
int k = key++;
subscribers.Add(k, observer);
int k = _key++;
_subscribers.Add(k, observer);

OnSubscribed(observer);

return new AnonymousDisposable(() =>
{
lock (thisLock)
lock (_thisLock)
{
subscribers.Remove(k);
_subscribers.Remove(k);
}
});
}
Expand All @@ -99,16 +106,16 @@ public IDisposable Subscribe(IObserver<T> observer)

class AnonymousDisposable : IDisposable
{
readonly Action dispose;
readonly Action _dispose;

public AnonymousDisposable(Action dispose)
{
this.dispose = dispose;
this._dispose = dispose;
}

public void Dispose()
{
dispose();
_dispose();
}
}
}
16 changes: 14 additions & 2 deletions Hypocrite.Core/Reactive/PropertyChangedObservable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ internal class PropertyChangedObservable<T> : Observable<T>
private readonly bool _onChanged;
private readonly bool _initialCall;

public PropertyChangedObservable(BindableObject bindable, PropertyInfo property, bool initialCall, bool onChanged = true)
private bool _isDisposed = false;

public PropertyChangedObservable(BindableObject bindable, PropertyInfo property, bool initialCall, bool onChanged = true)
{
_onChanged = onChanged;
_initialCall = initialCall;
Expand Down Expand Up @@ -67,12 +69,22 @@ protected override void OnSubscribed(IObserver<T> observer)

protected override void Dispose(bool disposing)
{
if (_isDisposed)
return;

if (_onChanged)
_bindable.PropertyChanged -= Preparer;
else
_bindable.PropertyChanging -= Preparer;

base.Dispose(disposing);

_isDisposed = true;
}

~PropertyChangedObservable()
{
Dispose(false);
}
}
}
}
19 changes: 15 additions & 4 deletions Hypocrite.Core/Reactive/PropertySetObservable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ internal class PropertySetObservable<T> : Observable<T>
private readonly PropertyInfo _property;
private readonly bool _onSet;
private readonly bool _initialCall;
private bool _isDisposed = false;

public PropertySetObservable(BindableObject bindable, PropertyInfo property, bool initialCall, bool onSet = true)
public PropertySetObservable(BindableObject bindable, PropertyInfo property, bool initialCall, bool onSet = true)
{
_onSet = onSet;
_initialCall = initialCall;
Expand Down Expand Up @@ -67,12 +68,22 @@ protected override void OnSubscribed(IObserver<T> observer)

protected override void Dispose(bool disposing)
{
if (_onSet)
if (_isDisposed)
return;

if (_onSet)
_bindable.PropertySet -= Preparer;
else
_bindable.PropertySetting -= Preparer;

base.Dispose(disposing);
}
}

_isDisposed = true;
}

~PropertySetObservable()
{
Dispose(false);
}
}
}
2 changes: 1 addition & 1 deletion Hypocrite.Wpf/Hypocrite.Wpf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<PackageDescription>A powerful base for Mvvm apps with Prism</PackageDescription>
<Copyright>Copyright © 2023</Copyright>
<PackageTags>Prism Mvvm DI Reactive</PackageTags>
<PackageVersion>1.2.7</PackageVersion>
<PackageVersion>1.2.9</PackageVersion>
<PackageProjectUrl>https://github.com/CrackAndDie/Hypocrite.Services</PackageProjectUrl>
<RepositoryUrl>https://github.com/CrackAndDie/Hypocrite.Services</RepositoryUrl>
<PackageIconUrl>https://raw.githubusercontent.com/CADindustries/container/main/logos/AbdrakovSolutions.png</PackageIconUrl>
Expand Down

0 comments on commit a18c7a0

Please sign in to comment.