Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions rd-net/Lifetimes/Lifetimes/Lifetime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,42 @@ public enum LifetimeTerminationTimeoutKind
{

private readonly LifetimeDefinition? myDefinition;
internal LifetimeDefinition Definition => myDefinition ?? LifetimeDefinition.Eternal;

internal LifetimeDefinition Definition
{
get
{
var def = myDefinition;
if (def != null) return def;

Assertion.Assert(IsUninitialized);

AssertInitialized();
return LifetimeDefinition.Eternal;
}
}

internal void AssertInitialized()
{
if (!Mode.IsAssertion) return;

if (LogErrorIfLifetimeIsNotInitialized && IsUninitialized)
{
Log.Root.Error("Lifetime is not initialized. " +
"This may cause a memory leak as default(Lifetime) is treated as Eternal. " +
"Please provide a properly initialized Lifetime or use `Lifetime?` if you need to handle both cases. " +
"Use Lifetime.Eternal explicitly if that behavior is intended.");
}
}

//ctor
internal Lifetime(LifetimeDefinition definition)
{
myDefinition = definition;
}

[PublicAPI]
public static bool LogErrorIfLifetimeIsNotInitialized = true;


#if !NET35
/// <summary>
Expand Down Expand Up @@ -147,6 +175,17 @@ internal Lifetime(LifetimeDefinition definition)
/// Whether current lifetime is equal to <see cref="Eternal"/> and never be terminated
/// </summary>
[PublicAPI] public bool IsEternal => Definition.IsEternal;


/// <summary>
/// Whether current lifetime is not properly initialized (created by default(Lifetime))
/// </summary>
[PublicAPI] public bool IsUninitialized => !IsInitialized;

/// <summary>
/// Whether current lifetime is properly initialized
/// </summary>
[PublicAPI] public bool IsInitialized => myDefinition != null;

/// <summary>
/// Is <see cref="Status"/> of this lifetime equal to <see cref="LifetimeStatus.Alive"/>
Expand Down
11 changes: 8 additions & 3 deletions rd-net/Lifetimes/Lifetimes/LifetimeDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,16 +460,21 @@ public void Terminate()
+ "This may happen either because of the ExecuteIfAlive failed to complete in a timely manner. In the case there will be following error messages." + Environment.NewLine
+ "This is also possible if the thread waiting for the termination wasn't able to receive execution time during the wait in SpinWait.spinUntil, so it has missed the fact that the lifetime was terminated in time.");

ourLogErrorAfterExecution.InterlockedUpdate(ref myState, true);
#if !NET35
if (AdditionalDiagnostics is { } additionalDiagnostics)
{
Log.Catch(() =>
try
{
ourAdditionalDiagnosticsStorage.AddData(this, additionalDiagnostics.GetAdditionalDiagnosticsIfExecutionWasNotCancelledByTimeoutAsync(Lifetime));
});
}
catch (Exception e)
{
Log.Error(e);
}
}
#endif

ourLogErrorAfterExecution.InterlockedUpdate(ref myState, true);
}

if (!IncrementStatusIfEqualsTo(LifetimeStatus.Canceling))
Expand Down
4 changes: 3 additions & 1 deletion rd-net/Lifetimes/Lifetimes/ValueLifetimed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ public void Deconstruct(out Lifetime lifetime, out T? value)

public ValueLifetimed(Lifetime lifetime, T value)
{
lifetime.AssertInitialized();

Lifetime = lifetime;
Value = value;
}

public void ClearValueIfNotAlive()
{
if (!Lifetime.IsAlive)
if (Lifetime is { IsInitialized: true, IsAlive: false })
Value = default(T);
}
}
Expand Down
25 changes: 17 additions & 8 deletions rd-net/Test.Lifetimes/Lifetimes/LifetimeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,25 @@ public void TestEternal()
[Test]
public void TestEquals()
{
Lifetime eternal = default;
Assert.AreEqual(Lifetime.Eternal, eternal);
Assert.AreEqual(Lifetime.Eternal, Lifetime.Eternal);
Assert.AreEqual(eternal, eternal);
var old = Lifetime.LogErrorIfLifetimeIsNotInitialized;
Lifetime.LogErrorIfLifetimeIsNotInitialized = false;
try
{
Lifetime eternal = default;
Assert.AreEqual(Lifetime.Eternal, eternal);
Assert.AreEqual(Lifetime.Eternal, Lifetime.Eternal);
Assert.AreEqual(eternal, eternal);

Assert.True(Lifetime.Eternal == eternal);
Assert.True(Lifetime.Eternal == eternal);

Assert.AreNotEqual(Lifetime.Eternal, Lifetime.Terminated);
Assert.False(Lifetime.Eternal == Lifetime.Terminated);
Assert.False(eternal == Lifetime.Terminated);
Assert.AreNotEqual(Lifetime.Eternal, Lifetime.Terminated);
Assert.False(Lifetime.Eternal == Lifetime.Terminated);
Assert.False(eternal == Lifetime.Terminated);
}
finally
{
Lifetime.LogErrorIfLifetimeIsNotInitialized = old;
}
}

[Test]
Expand Down